@cesium/engine 26.3.0 → 26.3.1-wasm.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 (143) hide show
  1. package/Build/ThirdParty/Workers/zip-web-worker.js +504 -535
  2. package/Build/Workers/chunk-2P3WKV6V.js +290 -0
  3. package/Build/Workers/{chunk-MUW4DJV7.js → chunk-2U5272QU.js} +17 -17
  4. package/Build/Workers/{chunk-7WXBTNRV.js → chunk-4KCOC6OZ.js} +8 -10
  5. package/Build/Workers/{chunk-GS7RY2DH.js → chunk-5FULJNWY.js} +11 -13
  6. package/Build/Workers/{chunk-2PWVICP6.js → chunk-65ZF23AQ.js} +1 -1
  7. package/Build/Workers/{chunk-SEJIXZZ4.js → chunk-6D5534B7.js} +10 -12
  8. package/Build/Workers/{chunk-MDDKCLMF.js → chunk-6GFMBHBD.js} +19 -19
  9. package/Build/Workers/{chunk-PKZA44LH.js → chunk-6VRGQF3D.js} +4 -4
  10. package/Build/Workers/{chunk-JBJ6BRIM.js → chunk-6XUIECFB.js} +4 -6
  11. package/Build/Workers/{chunk-DKSANM4A.js → chunk-7KWUH6RK.js} +14 -14
  12. package/Build/Workers/{chunk-6BSNYZZG.js → chunk-7ZBJRQQT.js} +7 -7
  13. package/Build/Workers/{chunk-XRZCS3HE.js → chunk-AEHANE5A.js} +991 -5612
  14. package/Build/Workers/chunk-AUU74SIZ.js +2420 -0
  15. package/Build/Workers/{chunk-2YY724ZX.js → chunk-B6V5NMIE.js} +13 -11
  16. package/Build/Workers/{chunk-5JCZHJUU.js → chunk-BRQ52ASU.js} +15 -17
  17. package/Build/Workers/{chunk-Z2DW5NM2.js → chunk-FVLSQBPH.js} +7 -14
  18. package/Build/Workers/{chunk-L73K5UPP.js → chunk-IFKM2GZR.js} +12 -12
  19. package/Build/Workers/{chunk-F34TJJLA.js → chunk-KF6OEWVT.js} +17 -17
  20. package/Build/Workers/{chunk-JL4NWWQY.js → chunk-KOAXSU77.js} +5 -7
  21. package/Build/Workers/{chunk-CKK6CUXK.js → chunk-KRVYCMGN.js} +6 -6
  22. package/Build/Workers/{chunk-KBGAHN5R.js → chunk-LTZRLNQP.js} +1 -1
  23. package/Build/Workers/{chunk-CQ4TZXAT.js → chunk-M7WEAGWT.js} +8 -8
  24. package/Build/Workers/{chunk-A7SMPV6B.js → chunk-MJTLGN63.js} +14 -14
  25. package/Build/Workers/{chunk-DZK34ZVD.js → chunk-MUNZ77KV.js} +1 -1
  26. package/Build/Workers/{chunk-X27HKF5E.js → chunk-NC5BUJEF.js} +2 -2
  27. package/Build/Workers/chunk-NYKURYFR.js +2131 -0
  28. package/Build/Workers/{chunk-5KG7KDDW.js → chunk-NZAQG57U.js} +7 -7
  29. package/Build/Workers/{chunk-JKTWW7IO.js → chunk-O5GUOP2G.js} +5 -7
  30. package/Build/Workers/{chunk-6R6SGKYN.js → chunk-OQUOLQTN.js} +8 -10
  31. package/Build/Workers/chunk-OUG5JB2K.js +46 -0
  32. package/Build/Workers/{chunk-HDD3RFLT.js → chunk-P4SDLSGF.js} +13 -6
  33. package/Build/Workers/{chunk-M6W46OAP.js → chunk-P6PC2OIM.js} +7 -7
  34. package/Build/Workers/{chunk-XSIUYAT6.js → chunk-PPRK3XQU.js} +31 -35
  35. package/Build/Workers/{chunk-4LRFYRBX.js → chunk-QGTYLWOT.js} +2 -2
  36. package/Build/Workers/{chunk-COKOYTRS.js → chunk-QHTLIQUH.js} +5 -7
  37. package/Build/Workers/{chunk-N5YK44FS.js → chunk-ROHWZQZ5.js} +5 -5
  38. package/Build/Workers/{chunk-XBY3354M.js → chunk-SNUWISJO.js} +6 -8
  39. package/Build/Workers/{chunk-EDETO6NY.js → chunk-T67YY3KP.js} +4 -2
  40. package/Build/Workers/{chunk-4DMAXPKB.js → chunk-TF5473GK.js} +13 -13
  41. package/Build/Workers/{chunk-B7Q2WF6Q.js → chunk-THHFTMAL.js} +4 -6
  42. package/Build/Workers/{chunk-SL2HCFYW.js → chunk-UFCZ62WM.js} +15 -13
  43. package/Build/Workers/{chunk-NZQUP52G.js → chunk-UV2YC2Q5.js} +11 -11
  44. package/Build/Workers/{chunk-E7G32DWL.js → chunk-V4ICCWYA.js} +1 -1
  45. package/Build/Workers/{chunk-75BC2IHI.js → chunk-VC6XXI2Z.js} +9 -9
  46. package/Build/Workers/{chunk-JMUUAW4X.js → chunk-VXJ6P4UI.js} +10 -10
  47. package/Build/Workers/{chunk-QTAEVUED.js → chunk-W2BKP7G7.js} +15 -17
  48. package/Build/Workers/{chunk-VRECSMG3.js → chunk-WMVGNBSH.js} +2 -2
  49. package/Build/Workers/{chunk-7SESBH2I.js → chunk-XFZMQZSZ.js} +4 -4
  50. package/Build/Workers/{chunk-Q2JS5LCB.js → chunk-XJ532R6R.js} +20 -20
  51. package/Build/Workers/{chunk-SLHK3KAR.js → chunk-YJNU4SM4.js} +5 -5
  52. package/Build/Workers/{chunk-LL2SGJYH.js → chunk-YJRDTEHQ.js} +8 -8
  53. package/Build/Workers/chunk-YUICDZKO.js +2660 -0
  54. package/Build/Workers/{chunk-ATSXKJ3L.js → chunk-Z3DEVGJV.js} +7 -7
  55. package/Build/Workers/{chunk-6V2KDEHL.js → chunk-ZECGI7UZ.js} +4 -4
  56. package/Build/Workers/{chunk-LYJUL4XQ.js → chunk-ZFLPVPUJ.js} +6 -8
  57. package/Build/Workers/{chunk-BNDSDQ7D.js → chunk-ZIM5H2DB.js} +11 -11
  58. package/Build/Workers/{chunk-KEWK6VZL.js → chunk-ZSQMGGSB.js} +14 -16
  59. package/Build/Workers/{chunk-2DKJSPYF.js → chunk-ZWYRGMBK.js} +16 -18
  60. package/Build/Workers/{chunk-UZY5XRL2.js → chunk-ZY733NZA.js} +1 -1
  61. package/Build/Workers/combineGeometry.js +24 -24
  62. package/Build/Workers/createBoxGeometry.js +18 -18
  63. package/Build/Workers/createBoxOutlineGeometry.js +20 -19
  64. package/Build/Workers/createCircleGeometry.js +28 -27
  65. package/Build/Workers/createCircleOutlineGeometry.js +21 -20
  66. package/Build/Workers/createCoplanarPolygonGeometry.js +34 -34
  67. package/Build/Workers/createCoplanarPolygonOutlineGeometry.js +33 -32
  68. package/Build/Workers/createCorridorGeometry.js +31 -31
  69. package/Build/Workers/createCorridorOutlineGeometry.js +30 -30
  70. package/Build/Workers/createCylinderGeometry.js +20 -20
  71. package/Build/Workers/createCylinderOutlineGeometry.js +22 -21
  72. package/Build/Workers/createEllipseGeometry.js +26 -26
  73. package/Build/Workers/createEllipseOutlineGeometry.js +19 -19
  74. package/Build/Workers/createEllipsoidGeometry.js +19 -19
  75. package/Build/Workers/createEllipsoidOutlineGeometry.js +18 -18
  76. package/Build/Workers/createFrustumGeometry.js +18 -18
  77. package/Build/Workers/createFrustumOutlineGeometry.js +18 -18
  78. package/Build/Workers/createGeometry.js +27 -26
  79. package/Build/Workers/createGroundPolylineGeometry.js +27 -26
  80. package/Build/Workers/createPlaneGeometry.js +18 -17
  81. package/Build/Workers/createPlaneOutlineGeometry.js +15 -15
  82. package/Build/Workers/createPolygonGeometry.js +35 -35
  83. package/Build/Workers/createPolygonOutlineGeometry.js +34 -34
  84. package/Build/Workers/createPolylineGeometry.js +28 -29
  85. package/Build/Workers/createPolylineVolumeGeometry.js +34 -35
  86. package/Build/Workers/createPolylineVolumeOutlineGeometry.js +30 -31
  87. package/Build/Workers/createRectangleGeometry.js +30 -30
  88. package/Build/Workers/createRectangleOutlineGeometry.js +23 -24
  89. package/Build/Workers/createSimplePolylineGeometry.js +26 -27
  90. package/Build/Workers/createSphereGeometry.js +19 -19
  91. package/Build/Workers/createSphereOutlineGeometry.js +18 -18
  92. package/Build/Workers/createTaskProcessorWorker.js +3 -3
  93. package/Build/Workers/createVectorTileClampedPolylines.js +17 -16
  94. package/Build/Workers/createVectorTileGeometries.js +24 -24
  95. package/Build/Workers/createVectorTilePoints.js +13 -13
  96. package/Build/Workers/createVectorTilePolygons.js +22 -22
  97. package/Build/Workers/createVectorTilePolylines.js +17 -16
  98. package/Build/Workers/createVerticesFromCesium3DTilesTerrain.js +36 -26
  99. package/Build/Workers/createVerticesFromGoogleEarthEnterpriseBuffer.js +24 -24
  100. package/Build/Workers/createVerticesFromHeightmap.js +24 -25
  101. package/Build/Workers/createVerticesFromQuantizedTerrainMesh.js +20 -20
  102. package/Build/Workers/createWallGeometry.js +27 -28
  103. package/Build/Workers/createWallOutlineGeometry.js +26 -27
  104. package/Build/Workers/decodeDraco.js +16 -12
  105. package/Build/Workers/decodeGoogleEarthEnterprisePacket.js +336 -337
  106. package/Build/Workers/decodeI3S.js +17 -12
  107. package/Build/Workers/{chunk-GLHDTTTO.js → decodeMeshopt.js} +23 -29
  108. package/Build/Workers/decodeSpz.js +1960 -0
  109. package/Build/Workers/gaussianSplatSorter.js +13 -6
  110. package/Build/Workers/gaussianSplatTextureGenerator.js +13 -6
  111. package/Build/Workers/incrementallyBuildTerrainPicker.js +9 -10
  112. package/Build/Workers/transcodeKTX2.js +26 -12
  113. package/Build/Workers/transferTypedArrayTest.js +1 -1
  114. package/Build/Workers/upsampleQuantizedTerrainMesh.js +24 -24
  115. package/Build/Workers/upsampleVerticesFromCesium3DTilesTerrain.js +25 -25
  116. package/Source/Core/Cesium3DTilesTerrainData.js +11 -1
  117. package/Source/Core/Cesium3DTilesTerrainGeometryProcessor.js +33 -23
  118. package/Source/Core/KTX2Transcoder.js +99 -5
  119. package/Source/Core/Resource.js +2 -0
  120. package/Source/Core/TaskProcessor.js +249 -129
  121. package/Source/Core/TrustedServers.js +34 -1
  122. package/Source/Core/WebAssemblyWorkerInitializer.js +125 -0
  123. package/Source/Core/fetchWebAssemblyBinary.js +52 -0
  124. package/Source/Scene/GaussianSplatPrimitive.js +153 -66
  125. package/Source/Scene/GltfBufferViewLoader.js +25 -13
  126. package/Source/Scene/GltfSpzLoader.js +5 -4
  127. package/Source/Scene/SpzDecoder.js +106 -0
  128. package/Source/ThirdParty/Workers/zip-web-worker.js +1 -1
  129. package/Source/ThirdParty/zip-module.wasm +0 -0
  130. package/Source/Workers/createTaskProcessorWorker.js +2 -0
  131. package/Source/Workers/createVerticesFromCesium3DTilesTerrain.js +13 -1
  132. package/Source/Workers/decodeDraco.js +7 -3
  133. package/Source/Workers/decodeI3S.js +7 -3
  134. package/Source/Workers/decodeMeshopt.js +21 -0
  135. package/Source/Workers/decodeSpz.js +20 -0
  136. package/Source/Workers/gaussianSplatSorter.js +7 -3
  137. package/Source/Workers/gaussianSplatTextureGenerator.js +7 -3
  138. package/Source/Workers/transcodeKTX2.js +22 -5
  139. package/index.d.ts +93 -0
  140. package/index.js +4 -1
  141. package/package.json +1 -1
  142. package/Build/Workers/chunk-B4AVL7VI.js +0 -82
  143. package/Build/Workers/chunk-HDPNFEPP.js +0 -3820
