@privateid/ultrapass-web-sdk 1.7.0 → 2.0.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 (115) hide show
  1. package/dist/application/modules/core/document/DocumentService.js +16 -31
  2. package/dist/application/modules/core/document/DocumentService.js.map +1 -1
  3. package/dist/application/modules/core/document/document.types.d.ts +151 -0
  4. package/dist/application/modules/core/document/document.utils.d.ts +23 -1
  5. package/dist/application/modules/core/document/document.utils.js +123 -20
  6. package/dist/application/modules/core/document/document.utils.js.map +1 -1
  7. package/dist/application/modules/core/face/FaceService.d.ts +1 -2
  8. package/dist/application/modules/core/face/FaceService.js +11 -23
  9. package/dist/application/modules/core/face/FaceService.js.map +1 -1
  10. package/dist/application/modules/core/face/face.types.d.ts +104 -2
  11. package/dist/application/modules/core/face/face.types.js.map +1 -1
  12. package/dist/application/modules/core/face/face.utils.d.ts +14 -0
  13. package/dist/application/modules/core/face/face.utils.js +86 -2
  14. package/dist/application/modules/core/face/face.utils.js.map +1 -1
  15. package/dist/application/modules/internal/feature-flag/LDFeatureFlagService.js +0 -1
  16. package/dist/application/modules/internal/feature-flag/LDFeatureFlagService.js.map +1 -1
  17. package/dist/application/modules/internal/shared/index.d.ts +1 -0
  18. package/dist/application/modules/internal/shared/index.js +1 -0
  19. package/dist/application/modules/internal/shared/index.js.map +1 -1
  20. package/dist/application/modules/internal/shared/shared.types.d.ts +21 -0
  21. package/dist/application/modules/internal/shared/shared.types.js +2 -0
  22. package/dist/application/modules/internal/shared/shared.types.js.map +1 -0
  23. package/dist/application/modules/internal/shared/shared.utils.d.ts +6 -0
  24. package/dist/application/modules/internal/shared/shared.utils.js +26 -3
  25. package/dist/application/modules/internal/shared/shared.utils.js.map +1 -1
  26. package/dist/application/modules/internal/wasm-orchestrator/WasmOrchestratorService.d.ts +0 -1
  27. package/dist/application/modules/internal/wasm-orchestrator/WasmOrchestratorService.js +87 -208
  28. package/dist/application/modules/internal/wasm-orchestrator/WasmOrchestratorService.js.map +1 -1
  29. package/dist/application/modules/internal/wasm-orchestrator/index.d.ts +1 -2
  30. package/dist/application/modules/internal/wasm-orchestrator/index.js +0 -2
  31. package/dist/application/modules/internal/wasm-orchestrator/index.js.map +1 -1
  32. package/dist/application/modules/internal/wasm-orchestrator/wasm-orchestrator.types.d.ts +7 -19
  33. package/dist/application/modules/internal/wasm-orchestrator/wasm-orchestrator.utils.d.ts +18 -0
  34. package/dist/application/modules/internal/wasm-orchestrator/wasm-orchestrator.utils.js +69 -10
  35. package/dist/application/modules/internal/wasm-orchestrator/wasm-orchestrator.utils.js.map +1 -1
  36. package/dist/application/modules/internal/wasm-orchestrator/wasm-orchestrator.utils.test.d.ts +1 -0
  37. package/dist/application/modules/internal/wasm-orchestrator/wasm-orchestrator.utils.test.js +218 -0
  38. package/dist/application/modules/internal/wasm-orchestrator/wasm-orchestrator.utils.test.js.map +1 -0
  39. package/dist/application/modules/support/camera/CameraServiceFactory.js +0 -1
  40. package/dist/application/modules/support/camera/CameraServiceFactory.js.map +1 -1
  41. package/dist/application/modules/support/camera/camera.types.d.ts +8 -3
  42. package/dist/application/modules/support/camera/camera.types.js +9 -5
  43. package/dist/application/modules/support/camera/camera.types.js.map +1 -1
  44. package/dist/application/modules/support/camera/camera.utils.js +0 -1
  45. package/dist/application/modules/support/camera/camera.utils.js.map +1 -1
  46. package/dist/application/modules/support/camera/index.d.ts +2 -1
  47. package/dist/application/modules/support/camera/index.js +1 -0
  48. package/dist/application/modules/support/camera/index.js.map +1 -1
  49. package/dist/application/modules/support/camera/services/BaseCameraService.js +0 -3
  50. package/dist/application/modules/support/camera/services/BaseCameraService.js.map +1 -1
  51. package/dist/application/modules/support/camera/services/DesktopCameraService.js +0 -1
  52. package/dist/application/modules/support/camera/services/DesktopCameraService.js.map +1 -1
  53. package/dist/application/modules/support/camera/services/FirefoxCameraService.js +0 -1
  54. package/dist/application/modules/support/camera/services/FirefoxCameraService.js.map +1 -1
  55. package/dist/application/modules/support/camera/services/MacSafariCameraService.js +0 -1
  56. package/dist/application/modules/support/camera/services/MacSafariCameraService.js.map +1 -1
  57. package/dist/application/modules/support/camera/services/MobileCameraService.js +1 -3
  58. package/dist/application/modules/support/camera/services/MobileCameraService.js.map +1 -1
  59. package/dist/application/modules/support/engine/EngineService.js +0 -2
  60. package/dist/application/modules/support/engine/EngineService.js.map +1 -1
  61. package/dist/application/modules/support/engine/engine.types.d.ts +2 -21
  62. package/dist/application/modules/support/engine/engine.utils.js +1 -3
  63. package/dist/application/modules/support/engine/engine.utils.js.map +1 -1
  64. package/dist/application/modules/support/engine/index.d.ts +1 -1
  65. package/dist/application/modules/support/permissions/PermissionsService.js +0 -2
  66. package/dist/application/modules/support/permissions/PermissionsService.js.map +1 -1
  67. package/dist/application/modules/support/permissions/index.js +0 -1
  68. package/dist/application/modules/support/permissions/index.js.map +1 -1
  69. package/dist/application/workers/wasm/WasmWorkerService.d.ts +14 -3
  70. package/dist/application/workers/wasm/WasmWorkerService.js +270 -206
  71. package/dist/application/workers/wasm/WasmWorkerService.js.map +1 -1
  72. package/dist/application/workers/wasm/wasm-worker.types.d.ts +19 -1
  73. package/dist/application/workers/wasm/wasm-worker.utils.d.ts +28 -1
  74. package/dist/application/workers/wasm/wasm-worker.utils.js +132 -22
  75. package/dist/application/workers/wasm/wasm-worker.utils.js.map +1 -1
  76. package/dist/application/workers/wasm/wasm-worker.utils.test.d.ts +1 -0
  77. package/dist/application/workers/wasm/wasm-worker.utils.test.js +123 -0
  78. package/dist/application/workers/wasm/wasm-worker.utils.test.js.map +1 -0
  79. package/dist/index.d.ts +46 -35
  80. package/dist/index.js +104 -77
  81. package/dist/index.js.map +1 -1
  82. package/package.json +19 -11
  83. package/wasm/ultra/manifest.json +3 -3
  84. package/workers/wasm-new.worker.js +1 -1
  85. package/workers/wasm-new.worker.js.map +3 -3
  86. package/dist/apiUtils.d.ts +0 -46
  87. package/dist/apiUtils.js +0 -923
  88. package/dist/apiUtils.js.map +0 -1
  89. package/dist/cameraUtils.d.ts +0 -77
  90. package/dist/cameraUtils.js +0 -362
  91. package/dist/cameraUtils.js.map +0 -1
  92. package/dist/constants.d.ts +0 -9
  93. package/dist/constants.js +0 -14
  94. package/dist/constants.js.map +0 -1
  95. package/dist/createCallback.d.ts +0 -57
  96. package/dist/createCallback.js +0 -336
  97. package/dist/createCallback.js.map +0 -1
  98. package/dist/dbUtils.d.ts +0 -14
  99. package/dist/dbUtils.js +0 -149
  100. package/dist/dbUtils.js.map +0 -1
  101. package/dist/envUtils.d.ts +0 -4
  102. package/dist/envUtils.js +0 -17
  103. package/dist/envUtils.js.map +0 -1
  104. package/dist/faceModule.d.ts +0 -233
  105. package/dist/faceModule.js +0 -1021
  106. package/dist/faceModule.js.map +0 -1
  107. package/dist/main.d.ts +0 -48
  108. package/dist/main.js +0 -111
  109. package/dist/main.js.map +0 -1
  110. package/dist/types.d.ts +0 -139
  111. package/dist/types.js +0 -78
  112. package/dist/types.js.map +0 -1
  113. package/dist/utils.d.ts +0 -90
  114. package/dist/utils.js +0 -587
  115. package/dist/utils.js.map +0 -1
