@mapwhit/tilerenderer 0.47.1 → 0.47.2
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/build/min/package.json +1 -1
- package/package.json +1 -2
- package/src/data/array_types.js +1 -1
- package/src/data/bucket/circle_bucket.js +1 -1
- package/src/data/bucket/fill_bucket.js +1 -1
- package/src/data/bucket/fill_extrusion_bucket.js +1 -1
- package/src/data/bucket/heatmap_bucket.js +1 -1
- package/src/data/bucket/line_bucket.js +1 -1
- package/src/data/bucket/symbol_bucket.js +1 -1
- package/src/data/dem_data.js +1 -1
- package/src/data/feature_index.js +43 -82
- package/src/data/program_configuration.js +1 -1
- package/src/data/segment.js +2 -2
- package/src/gl/color_mode.js +6 -6
- package/src/index.js +2 -0
- package/src/render/glyph_atlas.js +1 -1
- package/src/render/glyph_manager.js +43 -48
- package/src/render/image_atlas.js +1 -1
- package/src/render/image_manager.js +9 -37
- package/src/source/geojson_source.js +49 -93
- package/src/source/geojson_worker_source.js +33 -134
- package/src/source/image_source.js +9 -14
- package/src/source/load_tilejson.js +27 -34
- package/src/source/raster_dem_tile_source.js +27 -40
- package/src/source/raster_tile_source.js +53 -62
- package/src/source/rtl_text_plugin.js +2 -1
- package/src/source/source_cache.js +22 -20
- package/src/source/source_state.js +17 -26
- package/src/source/tile_id.js +1 -1
- package/src/source/vector_tile_source.js +56 -73
- package/src/source/vector_tile_worker_source.js +20 -85
- package/src/source/worker.js +38 -95
- package/src/source/worker_tile.js +39 -84
- package/src/style/load_sprite.js +14 -17
- package/src/style/properties.js +1 -1
- package/src/style/style.js +22 -22
- package/src/style/style_layer_index.js +17 -23
- package/src/style-spec/reference/v8.json +2 -2
- package/src/symbol/anchor.js +1 -1
- package/src/symbol/collision_index.js +23 -16
- package/src/symbol/grid_index.js +176 -182
- package/src/symbol/mergelines.js +48 -48
- package/src/symbol/opacity_state.js +1 -1
- package/src/ui/camera.js +82 -85
- package/src/ui/map.js +5 -32
- package/src/util/actor.js +46 -42
- package/src/util/browser.js +6 -0
- package/src/util/dictionary_coder.js +13 -21
- package/src/util/dispatcher.js +14 -17
- package/src/util/image.js +1 -1
- package/src/util/loader/image.js +11 -11
- package/src/util/polyfill.js +16 -0
- package/src/util/task_queue.js +39 -43
- package/src/util/transfer_registry.js +167 -0
- package/src/util/web_worker_transfer.js +5 -190
- package/src/source/raster_dem_tile_worker_source.js +0 -26
package/src/ui/camera.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const {
|
|
1
|
+
const { deepEqual } = require('../util/object');
|
|
2
2
|
const { clamp, wrap, ease: defaultEasing } = require('../util/util');
|
|
3
3
|
const warn = require('../util/warn');
|
|
4
4
|
const interpolate = require('../util/interpolate');
|
|
@@ -53,8 +53,6 @@ class Camera extends Evented {
|
|
|
53
53
|
this._zooming = false;
|
|
54
54
|
this.transform = transform;
|
|
55
55
|
this._bearingSnap = options.bearingSnap;
|
|
56
|
-
|
|
57
|
-
bindAll(['_renderFrameCallback'], this);
|
|
58
56
|
}
|
|
59
57
|
|
|
60
58
|
/**
|
|
@@ -96,9 +94,9 @@ class Camera extends Evented {
|
|
|
96
94
|
* @returns {Map} `this`
|
|
97
95
|
* @see [Navigate the map with game-like controls](https://www.mapbox.com/mapbox-gl-js/example/game-controls/)
|
|
98
96
|
*/
|
|
99
|
-
panBy(offset, options, eventData) {
|
|
97
|
+
panBy(offset, options = {}, eventData) {
|
|
100
98
|
offset = Point.convert(offset).mult(-1);
|
|
101
|
-
return this.panTo(this.transform.center,
|
|
99
|
+
return this.panTo(this.transform.center, { offset, ...options }, eventData);
|
|
102
100
|
}
|
|
103
101
|
|
|
104
102
|
/**
|
|
@@ -112,16 +110,8 @@ class Camera extends Evented {
|
|
|
112
110
|
* @fires moveend
|
|
113
111
|
* @returns {Map} `this`
|
|
114
112
|
*/
|
|
115
|
-
panTo(lnglat, options, eventData) {
|
|
116
|
-
return this.easeTo(
|
|
117
|
-
Object.assign(
|
|
118
|
-
{
|
|
119
|
-
center: lnglat
|
|
120
|
-
},
|
|
121
|
-
options
|
|
122
|
-
),
|
|
123
|
-
eventData
|
|
124
|
-
);
|
|
113
|
+
panTo(lnglat, options = {}, eventData) {
|
|
114
|
+
return this.easeTo({ center: lnglat, ...options }, eventData);
|
|
125
115
|
}
|
|
126
116
|
|
|
127
117
|
/**
|
|
@@ -171,16 +161,8 @@ class Camera extends Evented {
|
|
|
171
161
|
* @fires zoomend
|
|
172
162
|
* @returns {Map} `this`
|
|
173
163
|
*/
|
|
174
|
-
zoomTo(zoom, options, eventData) {
|
|
175
|
-
return this.easeTo(
|
|
176
|
-
Object.assign(
|
|
177
|
-
{
|
|
178
|
-
zoom: zoom
|
|
179
|
-
},
|
|
180
|
-
options
|
|
181
|
-
),
|
|
182
|
-
eventData
|
|
183
|
-
);
|
|
164
|
+
zoomTo(zoom, options = {}, eventData) {
|
|
165
|
+
return this.easeTo({ zoom, ...options }, eventData);
|
|
184
166
|
}
|
|
185
167
|
|
|
186
168
|
/**
|
|
@@ -266,16 +248,8 @@ class Camera extends Evented {
|
|
|
266
248
|
* @fires moveend
|
|
267
249
|
* @returns {Map} `this`
|
|
268
250
|
*/
|
|
269
|
-
rotateTo(bearing, options, eventData) {
|
|
270
|
-
return this.easeTo(
|
|
271
|
-
Object.assign(
|
|
272
|
-
{
|
|
273
|
-
bearing: bearing
|
|
274
|
-
},
|
|
275
|
-
options
|
|
276
|
-
),
|
|
277
|
-
eventData
|
|
278
|
-
);
|
|
251
|
+
rotateTo(bearing, options = {}, eventData) {
|
|
252
|
+
return this.easeTo({ bearing, ...options }, eventData);
|
|
279
253
|
}
|
|
280
254
|
|
|
281
255
|
/**
|
|
@@ -288,8 +262,8 @@ class Camera extends Evented {
|
|
|
288
262
|
* @fires moveend
|
|
289
263
|
* @returns {Map} `this`
|
|
290
264
|
*/
|
|
291
|
-
resetNorth(options, eventData) {
|
|
292
|
-
this.rotateTo(0,
|
|
265
|
+
resetNorth(options = {}, eventData) {
|
|
266
|
+
this.rotateTo(0, { duration: 1000, ...options }, eventData);
|
|
293
267
|
return this;
|
|
294
268
|
}
|
|
295
269
|
|
|
@@ -338,45 +312,35 @@ class Camera extends Evented {
|
|
|
338
312
|
}
|
|
339
313
|
|
|
340
314
|
/**
|
|
341
|
-
* Pans and zooms the map to contain its visible area within the specified geographical bounds.
|
|
342
|
-
* This function will also reset the map's bearing to 0 if bearing is nonzero.
|
|
343
|
-
*
|
|
344
315
|
* @memberof Map#
|
|
345
|
-
* @param bounds
|
|
346
|
-
* zoom level up to and including `Map#getMaxZoom()` that fits
|
|
316
|
+
* @param bounds Calculate the center for these bounds in the viewport and use
|
|
317
|
+
* the highest zoom level up to and including `Map#getMaxZoom()` that fits
|
|
318
|
+
* in the viewport.
|
|
347
319
|
* @param options
|
|
348
320
|
* @param {number | PaddingOptions} [options.padding] The amount of padding in pixels to add to the given bounds.
|
|
349
|
-
* @param {boolean} [options.linear=false] If `true`, the map transitions using
|
|
350
|
-
* {@link Map#easeTo}. If `false`, the map transitions using {@link Map#flyTo}. See
|
|
351
|
-
* those functions and {@link AnimationOptions} for information about options available.
|
|
352
|
-
* @param {Function} [options.easing] An easing function for the animated transition. See {@link AnimationOptions}.
|
|
353
321
|
* @param {PointLike} [options.offset=[0, 0]] The center of the given bounds relative to the map's center, measured in pixels.
|
|
354
|
-
* @param {number} [options.maxZoom] The maximum zoom level to allow when the
|
|
355
|
-
* @
|
|
356
|
-
*
|
|
357
|
-
*
|
|
358
|
-
* @returns {Map} `this`
|
|
322
|
+
* @param {number} [options.maxZoom] The maximum zoom level to allow when the camera would transition to the specified bounds.
|
|
323
|
+
* @returns {CameraOptions | void} If map is able to fit to provided bounds, returns `CameraOptions` with
|
|
324
|
+
* at least `center`, `zoom`, `bearing`, `offset`, `padding`, and `maxZoom`, as well as any other
|
|
325
|
+
* `options` provided in arguments. If map is unable to fit, method will warn and return undefined.
|
|
359
326
|
* @example
|
|
360
327
|
* var bbox = [[-79, 43], [-73, 45]];
|
|
361
|
-
* map.
|
|
328
|
+
* var newCameraTransform = map.cameraForBounds(bbox, {
|
|
362
329
|
* padding: {top: 10, bottom:25, left: 15, right: 5}
|
|
363
330
|
* });
|
|
364
|
-
* @see [Fit a map to a bounding box](https://www.mapbox.com/mapbox-gl-js/example/fitbounds/)
|
|
365
331
|
*/
|
|
366
|
-
|
|
367
|
-
options =
|
|
368
|
-
{
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
left: 0
|
|
374
|
-
},
|
|
375
|
-
offset: [0, 0],
|
|
376
|
-
maxZoom: this.transform.maxZoom
|
|
332
|
+
cameraForBounds(bounds, options) {
|
|
333
|
+
options = {
|
|
334
|
+
padding: {
|
|
335
|
+
top: 0,
|
|
336
|
+
bottom: 0,
|
|
337
|
+
right: 0,
|
|
338
|
+
left: 0
|
|
377
339
|
},
|
|
378
|
-
|
|
379
|
-
|
|
340
|
+
offset: [0, 0],
|
|
341
|
+
maxZoom: this.transform.maxZoom,
|
|
342
|
+
...options
|
|
343
|
+
};
|
|
380
344
|
|
|
381
345
|
if (typeof options.padding === 'number') {
|
|
382
346
|
const p = options.padding;
|
|
@@ -398,7 +362,7 @@ class Camera extends Evented {
|
|
|
398
362
|
)
|
|
399
363
|
) {
|
|
400
364
|
warn.once("options.padding must be a positive number, or an Object with keys 'bottom', 'left', 'right', 'top'");
|
|
401
|
-
return
|
|
365
|
+
return;
|
|
402
366
|
}
|
|
403
367
|
|
|
404
368
|
bounds = LngLatBounds.convert(bounds);
|
|
@@ -425,13 +389,50 @@ class Camera extends Evented {
|
|
|
425
389
|
|
|
426
390
|
if (scaleY < 0 || scaleX < 0) {
|
|
427
391
|
warn.once('Map cannot fit within canvas with the given bounds, padding, and/or offset.');
|
|
428
|
-
return
|
|
392
|
+
return;
|
|
429
393
|
}
|
|
430
394
|
|
|
431
395
|
options.center = tr.unproject(nw.add(se).div(2));
|
|
432
396
|
options.zoom = Math.min(tr.scaleZoom(tr.scale * Math.min(scaleX, scaleY)), options.maxZoom);
|
|
433
397
|
options.bearing = 0;
|
|
434
398
|
|
|
399
|
+
return options;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
/**
|
|
403
|
+
* Pans and zooms the map to contain its visible area within the specified geographical bounds.
|
|
404
|
+
* This function will also reset the map's bearing to 0 if bearing is nonzero.
|
|
405
|
+
*
|
|
406
|
+
* @memberof Map#
|
|
407
|
+
* @param bounds Center these bounds in the viewport and use the highest
|
|
408
|
+
* zoom level up to and including `Map#getMaxZoom()` that fits them in the viewport.
|
|
409
|
+
* @param options
|
|
410
|
+
* @param {number | PaddingOptions} [options.padding] The amount of padding in pixels to add to the given bounds.
|
|
411
|
+
* @param {boolean} [options.linear=false] If `true`, the map transitions using
|
|
412
|
+
* {@link Map#easeTo}. If `false`, the map transitions using {@link Map#flyTo}. See
|
|
413
|
+
* those functions and {@link AnimationOptions} for information about options available.
|
|
414
|
+
* @param {Function} [options.easing] An easing function for the animated transition. See {@link AnimationOptions}.
|
|
415
|
+
* @param {PointLike} [options.offset=[0, 0]] The center of the given bounds relative to the map's center, measured in pixels.
|
|
416
|
+
* @param {number} [options.maxZoom] The maximum zoom level to allow when the map view transitions to the specified bounds.
|
|
417
|
+
* @param eventData Additional properties to be added to event objects of events triggered by this method.
|
|
418
|
+
* @fires movestart
|
|
419
|
+
* @fires moveend
|
|
420
|
+
* @returns {Map} `this`
|
|
421
|
+
* @example
|
|
422
|
+
* var bbox = [[-79, 43], [-73, 45]];
|
|
423
|
+
* map.fitBounds(bbox, {
|
|
424
|
+
* padding: {top: 10, bottom:25, left: 15, right: 5}
|
|
425
|
+
* });
|
|
426
|
+
* @see [Fit a map to a bounding box](https://www.mapbox.com/mapbox-gl-js/example/fitbounds/)
|
|
427
|
+
*/
|
|
428
|
+
fitBounds(bounds, options, eventData) {
|
|
429
|
+
const calculatedOptions = this.cameraForBounds(bounds, options);
|
|
430
|
+
|
|
431
|
+
// cameraForBounds warns + returns undefined if unable to fit:
|
|
432
|
+
if (!calculatedOptions) return this;
|
|
433
|
+
|
|
434
|
+
options = Object.assign(calculatedOptions, options);
|
|
435
|
+
|
|
435
436
|
return options.linear
|
|
436
437
|
? this.easeTo(options, eventData)
|
|
437
438
|
: options.animate === false
|
|
@@ -534,14 +535,12 @@ class Camera extends Evented {
|
|
|
534
535
|
easeTo(options, eventData) {
|
|
535
536
|
this.stop();
|
|
536
537
|
|
|
537
|
-
options =
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
options
|
|
544
|
-
);
|
|
538
|
+
options = {
|
|
539
|
+
offset: [0, 0],
|
|
540
|
+
duration: 500,
|
|
541
|
+
easing: defaultEasing,
|
|
542
|
+
...options
|
|
543
|
+
};
|
|
545
544
|
|
|
546
545
|
if (options.animate === false) options.duration = 0;
|
|
547
546
|
|
|
@@ -732,15 +731,13 @@ class Camera extends Evented {
|
|
|
732
731
|
|
|
733
732
|
this.stop();
|
|
734
733
|
|
|
735
|
-
options =
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
options
|
|
743
|
-
);
|
|
734
|
+
options = {
|
|
735
|
+
offset: [0, 0],
|
|
736
|
+
speed: 1.2,
|
|
737
|
+
curve: 1.42,
|
|
738
|
+
easing: defaultEasing,
|
|
739
|
+
...options
|
|
740
|
+
};
|
|
744
741
|
|
|
745
742
|
const tr = this.transform;
|
|
746
743
|
const startZoom = this.getZoom();
|
package/src/ui/map.js
CHANGED
|
@@ -16,7 +16,7 @@ const LngLatBounds = require('../geo/lng_lat_bounds');
|
|
|
16
16
|
const Point = require('@mapbox/point-geometry');
|
|
17
17
|
const { RGBAImage } = require('../util/image');
|
|
18
18
|
const { Event, ErrorEvent } = require('../util/evented');
|
|
19
|
-
const
|
|
19
|
+
const taskQueue = require('../util/task_queue');
|
|
20
20
|
|
|
21
21
|
const defaultMinZoom = 0;
|
|
22
22
|
const defaultMaxZoom = 22;
|
|
@@ -134,36 +134,6 @@ const defaultOptions = {
|
|
|
134
134
|
* @see [Display a map](https://www.mapbox.com/mapbox-gl-js/examples/)
|
|
135
135
|
*/
|
|
136
136
|
class Map extends Camera {
|
|
137
|
-
/**
|
|
138
|
-
* The map's {@link ScrollZoomHandler}, which implements zooming in and out with a scroll wheel or trackpad.
|
|
139
|
-
*/
|
|
140
|
-
|
|
141
|
-
/**
|
|
142
|
-
* The map's {@link BoxZoomHandler}, which implements zooming using a drag gesture with the Shift key pressed.
|
|
143
|
-
*/
|
|
144
|
-
|
|
145
|
-
/**
|
|
146
|
-
* The map's {@link DragRotateHandler}, which implements rotating the map while dragging with the right
|
|
147
|
-
* mouse button or with the Control key pressed.
|
|
148
|
-
*/
|
|
149
|
-
|
|
150
|
-
/**
|
|
151
|
-
* The map's {@link DragPanHandler}, which implements dragging the map with a mouse or touch gesture.
|
|
152
|
-
*/
|
|
153
|
-
|
|
154
|
-
/**
|
|
155
|
-
* The map's {@link KeyboardHandler}, which allows the user to zoom, rotate, and pan the map using keyboard
|
|
156
|
-
* shortcuts.
|
|
157
|
-
*/
|
|
158
|
-
|
|
159
|
-
/**
|
|
160
|
-
* The map's {@link DoubleClickZoomHandler}, which allows the user to zoom by double clicking.
|
|
161
|
-
*/
|
|
162
|
-
|
|
163
|
-
/**
|
|
164
|
-
* The map's {@link TouchZoomRotateHandler}, which allows the user to zoom or rotate the map with touch gestures.
|
|
165
|
-
*/
|
|
166
|
-
|
|
167
137
|
constructor(options) {
|
|
168
138
|
options = Object.assign({}, defaultOptions, options);
|
|
169
139
|
|
|
@@ -186,7 +156,7 @@ class Map extends Camera {
|
|
|
186
156
|
this._fadeDuration = options.fadeDuration;
|
|
187
157
|
this._crossSourceCollisions = options.crossSourceCollisions;
|
|
188
158
|
this._crossFadingFactor = 1;
|
|
189
|
-
this._renderTaskQueue =
|
|
159
|
+
this._renderTaskQueue = taskQueue(this);
|
|
190
160
|
|
|
191
161
|
if (typeof options.container === 'string') {
|
|
192
162
|
const container = window.document.getElementById(options.container);
|
|
@@ -220,6 +190,9 @@ class Map extends Camera {
|
|
|
220
190
|
|
|
221
191
|
this._setupContainer();
|
|
222
192
|
this._setupPainter();
|
|
193
|
+
if (this.painter === undefined) {
|
|
194
|
+
throw new Error('Failed to initialize WebGL.');
|
|
195
|
+
}
|
|
223
196
|
|
|
224
197
|
this.on('move', this._update.bind(this, false));
|
|
225
198
|
this.on('moveend', this._update.bind(this, false));
|
package/src/util/actor.js
CHANGED
|
@@ -15,24 +15,16 @@ module.exports = actor;
|
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
17
|
function actor(target, parent, mapId, name) {
|
|
18
|
-
const
|
|
19
|
-
let callbackID =
|
|
18
|
+
const promises = new Map();
|
|
19
|
+
let callbackID = Number.MIN_SAFE_INTEGER;
|
|
20
20
|
target.addEventListener('message', receive, false);
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
id,
|
|
29
|
-
data: serialize(data, buffers)
|
|
30
|
-
};
|
|
31
|
-
if (err) {
|
|
32
|
-
payload.error = serialize(err);
|
|
33
|
-
}
|
|
34
|
-
target.postMessage(payload, buffers);
|
|
35
|
-
}
|
|
22
|
+
return {
|
|
23
|
+
send,
|
|
24
|
+
receive,
|
|
25
|
+
remove,
|
|
26
|
+
name
|
|
27
|
+
};
|
|
36
28
|
|
|
37
29
|
/**
|
|
38
30
|
* Sends a message from a main-thread map to a Worker or from a Worker back to
|
|
@@ -42,50 +34,54 @@ function actor(target, parent, mapId, name) {
|
|
|
42
34
|
* @param targetMapId A particular mapId to which to send this message.
|
|
43
35
|
* @private
|
|
44
36
|
*/
|
|
45
|
-
function send(type, data,
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
callbacks[id] = callback;
|
|
50
|
-
}
|
|
37
|
+
function send(type, data, targetMapId) {
|
|
38
|
+
const id = `${mapId}:${callbackID++}`;
|
|
39
|
+
const p = Promise.withResolvers();
|
|
40
|
+
promises.set(id, p);
|
|
51
41
|
postMessage(targetMapId, id, type, data);
|
|
42
|
+
return p.promise;
|
|
52
43
|
}
|
|
53
44
|
|
|
54
|
-
function receive(message) {
|
|
45
|
+
async function receive(message) {
|
|
55
46
|
const { data } = message;
|
|
56
47
|
const { id, type, targetMapId } = data;
|
|
57
48
|
|
|
58
49
|
if (targetMapId && mapId !== targetMapId) return;
|
|
59
50
|
|
|
60
|
-
const done = (err, data) => postMessage(undefined, id, '<response>', data, err);
|
|
61
|
-
|
|
62
51
|
if (type === '<response>') {
|
|
63
|
-
const
|
|
64
|
-
|
|
65
|
-
|
|
52
|
+
const p = promises.get(id);
|
|
53
|
+
if (p) {
|
|
54
|
+
promises.delete(id);
|
|
66
55
|
if (data.error) {
|
|
67
|
-
|
|
56
|
+
p.reject(deserialize(data.error));
|
|
68
57
|
} else {
|
|
69
|
-
|
|
58
|
+
p.resolve(deserialize(data.data));
|
|
70
59
|
}
|
|
71
60
|
}
|
|
72
61
|
return;
|
|
73
62
|
}
|
|
74
63
|
|
|
75
64
|
if (typeof id !== 'undefined') {
|
|
65
|
+
let perform;
|
|
76
66
|
if (parent[type]) {
|
|
77
|
-
// data.type == 'loadTile'
|
|
78
|
-
parent[type](data.sourceMapId, deserialize(data.data)
|
|
79
|
-
|
|
80
|
-
}
|
|
81
|
-
if (parent.getWorkerSource) {
|
|
67
|
+
// data.type == 'loadTile' etc.
|
|
68
|
+
perform = () => parent[type](data.sourceMapId, deserialize(data.data));
|
|
69
|
+
} else if (parent.getWorkerSource) {
|
|
82
70
|
// data.type == sourcetype.method
|
|
83
71
|
const [sourcetype, method] = type.split('.');
|
|
84
72
|
const params = deserialize(data.data);
|
|
85
73
|
const workerSource = parent.getWorkerSource(data.sourceMapId, sourcetype, params.source);
|
|
86
|
-
workerSource[method](params
|
|
74
|
+
perform = () => workerSource[method](params);
|
|
75
|
+
} else {
|
|
87
76
|
return;
|
|
88
77
|
}
|
|
78
|
+
try {
|
|
79
|
+
const result = await perform();
|
|
80
|
+
postMessage(data.sourceMapId, id, '<response>', result);
|
|
81
|
+
} catch (err) {
|
|
82
|
+
postMessage(data.sourceMapId, id, '<response>', undefined, err);
|
|
83
|
+
}
|
|
84
|
+
return;
|
|
89
85
|
}
|
|
90
86
|
|
|
91
87
|
parent[type](deserialize(data.data));
|
|
@@ -95,10 +91,18 @@ function actor(target, parent, mapId, name) {
|
|
|
95
91
|
target.removeEventListener('message', receive, false);
|
|
96
92
|
}
|
|
97
93
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
94
|
+
function postMessage(targetMapId, id, type, data, err) {
|
|
95
|
+
const buffers = [];
|
|
96
|
+
const payload = {
|
|
97
|
+
targetMapId,
|
|
98
|
+
sourceMapId: mapId,
|
|
99
|
+
type,
|
|
100
|
+
id,
|
|
101
|
+
data: serialize(data, buffers)
|
|
102
|
+
};
|
|
103
|
+
if (err) {
|
|
104
|
+
payload.error = serialize(err);
|
|
105
|
+
}
|
|
106
|
+
target.postMessage(payload, buffers);
|
|
107
|
+
}
|
|
104
108
|
}
|
package/src/util/browser.js
CHANGED
|
@@ -51,6 +51,12 @@ const exported = {
|
|
|
51
51
|
return context.getImageData(0, 0, img.width, img.height);
|
|
52
52
|
},
|
|
53
53
|
|
|
54
|
+
resolveURL(path) {
|
|
55
|
+
const a = window.document.createElement('a');
|
|
56
|
+
a.href = path;
|
|
57
|
+
return a.href;
|
|
58
|
+
},
|
|
59
|
+
|
|
54
60
|
hardwareConcurrency: typeof window === 'object' ? window.navigator.hardwareConcurrency : 4,
|
|
55
61
|
|
|
56
62
|
get devicePixelRatio() {
|
|
@@ -1,25 +1,17 @@
|
|
|
1
1
|
const assert = require('assert');
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
constructor(strings) {
|
|
5
|
-
this._stringToNumber = {};
|
|
6
|
-
this._numberToString = [];
|
|
7
|
-
for (let i = 0; i < strings.length; i++) {
|
|
8
|
-
const string = strings[i];
|
|
9
|
-
this._stringToNumber[string] = i;
|
|
10
|
-
this._numberToString[i] = string;
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
encode(string) {
|
|
15
|
-
assert(string in this._stringToNumber);
|
|
16
|
-
return this._stringToNumber[string];
|
|
17
|
-
}
|
|
3
|
+
module.exports = dictionaryCoder;
|
|
18
4
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
5
|
+
function dictionaryCoder(strings) {
|
|
6
|
+
const numberToString = strings.sort();
|
|
7
|
+
const stringToNumber = new Map(numberToString.map((s, i) => [s, i]));
|
|
8
|
+
return {
|
|
9
|
+
encode(string) {
|
|
10
|
+
return stringToNumber.get(string);
|
|
11
|
+
},
|
|
12
|
+
decode(n) {
|
|
13
|
+
assert(n < numberToString.length);
|
|
14
|
+
return numberToString[n];
|
|
15
|
+
}
|
|
16
|
+
};
|
|
23
17
|
}
|
|
24
|
-
|
|
25
|
-
module.exports = DictionaryCoder;
|
package/src/util/dispatcher.js
CHANGED
|
@@ -1,11 +1,8 @@
|
|
|
1
|
-
const async = require('./async');
|
|
2
1
|
const uniqueId = require('./unique_id');
|
|
3
2
|
const actor = require('./actor');
|
|
4
3
|
|
|
5
4
|
module.exports = dispatcher;
|
|
6
5
|
|
|
7
|
-
const noop = () => {};
|
|
8
|
-
|
|
9
6
|
/**
|
|
10
7
|
* Responsible for sending messages from a {@link Source} to an associated
|
|
11
8
|
* {@link WorkerSource}.
|
|
@@ -15,7 +12,7 @@ const noop = () => {};
|
|
|
15
12
|
function dispatcher(workerPool, parent, makeActor = actor) {
|
|
16
13
|
// exposed to allow stubbing in unit tests
|
|
17
14
|
|
|
18
|
-
let currentActor =
|
|
15
|
+
let currentActor = -1;
|
|
19
16
|
const id = uniqueId();
|
|
20
17
|
const workers = workerPool.acquire(id);
|
|
21
18
|
const actors = workers.map((worker, i) => makeActor(worker, parent, id, `Worker ${i}`));
|
|
@@ -23,8 +20,9 @@ function dispatcher(workerPool, parent, makeActor = actor) {
|
|
|
23
20
|
/**
|
|
24
21
|
* Broadcast a message to all Workers.
|
|
25
22
|
*/
|
|
26
|
-
function broadcast(type, data
|
|
27
|
-
|
|
23
|
+
function broadcast(type, data) {
|
|
24
|
+
const tasks = actors.map(actor => actor.send(type, data));
|
|
25
|
+
return Promise.all(tasks);
|
|
28
26
|
}
|
|
29
27
|
|
|
30
28
|
// Use round robin to send requests to web workers.
|
|
@@ -41,16 +39,8 @@ function dispatcher(workerPool, parent, makeActor = actor) {
|
|
|
41
39
|
* @param targetID The ID of the Worker to which to send this message. Omit to allow the dispatcher to choose.
|
|
42
40
|
* @returns The ID of the worker to which the message was sent.
|
|
43
41
|
*/
|
|
44
|
-
function send(type, data,
|
|
45
|
-
|
|
46
|
-
targetID = nextActorId();
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
const actor = actors[targetID];
|
|
50
|
-
if (actor) {
|
|
51
|
-
actor.send(type, data, callback);
|
|
52
|
-
}
|
|
53
|
-
return targetID;
|
|
42
|
+
function send(type, data, targetID = nextActorId()) {
|
|
43
|
+
return actors[targetID]?.send(type, data) ?? Promise.resolve();
|
|
54
44
|
}
|
|
55
45
|
|
|
56
46
|
function remove() {
|
|
@@ -59,10 +49,17 @@ function dispatcher(workerPool, parent, makeActor = actor) {
|
|
|
59
49
|
workerPool.release(id);
|
|
60
50
|
}
|
|
61
51
|
|
|
52
|
+
function nextWorkerId(workerId = nextActorId()) {
|
|
53
|
+
return workerId;
|
|
54
|
+
}
|
|
55
|
+
|
|
62
56
|
return {
|
|
63
|
-
id
|
|
57
|
+
get id() {
|
|
58
|
+
return id;
|
|
59
|
+
},
|
|
64
60
|
broadcast,
|
|
65
61
|
send,
|
|
62
|
+
nextWorkerId,
|
|
66
63
|
remove
|
|
67
64
|
};
|
|
68
65
|
}
|
package/src/util/image.js
CHANGED
package/src/util/loader/image.js
CHANGED
|
@@ -1,32 +1,32 @@
|
|
|
1
1
|
module.exports = image;
|
|
2
2
|
|
|
3
|
-
function image(data
|
|
3
|
+
function image(data) {
|
|
4
4
|
if (!data) {
|
|
5
|
-
|
|
6
|
-
}
|
|
7
|
-
if (data.byteLength === 0) {
|
|
8
|
-
transparentImage(fn);
|
|
9
|
-
} else {
|
|
10
|
-
imageFromData({ data }, fn);
|
|
5
|
+
throw new Error('image data not loaded');
|
|
11
6
|
}
|
|
7
|
+
return data.byteLength === 0 ? transparentImage() : imageFromData({ data });
|
|
12
8
|
}
|
|
13
9
|
|
|
14
|
-
async function imageFromData(imgData
|
|
10
|
+
async function imageFromData(imgData) {
|
|
11
|
+
const { promise, resolve } = Promise.withResolvers();
|
|
15
12
|
const blob = new window.Blob([imgData.data], { type: imgData.type || 'image/png' });
|
|
16
13
|
const img = new window.Image();
|
|
17
14
|
|
|
18
15
|
img.onload = () => {
|
|
19
|
-
|
|
16
|
+
resolve(img);
|
|
20
17
|
window.URL.revokeObjectURL(img.src);
|
|
21
18
|
};
|
|
22
19
|
img.src = await window.URL.createObjectURL(blob);
|
|
20
|
+
return promise;
|
|
23
21
|
}
|
|
24
22
|
|
|
25
23
|
const transparentPngUrl =
|
|
26
24
|
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAC0lEQVQYV2NgAAIAAAUAAarVyFEAAAAASUVORK5CYII=';
|
|
27
25
|
|
|
28
|
-
function transparentImage(
|
|
26
|
+
function transparentImage() {
|
|
27
|
+
const { promise, resolve } = Promise.withResolvers();
|
|
29
28
|
const img = new window.Image();
|
|
30
|
-
img.onload = () =>
|
|
29
|
+
img.onload = () => resolve(img);
|
|
31
30
|
img.src = transparentPngUrl;
|
|
31
|
+
return promise;
|
|
32
32
|
}
|
|
@@ -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
|
+
}
|