@@ -2063,6 +2063,7 @@ function loadWithHttpRequest(
2063
2063
  fetch(url, {
2064
2064
  method,
2065
2065
  headers,
2066
+ credentials: TrustedServers.contains(url) ? "include" : "same-origin",
2066
2067
  })
2067
2068
  .then(async (response) => {
2068
2069
  if (!response.ok) {
@@ -2251,6 +2252,7 @@ Resource._DefaultImplementations.createImage =
2251
2252
  Resource._Implementations.createImage;
2252
2253
  Resource._DefaultImplementations.loadWithXhr =
2253
2254
  Resource._Implementations.loadWithXhr;
2255
+ Resource._DefaultImplementations.loadWithHttpRequest = loadWithHttpRequest;
2254
2256
  Resource._DefaultImplementations.loadAndExecuteScript =
2255
2257
  Resource._Implementations.loadAndExecuteScript;
2256
2258
 
@@ -6,8 +6,9 @@ import DeveloperError from "./DeveloperError.js";
6
6
  import Event from "./Event.js";
7
7
  import FeatureDetection from "./FeatureDetection.js";
8
8
  import isCrossOriginUrl from "./isCrossOriginUrl.js";
9
- import Resource from "./Resource.js";
10
9
  import RuntimeError from "./RuntimeError.js";
10
+ import TrustedServers from "./TrustedServers.js";
11
+ import WebAssemblyWorkerInitializer from "./WebAssemblyWorkerInitializer.js";
11
12
 
12
13
  function canTransferArrayBuffer() {
13
14
  if (!defined(TaskProcessor._canTransferArrayBuffer)) {
@@ -17,6 +18,42 @@ function canTransferArrayBuffer() {
17
18
  const value = 99;
18
19
  const array = new Int8Array([value]);
19
20
 
21
+ let settled = false;
22
+ let settle;
23
+ const promise = new Promise((resolve) => {
24
+ const cleanup = () => {
25
+ worker.removeEventListener("message", onMessage);
26
+ worker.removeEventListener("error", onFailure);
27
+ worker.removeEventListener("messageerror", onFailure);
28
+ worker.terminate();
29
+ };
30
+
31
+ settle = (result) => {
32
+ if (settled) {
33
+ return;
34
+ }
35
+ settled = true;
36
+ cleanup();
37
+ TaskProcessor._canTransferArrayBuffer = result;
38
+ resolve(result);
39
+ };
40
+
41
+ const onMessage = (event) => {
42
+ const array = event.data?.array;
43
+
44
+ // Verify that typed arrays round-trip correctly when transferred.
45
+ settle(defined(array) && array[0] === value);
46
+ };
47
+
48
+ const onFailure = () => settle(false);
49
+
50
+ worker.addEventListener("message", onMessage);
51
+ worker.addEventListener("error", onFailure);
52
+ worker.addEventListener("messageerror", onFailure);
53
+ });
54
+
55
+ TaskProcessor._canTransferArrayBuffer = promise;
56
+
20
57
  try {
21
58
  // postMessage might fail with a DataCloneError
22
59
  // if transferring array buffers is not supported.
@@ -27,25 +64,9 @@ function canTransferArrayBuffer() {
27
64
  [array.buffer],
28
65
  );
29
66
  } catch (e) {
30
- TaskProcessor._canTransferArrayBuffer = false;
67
+ settle(false);
31
68
  return TaskProcessor._canTransferArrayBuffer;
32
69
  }
33
-
34
- TaskProcessor._canTransferArrayBuffer = new Promise((resolve) => {
35
- worker.onmessage = function (event) {
36
- const array = event.data.array;
37
-
38
- // some versions of Firefox silently fail to transfer typed arrays.
39
- // https://bugzilla.mozilla.org/show_bug.cgi?id=841904
40
- // Check to make sure the value round-trips successfully.
41
- const result = defined(array) && array[0] === value;
42
- resolve(result);
43
-
44
- worker.terminate();
45
-
46
- TaskProcessor._canTransferArrayBuffer = result;
47
- };
48
- });
49
70
  }
50
71
 
51
72
  return TaskProcessor._canTransferArrayBuffer;
@@ -76,7 +97,7 @@ function urlFromScript(script) {
76
97
 
77
98
  function createWorker(url) {
78
99
  const uri = new Uri(url);
79
- const isUri = uri.scheme().length !== 0 && uri.fragment().length === 0;
100
+ const isUri = uri.scheme().length !== 0;
80
101
  const moduleID = url.replace(/\.js$/, "");
81
102
 
82
103
  const options = {};
@@ -135,35 +156,6 @@ function createWorker(url) {
135
156
  return new Worker(workerPath, options);
136
157
  }
137
158
 
138
- async function getWebAssemblyLoaderConfig(processor, wasmOptions) {
139
- const config = {
140
- modulePath: undefined,
141
- wasmBinaryFile: undefined,
142
- wasmBinary: undefined,
143
- };
144
-
145
- // Web assembly not supported, use fallback js module if provided
146
- if (!FeatureDetection.supportsWebAssembly()) {
147
- if (!defined(wasmOptions.fallbackModulePath)) {
148
- throw new RuntimeError(
149
- `This browser does not support Web Assembly, and no backup module was provided for ${processor._workerPath}`,
150
- );
151
- }
152
-
153
- config.modulePath = buildModuleUrl(wasmOptions.fallbackModulePath);
154
- return config;
155
- }
156
-
157
- config.wasmBinaryFile = buildModuleUrl(wasmOptions.wasmBinaryFile);
158
-
159
- const arrayBuffer = await Resource.fetchArrayBuffer({
160
- url: config.wasmBinaryFile,
161
- });
162
-
163
- config.wasmBinary = arrayBuffer;
164
- return config;
165
- }
166
-
167
159
  /**
168
160
  * A wrapper around a web worker that allows scheduling tasks for a given worker,
169
161
  * returning results asynchronously via a promise.
@@ -183,66 +175,202 @@ function TaskProcessor(workerPath, maximumActiveTasks) {
183
175
  this._maximumActiveTasks = maximumActiveTasks ?? Number.POSITIVE_INFINITY;
184
176
  this._activeTasks = 0;
185
177
  this._nextID = 0;
186
- this._webAssemblyPromise = undefined;
178
+ this._webAssemblyInitializer = undefined;
179
+ this._pendingTasks = new Map();
180
+ this._workerFailureHandlers = new Map();
187
181
  }
188
182
 
189
- const createOnmessageHandler = (worker, id, resolve, reject) => {
190
- const listener = ({ data }) => {
191
- if (data.id !== id) {
192
- return;
183
+ function deserializeWorkerError(serializedError) {
184
+ let error = serializedError;
185
+ if (error.name === "RuntimeError") {
186
+ error = new RuntimeError(serializedError.message);
187
+ error.stack = serializedError.stack;
188
+ } else if (error.name === "DeveloperError") {
189
+ error = new DeveloperError(serializedError.message);
190
+ error.stack = serializedError.stack;
191
+ } else if (error.name === "Error") {
192
+ error = new Error(serializedError.message);
193
+ error.stack = serializedError.stack;
194
+ } else if (defined(error.name) && defined(error.message)) {
195
+ // Any other error class the worker threw, such as the EvalError a
196
+ // Content-Security-Policy produces. Rebuilding it as an Error keeps the
197
+ // name and message legible instead of surfacing an opaque object.
198
+ error = new Error(`${serializedError.name}: ${serializedError.message}`);
199
+ error.stack = serializedError.stack;
200
+ }
201
+ return error;
202
+ }
203
+
204
+ function workerFailureToError(event) {
205
+ if (defined(event.error)) {
206
+ if (event.error instanceof Error) {
207
+ return event.error;
193
208
  }
194
209
 
195
- if (defined(data.error)) {
196
- let error = data.error;
197
- if (error.name === "RuntimeError") {
198
- error = new RuntimeError(data.error.message);
199
- error.stack = data.error.stack;
200
- } else if (error.name === "DeveloperError") {
201
- error = new DeveloperError(data.error.message);
202
- error.stack = data.error.stack;
203
- } else if (error.name === "Error") {
204
- error = new Error(data.error.message);
205
- error.stack = data.error.stack;
210
+ if (defined(event.error.message)) {
211
+ const error = new Error(event.error.message);
212
+ if (defined(event.error.name)) {
213
+ error.name = event.error.name;
214
+ }
215
+ if (defined(event.error.stack)) {
216
+ error.stack = event.error.stack;
206
217
  }
207
- taskCompletedEvent.raiseEvent(error);
208
- reject(error);
209
- } else {
210
- taskCompletedEvent.raiseEvent();
211
- resolve(data.result);
218
+ return error;
212
219
  }
213
220
 
214
- worker.removeEventListener("message", listener);
215
- };
221
+ return new Error(String(event.error));
222
+ }
216
223
 
217
- return listener;
218
- };
224
+ return new Error(event.message ?? "Worker failed");
225
+ }
226
+
227
+ function removeWorkerFailureHandler(processor, worker) {
228
+ const handlers = processor._workerFailureHandlers;
229
+ if (!defined(handlers)) {
230
+ return;
231
+ }
232
+
233
+ const handler = handlers.get(worker);
234
+ if (!defined(handler)) {
235
+ return;
236
+ }
237
+
238
+ worker.removeEventListener("error", handler);
239
+ worker.removeEventListener("messageerror", handler);
240
+ handlers.delete(worker);
241
+ }
242
+
243
+ function settleTask(processor, id, error, result) {
244
+ if (!defined(processor._pendingTasks)) {
245
+ return;
246
+ }
247
+
248
+ const pendingTask = processor._pendingTasks.get(id);
249
+ if (!defined(pendingTask)) {
250
+ return;
251
+ }
252
+
253
+ processor._pendingTasks.delete(id);
254
+ pendingTask.worker.removeEventListener("message", pendingTask.listener);
255
+
256
+ if (defined(error)) {
257
+ taskCompletedEvent.raiseEvent(error);
258
+ pendingTask.reject(error);
259
+ } else {
260
+ taskCompletedEvent.raiseEvent();
261
+ pendingTask.resolve(result);
262
+ }
263
+ }
264
+
265
+ function cleanupWorker(processor, worker, error) {
266
+ processor._webAssemblyInitializer?.reset(worker, error);
267
+ removeWorkerFailureHandler(processor, worker);
268
+
269
+ if (defined(error) && defined(processor._pendingTasks)) {
270
+ for (const [id, pendingTask] of Array.from(
271
+ processor._pendingTasks.entries(),
272
+ )) {
273
+ if (pendingTask.worker === worker) {
274
+ settleTask(processor, id, error);
275
+ }
276
+ }
277
+ }
278
+
279
+ worker.terminate();
280
+
281
+ if (processor._worker === worker) {
282
+ processor._worker = undefined;
283
+ }
284
+ }
285
+
286
+ function handleWorkerFailure(processor, worker, event) {
287
+ const error = workerFailureToError(event);
288
+ cleanupWorker(processor, worker, error);
289
+ }
290
+
291
+ function createProcessorWorker(processor) {
292
+ const worker = createWorker(processor._workerPath);
293
+ const failureHandler = (event) =>
294
+ handleWorkerFailure(processor, worker, event);
295
+
296
+ worker.addEventListener("error", failureHandler);
297
+ worker.addEventListener("messageerror", failureHandler);
298
+ processor._workerFailureHandlers.set(worker, failureHandler);
299
+ return worker;
300
+ }
301
+
302
+ async function getWorker(processor) {
303
+ if (!defined(processor._webAssemblyInitializer)) {
304
+ if (!defined(processor._worker)) {
305
+ processor._worker = createProcessorWorker(processor);
306
+ }
307
+
308
+ return processor._worker;
309
+ }
310
+
311
+ await processor.initWebAssemblyModule();
312
+
313
+ return processor._worker;
314
+ }
219
315
 
220
316
  const emptyTransferableObjectArray = [];
221
317
  async function runTask(processor, parameters, transferableObjects) {
222
- const canTransfer = await Promise.resolve(canTransferArrayBuffer());
223
- if (!defined(transferableObjects)) {
224
- transferableObjects = emptyTransferableObjectArray;
225
- } else if (!canTransfer) {
226
- transferableObjects.length = 0;
318
+ const id = processor._nextID++;
319
+ const worker = defined(processor._webAssemblyInitializer)
320
+ ? await getWorker(processor)
321
+ : processor._worker;
322
+
323
+ if (processor.isDestroyed()) {
324
+ throw new RuntimeError("TaskProcessor was destroyed.");
227
325
  }
228
326
 
229
- const id = processor._nextID++;
230
327
  const promise = new Promise((resolve, reject) => {
231
- processor._worker.addEventListener(
232
- "message",
233
- createOnmessageHandler(processor._worker, id, resolve, reject),
234
- );
328
+ const listener = ({ data }) => {
329
+ if (!defined(data) || data.id !== id) {
330
+ return;
331
+ }
332
+
333
+ if (defined(data.error)) {
334
+ settleTask(processor, id, deserializeWorkerError(data.error));
335
+ } else {
336
+ settleTask(processor, id, undefined, data.result);
337
+ }
338
+ };
339
+
340
+ processor._pendingTasks.set(id, {
341
+ worker: worker,
342
+ listener: listener,
343
+ resolve: resolve,
344
+ reject: reject,
345
+ });
346
+ worker.addEventListener("message", listener);
235
347
  });
236
348
 
237
- processor._worker.postMessage(
238
- {
239
- id: id,
240
- baseUrl: buildModuleUrl.getCesiumBaseUrl().url,
241
- parameters: parameters,
242
- canTransferArrayBuffer: canTransfer,
243
- },
244
- transferableObjects,
245
- );
349
+ try {
350
+ const canTransfer = await Promise.resolve(canTransferArrayBuffer());
351
+ if (!processor._pendingTasks.has(id)) {
352
+ return promise;
353
+ }
354
+
355
+ if (!defined(transferableObjects)) {
356
+ transferableObjects = emptyTransferableObjectArray;
357
+ } else if (!canTransfer) {
358
+ transferableObjects.length = 0;
359
+ }
360
+
361
+ worker.postMessage(
362
+ {
363
+ id: id,
364
+ baseUrl: buildModuleUrl.getCesiumBaseUrl().url,
365
+ trustedServers: TrustedServers.pack(),
366
+ parameters: parameters,
367
+ canTransferArrayBuffer: canTransfer,
368
+ },
369
+ transferableObjects,
370
+ );
371
+ } catch (error) {
372
+ settleTask(processor, id, error);
373
+ }
246
374
 
247
375
  return promise;
248
376
  }
@@ -291,7 +419,9 @@ TaskProcessor.prototype.scheduleTask = function (
291
419
  transferableObjects,
292
420
  ) {
293
421
  if (!defined(this._worker)) {
294
- this._worker = createWorker(this._workerPath);
422
+ if (!defined(this._webAssemblyInitializer)) {
423
+ this._worker = createProcessorWorker(this);
424
+ }
295
425
  }
296
426
 
297
427
  if (this._activeTasks >= this._maximumActiveTasks) {
@@ -306,6 +436,9 @@ TaskProcessor.prototype.scheduleTask = function (
306
436
  * and compiling a web assembly module asynchronously, as well as an optional
307
437
  * fallback JavaScript module to use if Web Assembly is not supported.
308
438
  *
439
+ * Only the resolved url of the binary is posted. The worker requests and compiles
440
+ * the bytes itself, so WebAssembly is never fetched or compiled by the document.
441
+ *
309
442
  * @param {object} [webAssemblyOptions] An object with the following properties:
310
443
  * @param {string} [webAssemblyOptions.modulePath] The path of the web assembly JavaScript wrapper module.
311
444
  * @param {string} [webAssemblyOptions.wasmBinaryFile] The path of the web assembly binary file.
@@ -317,46 +450,32 @@ TaskProcessor.prototype.scheduleTask = function (
317
450
  TaskProcessor.prototype.initWebAssemblyModule = async function (
318
451
  webAssemblyOptions,
319
452
  ) {
320
- if (defined(this._webAssemblyPromise)) {
321
- return this._webAssemblyPromise;
453
+ let initializer = this._webAssemblyInitializer;
454
+ if (defined(initializer?.promise)) {
455
+ return initializer.promise;
322
456
  }
323
457
 
324
- const init = async () => {
325
- const worker = (this._worker = createWorker(this._workerPath));
326
- const wasmConfig = await getWebAssemblyLoaderConfig(
327
- this,
458
+ if (defined(webAssemblyOptions) || !defined(initializer)) {
459
+ initializer = new WebAssemblyWorkerInitializer(
460
+ this._workerPath,
328
461
  webAssemblyOptions,
329
462
  );
330
- const canTransfer = await Promise.resolve(canTransferArrayBuffer());
331
- let transferableObjects;
332
- const binary = wasmConfig.wasmBinary;
333
- if (defined(binary) && canTransfer) {
334
- transferableObjects = [binary];
335
- }
336
-
337
- const promise = new Promise((resolve, reject) => {
338
- worker.onmessage = function ({ data }) {
339
- if (defined(data)) {
340
- resolve(data.result);
341
- } else {
342
- reject(new RuntimeError("Could not configure wasm module"));
343
- }
344
- };
345
- });
463
+ this._webAssemblyInitializer = initializer;
464
+ }
346
465
 
347
- worker.postMessage(
348
- {
349
- canTransferArrayBuffer: canTransfer,
350
- parameters: { webAssemblyConfig: wasmConfig },
351
- },
352
- transferableObjects,
466
+ const worker = (this._worker = createProcessorWorker(this));
467
+ try {
468
+ return await initializer.initialize(
469
+ worker,
470
+ canTransferArrayBuffer,
471
+ deserializeWorkerError,
353
472
  );
354
-
355
- return promise;
356
- };
357
-
358
- this._webAssemblyPromise = init();
359
- return this._webAssemblyPromise;
473
+ } catch (error) {
474
+ if (this._workerFailureHandlers.has(worker)) {
475
+ cleanupWorker(this, worker, error);
476
+ }
477
+ throw error;
478
+ }
360
479
  };
361
480
 
362
481
  /**
@@ -380,8 +499,9 @@ TaskProcessor.prototype.isDestroyed = function () {
380
499
  * <code>isDestroyed</code> will result in a {@link DeveloperError} exception.
381
500
  */
382
501
  TaskProcessor.prototype.destroy = function () {
383
- if (defined(this._worker)) {
384
- this._worker.terminate();
502
+ const error = new RuntimeError("TaskProcessor was destroyed.");
503
+ for (const worker of this._workerFailureHandlers.keys()) {
504
+ cleanupWorker(this, worker, error);
385
505
  }
386
506
  return destroyObject(this);
387
507
  };
@@ -85,7 +85,8 @@ function getAuthority(url) {
85
85
  if (authority.indexOf(":") === -1) {
86
86
  let scheme = uri.scheme();
87
87
  if (scheme.length === 0) {
88
- scheme = window.location.protocol;
88
+ // `self` resolves in both a document and a Web Worker, unlike `window`.
89
+ scheme = self.location.protocol;
89
90
  scheme = scheme.substring(0, scheme.length - 1);
90
91
  }
91
92
  if (scheme === "http") {
@@ -133,6 +134,38 @@ TrustedServers.contains = function (url) {
133
134
  return false;
134
135
  };
135
136
 
137
+ /**
138
+ * Packs the registry into an array of trusted `host:port` authorities, so it
139
+ * can be sent across a realm boundary (e.g. to a Web Worker) and restored
140
+ * with {@link TrustedServers.unpack}. `TrustedServers` is module state, so a
141
+ * worker's copy of this module starts with an empty registry even though the
142
+ * document already called {@link TrustedServers.add}.
143
+ *
144
+ * @returns {string[]} The packed array of trusted `host:port` authorities.
145
+ *
146
+ * @example
147
+ * // Send the registry to a worker, then restore it there
148
+ * worker.postMessage({ trustedServers: TrustedServers.pack() });
149
+ * // In the worker:
150
+ * TrustedServers.unpack(data.trustedServers);
151
+ */
152
+ TrustedServers.pack = function () {
153
+ return Object.keys(_servers);
154
+ };
155
+
156
+ /**
157
+ * Replaces the registry with the authorities from an array packed by
158
+ * {@link TrustedServers.pack}.
159
+ *
160
+ * @param {string[]} packedAuthorities The packed array of trusted `host:port` authorities.
161
+ */
162
+ TrustedServers.unpack = function (packedAuthorities) {
163
+ _servers = {};
164
+ for (const authority of packedAuthorities) {
165
+ _servers[authority] = true;
166
+ }
167
+ };
168
+
136
169
  /**
137
170
  * Clears the registry
138
171
  *
@@ -0,0 +1,125 @@
1
+ import buildModuleUrl from "./buildModuleUrl.js";
2
+ import defined from "./defined.js";
3
+ import FeatureDetection from "./FeatureDetection.js";
4
+ import RuntimeError from "./RuntimeError.js";
5
+ import TrustedServers from "./TrustedServers.js";
6
+
7
+ function getWebAssemblyLoaderConfig(workerPath, wasmOptions) {
8
+ const config = {
9
+ modulePath: undefined,
10
+ wasmBinaryFile: undefined,
11
+ };
12
+
13
+ // Web assembly not supported, use fallback js module if provided
14
+ if (!FeatureDetection.supportsWebAssembly()) {
15
+ if (!defined(wasmOptions.fallbackModulePath)) {
16
+ throw new RuntimeError(
17
+ `This browser does not support Web Assembly, and no backup module was provided for ${workerPath}`,
18
+ );
19
+ }
20
+
21
+ config.modulePath = buildModuleUrl(wasmOptions.fallbackModulePath);
22
+ return config;
23
+ }
24
+
25
+ // Only the resolved url is sent. The worker requests and compiles the binary
26
+ // itself so that WebAssembly is never handled by the document, allowing
27
+ // applications to scope `wasm-unsafe-eval` to worker responses.
28
+ config.wasmBinaryFile = buildModuleUrl(wasmOptions.wasmBinaryFile);
29
+ if (defined(wasmOptions.modulePath)) {
30
+ config.modulePath = buildModuleUrl(wasmOptions.modulePath);
31
+ }
32
+
33
+ return config;
34
+ }
35
+
36
+ /**
37
+ * Handles the WebAssembly initialization exchange for a TaskProcessor worker.
38
+ * TaskProcessor owns the worker and resets this helper when the worker stops.
39
+ *
40
+ * @param {string} workerPath The worker URL or module ID.
41
+ * @param {object} [options] The WebAssembly loader options.
42
+ * @private
43
+ */
44
+ function WebAssemblyWorkerInitializer(workerPath, options) {
45
+ this._config = defined(options)
46
+ ? getWebAssemblyLoaderConfig(workerPath, options)
47
+ : undefined;
48
+ this._worker = undefined;
49
+ this._pending = undefined;
50
+ this.promise = undefined;
51
+ }
52
+
53
+ WebAssemblyWorkerInitializer.prototype._settle = function (error, result) {
54
+ const pending = this._pending;
55
+ if (!defined(pending)) {
56
+ return;
57
+ }
58
+
59
+ this._pending = undefined;
60
+ this._worker.removeEventListener("message", pending.listener);
61
+ if (defined(error)) {
62
+ pending.reject(error);
63
+ } else {
64
+ pending.resolve(result);
65
+ }
66
+ };
67
+
68
+ WebAssemblyWorkerInitializer.prototype.initialize = function (
69
+ worker,
70
+ canTransferArrayBuffer,
71
+ deserializeError,
72
+ ) {
73
+ this._worker = worker;
74
+ const response = new Promise((resolve, reject) => {
75
+ const listener = ({ data }) => {
76
+ if (
77
+ !defined(data) ||
78
+ typeof data !== "object" ||
79
+ (!Object.prototype.hasOwnProperty.call(data, "result") &&
80
+ !Object.prototype.hasOwnProperty.call(data, "error"))
81
+ ) {
82
+ this._settle(new RuntimeError("Could not configure wasm module"));
83
+ } else if (defined(data.error)) {
84
+ this._settle(deserializeError(data.error));
85
+ } else {
86
+ this._settle(undefined, data.result);
87
+ }
88
+ };
89
+ this._pending = { listener, resolve, reject };
90
+ worker.addEventListener("message", listener);
91
+ });
92
+
93
+ this.promise = (async () => {
94
+ try {
95
+ const canTransfer = await canTransferArrayBuffer();
96
+ if (this._worker === worker && defined(this._pending)) {
97
+ worker.postMessage({
98
+ canTransferArrayBuffer: canTransfer,
99
+ baseUrl: buildModuleUrl.getCesiumBaseUrl().url,
100
+ trustedServers: TrustedServers.pack(),
101
+ parameters: { webAssemblyConfig: this._config },
102
+ });
103
+ }
104
+ } catch (error) {
105
+ if (this._worker === worker) {
106
+ this._settle(error);
107
+ }
108
+ }
109
+ return response;
110
+ })();
111
+
112
+ return this.promise;
113
+ };
114
+
115
+ WebAssemblyWorkerInitializer.prototype.reset = function (worker, error) {
116
+ if (this._worker !== worker) {
117
+ return;
118
+ }
119
+
120
+ this._settle(error);
121
+ this._worker = undefined;
122
+ this.promise = undefined;
123
+ };
124
+
125
+ export default WebAssemblyWorkerInitializer;