@@ -7,12 +7,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
7
7
  step((generator = generator.apply(thisArg, _arguments || [])).next());
8
8
  });
9
9
  };
10
- /* eslint-disable no-underscore-dangle */
11
- /* eslint-disable lines-between-class-members */
12
- /* eslint-disable import/prefer-default-export */
13
10
  import { expose } from 'comlink';
14
11
  import { printLogs, setDebugType } from '../../modules/internal/shared/shared.utils';
15
- import { checkCacheAndCurrentAreSameVersion, fetchResource, flatImageDataArraysIntoUint8Array, readCurrentWasmVersion, readFromIndexedDB, removeNullBytesFromDecodedString, writeToIndexedDB, validateCustomWasmUrl, } from './wasm-worker.utils';
12
+ import { checkCacheAndCurrentAreSameVersion, classifyFailureReason, clearCacheEntry, flatImageDataArraysIntoUint8Array, isCacheCorruptionFailure, readCurrentWasmVersion, readFromIndexedDBWithTimeout, removeNullBytesFromDecodedString, validateCustomWasmUrl, validateWasmBinary, writeToCacheQuietly, } from './wasm-worker.utils';
16
13
  import { WASM_ULTRA_FOLDER_NAME } from './wasm-worker.constants';
17
14
  const callbackRegistry = {
18
15
  result: null,
@@ -105,6 +102,11 @@ export class WasmWorkerService {
105
102
  loadModules(params, errorCallback, progressCallback) {
106
103
  return __awaiter(this, void 0, void 0, function* () {
107
104
  try {
105
+ // Handle session regeneration without re-downloading modules.
106
+ // This path is used when credentials change (e.g., token refresh) but modules are already loaded.
107
+ if (this.wasmPrividModules && this.wasmSession && params.shouldRegenerateSession) {
108
+ return this.regenerateSession(params, errorCallback, progressCallback);
109
+ }
108
110
  // If modules are already loaded and session exists, don't re-initialize!
109
111
  // Re-initialization corrupts the WASM state causing _privid_check_models() to return 0
110
112
  if (this.wasmPrividModules && this.wasmSession) {
@@ -116,6 +118,7 @@ export class WasmWorkerService {
116
118
  return { message: 'Already loaded', status: this.lastLoadStatus };
117
119
  }
118
120
  catch (error) {
121
+ printLogs('[WasmWorkerService] loadModules error', error);
119
122
  return { message: 'Retrying initialization', status: null };
120
123
  }
121
124
  }
@@ -134,7 +137,40 @@ export class WasmWorkerService {
134
137
  }
135
138
  });
136
139
  }
140
+ regenerateSession(params, errorCallback, progressCallback) {
141
+ return __awaiter(this, void 0, void 0, function* () {
142
+ printLogs('[WasmWorkerService] Regenerating session as requested', '');
143
+ // Update callbacks and credentials for the new session
144
+ this.proxiedErrorCallback = errorCallback;
145
+ callbackRegistry.error = errorCallback;
146
+ this.proxiedProgressCallback = progressCallback;
147
+ callbackRegistry.progress = progressCallback;
148
+ this.apiUrl = params.apiUrl;
149
+ this.sessionToken = params.sessionToken;
150
+ this.publicKey = params.publicKey;
151
+ // Deinitialize the old session to free C++ heap memory.
152
+ // Wrapped in try-catch: if deinit throws (e.g., due to the C++ layer's internal state),
153
+ // we log and proceed -- a leaked session is better than a blocked regeneration.
154
+ try {
155
+ this.wasmPrividModules._privid_deinitialize_session(this.wasmSession);
156
+ }
157
+ catch (error) {
158
+ printLogs('[WasmWorkerService] _privid_deinitialize_session failed (non-fatal, proceeding with regeneration)', error, 'WARN');
159
+ }
160
+ // Null the existing session so initializeWasmSession creates a new one
161
+ // (initializeWasmSession returns early if this.wasmSession is already set)
162
+ this.wasmSession = null;
163
+ const newSession = yield this.initializeWasmSession(params.usageScenario, params.cacheContent);
164
+ if (!newSession) {
165
+ printLogs('[WasmWorkerService] ERROR: Failed to regenerate session', '', 'ERROR');
166
+ throw new Error('Session regeneration failed');
167
+ }
168
+ this.wasmSession = newSession;
169
+ return { message: 'Session regenerated', status: this.lastLoadStatus };
170
+ });
171
+ }
137
172
  loadModulesInternal(params, errorCallback, progressCallback) {
173
+ var _a, _b;
138
174
  return __awaiter(this, void 0, void 0, function* () {
139
175
  this.proxiedErrorCallback = errorCallback;
140
176
  callbackRegistry.error = errorCallback;
@@ -143,151 +179,53 @@ export class WasmWorkerService {
143
179
  this.apiUrl = params.apiUrl;
144
180
  this.sessionToken = params.sessionToken;
145
181
  this.publicKey = params.publicKey;
146
- this.useCdnLink = params.useCdn;
182
+ this.useCdnLink = (_a = params.useCdn) !== null && _a !== void 0 ? _a : true;
147
183
  this.setCache = params.cacheConfig;
148
184
  this.isSimd = params.simd;
149
185
  this.customWasm = params.customWasm || null;
150
186
  this.wasmBaseUrl = params.wasmBaseUrl || null;
151
- // Only set debugType if explicitly provided (legacy support)
152
- // Note: Debug type is already cached globally from WasmOrchestratorService.initialize()
153
187
  if (params.debugType) {
154
188
  this.debugType = params.debugType;
155
- // Set debug type onto Web Worker Context
156
189
  setDebugType(params.debugType);
157
190
  }
158
- // Store WASM folder name from orchestrator (feature flag resolved on main thread)
159
191
  if (params.wasmFolderName) {
160
192
  this.wasmFolderName = params.wasmFolderName;
161
193
  }
194
+ if (params.cdnBaseUrl) {
195
+ this.cdnUrl = params.cdnBaseUrl;
196
+ }
162
197
  printLogs('[WasmWorkerService] isLoad params: ', params);
198
+ // --- Resolve version ---
163
199
  const modulePath = params.simd ? 'simd' : 'nosimd';
164
200
  const moduleName = 'privid_fhe_ultra';
165
- const cachedModule = yield readFromIndexedDB(WASM_ULTRA_FOLDER_NAME);
166
201
  const currentModuleVersionJSON = yield readCurrentWasmVersion(modulePath, this.wasmBaseUrl, this.getWasmFolderName());
167
202
  this.currentWasmVersion = currentModuleVersionJSON.version;
168
- printLogs('[WasmWorkerService] currentModuleVersionJSON: ', currentModuleVersionJSON.version);
169
- // If custom WASM config is provided, validate and load with fallback
170
- if (this.customWasm) {
171
- printLogs('[WasmWorkerService] Custom WASM detected, validating...', this.customWasm);
172
- const isValid = yield validateCustomWasmUrl(this.customWasm.url);
173
- if (isValid) {
174
- const expectedVersion = currentModuleVersionJSON.version;
175
- const providedVersion = this.customWasm.version;
176
- // Check version equality
177
- if (providedVersion !== expectedVersion) {
178
- printLogs('[WasmWorkerService] Version mismatch detected, falling back to CDN', { expected: expectedVersion, provided: providedVersion }, 'WARN');
179
- this.customWasm = null;
180
- this.lastLoadStatus = { source: 'custom-fallback', versionMatch: false };
181
- // Continue with normal cache/CDN flow
182
- }
183
- else {
184
- printLogs('[WasmWorkerService] Version match confirmed', { version: providedVersion });
185
- // Proceed with loading
186
- printLogs('[WasmWorkerService] Custom WASM URL is valid, loading...', this.customWasm.url);
187
- yield this.loadFromPackage(currentModuleVersionJSON.version, modulePath, moduleName, params.usageScenario, params.cacheContent);
188
- // Final verification that WASM is fully initialized
189
- if (!this.wasmPrividModules || !this.wasmSession) {
190
- const error = 'WASM modules loaded but session not initialized';
191
- printLogs(`[WasmWorkerService] ERROR: ${error}`, '', 'ERROR');
192
- throw new Error(error);
193
- }
194
- this.lastLoadStatus = { source: 'custom', versionMatch: true };
195
- return { message: 'Loaded from custom URL', status: this.lastLoadStatus };
196
- }
197
- }
198
- else {
199
- printLogs('[WasmWorkerService] Custom WASM URL validation failed, falling back to CDN', '', 'WARN');
200
- this.customWasm = null;
201
- this.lastLoadStatus = { source: 'custom-fallback', versionMatch: false };
202
- // Continue with normal cache/CDN flow
203
- }
204
- }
205
- if (checkCacheAndCurrentAreSameVersion(cachedModule, currentModuleVersionJSON)) {
206
- printLogs('[WasmWorkerService] same version confirmed', '');
207
- printLogs('[WasmWorkerService] PRIVMODULES LOADED?: ', this.wasmPrividModules);
208
- if (!this.wasmPrividModules) {
209
- const { cachedWasm, cachedScript } = cachedModule;
210
- if (cachedWasm && cachedScript) {
211
- const blob = new Blob([cachedScript], { type: 'application/javascript' });
212
- const blobUrl = URL.createObjectURL(blob);
213
- try {
214
- // Import the cached script using importScripts
215
- importScripts(blobUrl);
216
- // Check if createTFLiteModule is now available
217
- if (typeof createTFLiteModule === 'undefined') {
218
- printLogs('[WasmWorkerService] createTFLiteModule not defined, falling back to package', '', 'WARN');
219
- yield this.loadFromPackage(currentModuleVersionJSON.version, modulePath, moduleName, params.usageScenario, params.cacheContent);
220
- return { message: 'Loaded from package (cache invalid)', status: this.lastLoadStatus };
221
- }
222
- this.wasmPrividModules = yield createTFLiteModule({ wasmBinary: cachedWasm });
223
- printLogs('[WasmWorkerService] ULTRA MODULES ', this.wasmPrividModules);
224
- if (!this.checkWasmLoaded) {
225
- yield this.initializeWasmSession(params.usageScenario, params.cacheContent);
226
- this.checkWasmLoaded = true;
227
- }
228
- printLogs('[WasmWorkerService] WASM MODULES: ', this.wasmPrividModules);
229
- if (!this.lastLoadStatus) {
230
- this.lastLoadStatus = { source: 'cache', versionMatch: true };
231
- }
232
- return { message: 'Loaded from cache (wasm and script)', status: this.lastLoadStatus };
233
- }
234
- catch (error) {
235
- printLogs('[WasmWorkerService] Error loading from cache:', error, 'ERROR');
236
- yield this.loadFromPackage(currentModuleVersionJSON.version, modulePath, moduleName, params.usageScenario, params.cacheContent);
237
- return { message: 'Loaded from package (cache error)', status: this.lastLoadStatus };
238
- }
239
- finally {
240
- // Clean up the blob URL
241
- URL.revokeObjectURL(blobUrl);
242
- }
243
- }
244
- }
245
- else if (this.wasmPrividModules && params.shouldRegenerateSession) {
246
- printLogs('[WasmWorkerService] Regenerating session as requested', '');
247
- const newSession = yield this.initializeWasmSession(params.usageScenario, params.cacheContent);
248
- if (!newSession) {
249
- printLogs('[WasmWorkerService] ERROR: Failed to regenerate session', '', 'ERROR');
250
- throw new Error('Session regeneration failed');
251
- }
252
- this.wasmSession = newSession;
253
- }
254
- else {
255
- yield this.loadFromPackage(currentModuleVersionJSON.version, modulePath, moduleName, params.usageScenario, params.cacheContent);
256
- return { message: 'Loaded', status: this.lastLoadStatus };
257
- }
258
- // Final verification that WASM is fully initialized
259
- if (!this.wasmPrividModules || !this.wasmSession) {
260
- const error = 'WASM modules loaded but session not initialized';
261
- printLogs(`[WasmWorkerService] ERROR: ${error}`, '', 'ERROR');
262
- throw new Error(error);
263
- }
264
- if (!this.lastLoadStatus) {
265
- this.lastLoadStatus = { source: 'cache', versionMatch: true };
266
- }
267
- return { message: 'Cache Loaded', status: this.lastLoadStatus };
268
- }
269
- yield this.loadFromPackage(currentModuleVersionJSON.version, modulePath, moduleName, params.usageScenario, params.cacheContent);
270
- // Final verification that WASM is fully initialized
271
- if (!this.wasmPrividModules || !this.wasmSession) {
272
- const error = 'WASM modules loaded but session not initialized';
273
- printLogs(`[WasmWorkerService] ERROR: ${error}`, '', 'ERROR');
274
- throw new Error(error);
275
- }
276
- if (!this.lastLoadStatus) {
277
- this.lastLoadStatus = { source: 'cdn', versionMatch: true };
278
- }
279
- return { message: 'Loaded', status: this.lastLoadStatus };
280
- });
281
- }
282
- loadFromPackage(wasmVersion, modulePath, moduleName, usageScenario, cache_content) {
283
- return __awaiter(this, void 0, void 0, function* () {
284
- printLogs('[WasmWorkerService loadFromPackage wasmVersion: ', wasmVersion);
285
- this.wasmPrividModules = yield this.loadWasmModule(modulePath, moduleName, true, wasmVersion);
203
+ // --- Resolve WASM module through tier pipeline ---
204
+ // Note: this.setCache may be undefined when cacheConfig is not passed in LoadParams.
205
+ // Default to true to match WasmOrchestratorService behavior (hardcodes cacheConfig: true).
206
+ const ctx = {
207
+ modulePath,
208
+ moduleName,
209
+ version: currentModuleVersionJSON.version,
210
+ saveCache: (_b = this.setCache) !== null && _b !== void 0 ? _b : true,
211
+ };
212
+ const result = yield this.resolveWasmModule(ctx);
213
+ this.wasmPrividModules = result.module;
214
+ this.lastLoadStatus = result.status;
215
+ // --- Initialize WASM session ---
286
216
  if (!this.checkWasmLoaded) {
287
- yield this.initializeWasmSession(usageScenario, cache_content);
217
+ yield this.initializeWasmSession(params.usageScenario, params.cacheContent);
288
218
  this.checkWasmLoaded = true;
289
219
  }
290
- return true;
220
+ // --- Final verification ---
221
+ if (!this.wasmPrividModules || !this.wasmSession) {
222
+ throw new Error('WASM modules loaded but session not initialized');
223
+ }
224
+ printLogs(`[WasmWorkerService] Load complete. Source: ${result.status.source}, Attempts: ${result.attempts.length}`, result.attempts);
225
+ return {
226
+ message: `Loaded from ${result.status.source}`,
227
+ status: this.lastLoadStatus,
228
+ };
291
229
  });
292
230
  }
293
231
  /**
@@ -300,85 +238,31 @@ export class WasmWorkerService {
300
238
  }
301
239
  return `../wasm/${relativePath}`;
302
240
  }
303
- loadWasmModule(modulePath, moduleName, saveCache, version) {
304
- return __awaiter(this, void 0, void 0, function* () {
305
- // If custom WASM config is provided (e.g., from iOS WebView), use it directly
306
- if (this.customWasm) {
307
- printLogs('[WasmWorkerService] Using custom WASM URL:', this.customWasm.url);
308
- // For custom URLs, we still need the JS file from the normal location
309
- const scriptUrls = {
310
- cdn: `${this.cdnUrl}/${WASM_ULTRA_FOLDER_NAME}/${modulePath}/${version}/${moduleName}.js`,
311
- local: this.getLocalWasmUrl(`${this.getWasmFolderName()}/${modulePath}/${version}/${moduleName}.js`),
312
- };
313
- const wasm = yield fetch(this.customWasm.url);
314
- if (!wasm.ok) {
315
- throw new Error(`Failed to fetch custom WASM from ${this.customWasm.url}: ${wasm.status}`);
316
- }
317
- const script = yield fetchResource(scriptUrls, this.useCdnLink);
318
- const scriptBuffer = yield script.text();
319
- const buffer = yield wasm.arrayBuffer();
320
- printLogs(`[WasmWorkerService] loadWasmModule script and buffer from custom URL': `, { scriptBuffer, buffer });
321
- const blob = new Blob([scriptBuffer], { type: 'application/javascript' });
322
- const blobUrl = URL.createObjectURL(blob);
323
- try {
324
- importScripts(blobUrl);
325
- if (typeof createTFLiteModule === 'undefined') {
326
- throw new Error('createTFLiteModule not defined after loading script');
327
- }
328
- const module = yield createTFLiteModule({ wasmBinary: buffer });
329
- printLogs('[WasmWorkerService] loadWasmModule module from custom URL: ', module);
330
- // Note: We don't cache when using custom URLs as they're iOS-specific
331
- return module;
332
- }
333
- catch (error) {
334
- printLogs('[WasmWorkerService] Error loading WASM module from custom URL:', error, 'ERROR');
335
- throw error;
336
- }
337
- finally {
338
- URL.revokeObjectURL(blobUrl);
339
- }
340
- }
341
- // Standard loading path (CDN or local)
342
- const wasmUrls = {
343
- cdn: `${this.cdnUrl}/${WASM_ULTRA_FOLDER_NAME}/${modulePath}/${version}/${moduleName}.wasm`,
344
- local: this.getLocalWasmUrl(`${this.getWasmFolderName()}/${modulePath}/${version}/${moduleName}.wasm`),
345
- };
346
- const scriptUrls = {
347
- cdn: `${this.cdnUrl}/${WASM_ULTRA_FOLDER_NAME}/${modulePath}/${version}/${moduleName}.js`,
348
- local: this.getLocalWasmUrl(`${this.getWasmFolderName()}/${modulePath}/${version}/${moduleName}.js`),
349
- };
350
- const wasm = yield fetchResource(wasmUrls, this.useCdnLink);
351
- const script = yield fetchResource(scriptUrls, this.useCdnLink);
352
- const scriptBuffer = yield script.text();
353
- const buffer = yield wasm.arrayBuffer();
354
- printLogs(`[WasmWorkerService] loadWasmModule script and buffer': `, { scriptBuffer, buffer });
355
- const blob = new Blob([scriptBuffer], { type: 'application/javascript' });
356
- const blobUrl = URL.createObjectURL(blob);
241
+ /**
242
+ * Loads a script via direct URL importScripts with CDN/local fallback.
243
+ * Avoids blob: URLs which are blocked by strict Content-Security-Policy.
244
+ */
245
+ importScriptFromUrl(scriptUrls) {
246
+ let localError;
247
+ try {
248
+ importScripts(scriptUrls.local);
249
+ return;
250
+ }
251
+ catch (error) {
252
+ localError = error;
253
+ printLogs('[WasmWorkerService] Local importScripts failed, trying CDN', localError, 'WARN');
254
+ }
255
+ if (this.useCdnLink) {
357
256
  try {
358
- // Import the script in the worker context using importScripts
359
- importScripts(blobUrl);
360
- // Check if createTFLiteModule is now available
361
- if (typeof createTFLiteModule === 'undefined') {
362
- throw new Error('createTFLiteModule not defined after loading script');
363
- }
364
- // Now createTFLiteModule should be available globally
365
- const module = yield createTFLiteModule({ wasmBinary: buffer });
366
- printLogs('[WasmWorkerService] loadWasmModule module: ', module);
367
- if (saveCache) {
368
- const moduleVersion = module.UTF8ToString(module._privid_get_version());
369
- yield writeToIndexedDB(WASM_ULTRA_FOLDER_NAME, buffer, scriptBuffer, moduleVersion);
370
- }
371
- return module;
372
- }
373
- catch (error) {
374
- printLogs('[WasmWorkerService] Error loading WASM module:', error, 'ERROR');
375
- throw error;
257
+ importScripts(scriptUrls.cdn);
376
258
  }
377
- finally {
378
- // Clean up the blob URL to free memory
379
- URL.revokeObjectURL(blobUrl);
259
+ catch (cdnError) {
260
+ throw new Error(`Both local and CDN importScripts failed. Local error: ${localError}; CDN error: ${cdnError}`);
380
261
  }
381
- });
262
+ }
263
+ else {
264
+ throw new Error(`Local importScripts failed and CDN is disabled: ${localError}`);
265
+ }
382
266
  }
383
267
  initializeWasmSession(usageScenario = '', cache_content = '') {
384
268
  return __awaiter(this, void 0, void 0, function* () {
@@ -403,6 +287,184 @@ export class WasmWorkerService {
403
287
  return wasmSessionPointer;
404
288
  });
405
289
  }
290
+ resolveWasmModule(ctx) {
291
+ return __awaiter(this, void 0, void 0, function* () {
292
+ const attempts = [];
293
+ const tiers = [];
294
+ console.log('[WasmWorkerService] resolveWasmModule ctx:', ctx);
295
+ // Build tier list based on configuration
296
+ if (this.customWasm) {
297
+ tiers.push({
298
+ source: 'custom',
299
+ obtain: () => this.obtainFromCustomUrl(this.customWasm, ctx.version),
300
+ shouldCache: false,
301
+ });
302
+ }
303
+ tiers.push({
304
+ source: 'cache',
305
+ obtain: () => this.obtainFromCache(ctx.version),
306
+ shouldCache: false,
307
+ });
308
+ tiers.push({
309
+ source: 'local',
310
+ obtain: () => this.obtainFromNetwork(ctx, 'local'),
311
+ shouldCache: ctx.saveCache,
312
+ });
313
+ if (this.useCdnLink) {
314
+ tiers.push({
315
+ source: 'cdn',
316
+ obtain: () => this.obtainFromNetwork(ctx, 'cdn'),
317
+ shouldCache: ctx.saveCache,
318
+ });
319
+ }
320
+ // Load the Emscripten JS runtime once for ctx.modulePath (SIMD or noSIMD).
321
+ // If SIMD compilation fails later, compileWasmBinary -> obtainFromNetworkWithFallback
322
+ // reloads the noSIMD JS runtime separately (it's a different Emscripten build).
323
+ // Wrapped in try-catch to add context: if this fails, no tier can succeed because
324
+ // createTFLiteModule won't be defined. The error is rethrown with the original message
325
+ // preserved so callers see both the context and the root cause.
326
+ try {
327
+ this.loadWasmRuntime(ctx);
328
+ }
329
+ catch (error) {
330
+ const msg = error instanceof Error ? error.message : String(error);
331
+ throw new Error(`WASM JS runtime failed to load for ${ctx.modulePath}/${ctx.version}: ${msg}`);
332
+ }
333
+ let fallback;
334
+ for (const tier of tiers) {
335
+ try {
336
+ const buffer = yield tier.obtain();
337
+ const validation = validateWasmBinary(buffer);
338
+ if (!validation.valid) {
339
+ throw new Error(`Validation failed: ${validation.reason}`);
340
+ }
341
+ const module = yield this.compileWasmBinary(buffer, ctx);
342
+ if (tier.shouldCache) {
343
+ yield writeToCacheQuietly(buffer, module, this.getWasmFolderName());
344
+ }
345
+ attempts.push({ source: tier.source, success: true });
346
+ // Determine the reported source. When the custom URL tier failed and we fell
347
+ // back to cache/CDN, the source is the successful tier but we also record the
348
+ // custom-fallback status for backward compatibility with existing consumers.
349
+ const reportedSource = (fallback === null || fallback === void 0 ? void 0 : fallback.originalSource) === 'custom' ? 'custom-fallback' : tier.source;
350
+ const versionMatch = reportedSource !== 'custom-fallback';
351
+ return {
352
+ module,
353
+ status: Object.assign({ source: reportedSource, versionMatch }, (fallback && { fallback })),
354
+ attempts,
355
+ };
356
+ }
357
+ catch (error) {
358
+ const errorMessage = error instanceof Error ? error.message : String(error);
359
+ attempts.push({ source: tier.source, success: false, error: errorMessage });
360
+ printLogs(`[WasmWorkerService] Tier '${tier.source}' failed: ${errorMessage}`, error, 'WARN');
361
+ // Record the first failure as the fallback reason (skip both 'local' and 'cdn' since both are network tiers)
362
+ if (!fallback && tier.source !== 'cdn' && tier.source !== 'local') {
363
+ fallback = {
364
+ originalSource: tier.source,
365
+ reason: classifyFailureReason(error),
366
+ };
367
+ }
368
+ // Only evict cache on corruption-related failures (validation failed, corrupted data).
369
+ // Do NOT evict on cache miss or version mismatch -- those are normal operational states.
370
+ if (tier.source === 'cache' && isCacheCorruptionFailure(error)) {
371
+ yield clearCacheEntry(this.getWasmFolderName()).catch(() => { });
372
+ }
373
+ }
374
+ }
375
+ throw new Error(`All WASM loading tiers failed. Attempts: ${JSON.stringify(attempts)}`);
376
+ });
377
+ }
378
+ loadWasmRuntime(ctx) {
379
+ const scriptUrls = {
380
+ cdn: `${this.cdnUrl}/${this.getWasmFolderName()}/${ctx.modulePath}/${ctx.version}/${ctx.moduleName}.js`,
381
+ local: this.getLocalWasmUrl(`${this.getWasmFolderName()}/${ctx.modulePath}/${ctx.version}/${ctx.moduleName}.js`),
382
+ };
383
+ this.importScriptFromUrl(scriptUrls);
384
+ if (typeof createTFLiteModule === 'undefined') {
385
+ throw new Error('createTFLiteModule not defined after loading WASM runtime');
386
+ }
387
+ }
388
+ obtainFromCache(expectedVersion) {
389
+ return __awaiter(this, void 0, void 0, function* () {
390
+ const cached = yield readFromIndexedDBWithTimeout(this.getWasmFolderName());
391
+ if (!cached || !cached.cachedWasm) {
392
+ throw new Error('Cache miss: no cached WASM found');
393
+ }
394
+ if (!checkCacheAndCurrentAreSameVersion(cached, { version: expectedVersion })) {
395
+ throw new Error(`Cache version mismatch: cached=${cached.version}, expected=${expectedVersion}`);
396
+ }
397
+ return cached.cachedWasm;
398
+ });
399
+ }
400
+ obtainFromCustomUrl(customWasm, expectedVersion) {
401
+ return __awaiter(this, void 0, void 0, function* () {
402
+ // Step 1: Validate the URL is accessible (HEAD request, matches existing behavior)
403
+ const isValid = yield validateCustomWasmUrl(customWasm.url);
404
+ if (!isValid) {
405
+ throw new Error(`Custom URL validation failed for ${customWasm.url}`);
406
+ }
407
+ // Step 2: Version check -- prevent loading a WASM binary with the wrong version,
408
+ // which could cause silent failures or crashes in the C++ layer.
409
+ if (customWasm.version !== expectedVersion) {
410
+ printLogs('[WasmWorkerService] Custom WASM version mismatch', { expected: expectedVersion, provided: customWasm.version }, 'WARN');
411
+ throw new Error(`Custom URL version mismatch: provided=${customWasm.version}, expected=${expectedVersion}`);
412
+ }
413
+ // Step 3: Fetch the binary
414
+ const response = yield fetch(customWasm.url);
415
+ if (!response.ok) {
416
+ throw new Error(`Custom URL fetch failed: ${response.status} for ${customWasm.url}`);
417
+ }
418
+ return response.arrayBuffer();
419
+ });
420
+ }
421
+ obtainFromNetwork(ctx, source) {
422
+ return __awaiter(this, void 0, void 0, function* () {
423
+ const wasmUrl = source === 'cdn'
424
+ ? `${this.cdnUrl}/${this.getWasmFolderName()}/${ctx.modulePath}/${ctx.version}/${ctx.moduleName}.wasm`
425
+ : this.getLocalWasmUrl(`${this.getWasmFolderName()}/${ctx.modulePath}/${ctx.version}/${ctx.moduleName}.wasm`);
426
+ const response = yield fetch(wasmUrl);
427
+ if (!response.ok) {
428
+ throw new Error(`Fetch failed: ${response.status} for ${wasmUrl}`);
429
+ }
430
+ return response.arrayBuffer();
431
+ });
432
+ }
433
+ compileWasmBinary(wasmBinary, ctx) {
434
+ return __awaiter(this, void 0, void 0, function* () {
435
+ try {
436
+ return yield createTFLiteModule({ wasmBinary });
437
+ }
438
+ catch (error) {
439
+ if (error instanceof WebAssembly.CompileError && ctx.modulePath === 'simd') {
440
+ printLogs('[WasmWorkerService] SIMD CompileError -- retrying with noSIMD', error, 'WARN');
441
+ return this.obtainFromNetworkWithFallback(ctx);
442
+ }
443
+ throw error;
444
+ }
445
+ });
446
+ }
447
+ obtainFromNetworkWithFallback(ctx) {
448
+ return __awaiter(this, void 0, void 0, function* () {
449
+ const noSimdCtx = Object.assign(Object.assign({}, ctx), { modulePath: 'nosimd' });
450
+ // Fetch noSIMD binary from network (local first, CDN fallback)
451
+ let buffer;
452
+ try {
453
+ buffer = yield this.obtainFromNetwork(noSimdCtx, 'local');
454
+ }
455
+ catch (localError) {
456
+ if (this.useCdnLink) {
457
+ buffer = yield this.obtainFromNetwork(noSimdCtx, 'cdn');
458
+ }
459
+ else {
460
+ throw new Error(`Local noSIMD fetch failed and CDN is disabled: ${localError}`);
461
+ }
462
+ }
463
+ // Load the noSIMD JS runtime (overwrites the global createTFLiteModule)
464
+ this.loadWasmRuntime(noSimdCtx);
465
+ return createTFLiteModule({ wasmBinary: buffer });
466
+ });
467
+ }
406
468
  ultraEnroll(params, resultCallback) {
407
469
  return __awaiter(this, void 0, void 0, function* () {
408
470
  callbackRegistry.result = resultCallback;
@@ -859,6 +921,7 @@ export class WasmWorkerService {
859
921
  yield this.moduleInitializationLock;
860
922
  }
861
923
  catch (error) {
924
+ printLogs('[WasmWorkerService] ensureModulesInitialized: Initialization failed during wait', error, 'ERROR');
862
925
  return false;
863
926
  }
864
927
  }
@@ -881,6 +944,7 @@ export class WasmWorkerService {
881
944
  }, this.proxiedErrorCallback);
882
945
  }
883
946
  catch (error) {
947
+ printLogs('[WasmWorkerService] ensureModulesInitialized: Failed to load WASM modules', error, 'ERROR');
884
948
  return false;
885
949
  }
886
950
  }