@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.
- package/dist/application/modules/core/document/DocumentService.js +16 -31
- package/dist/application/modules/core/document/DocumentService.js.map +1 -1
- package/dist/application/modules/core/document/document.types.d.ts +151 -0
- package/dist/application/modules/core/document/document.utils.d.ts +23 -1
- package/dist/application/modules/core/document/document.utils.js +123 -20
- package/dist/application/modules/core/document/document.utils.js.map +1 -1
- package/dist/application/modules/core/face/FaceService.d.ts +1 -2
- package/dist/application/modules/core/face/FaceService.js +11 -23
- package/dist/application/modules/core/face/FaceService.js.map +1 -1
- package/dist/application/modules/core/face/face.types.d.ts +104 -2
- package/dist/application/modules/core/face/face.types.js.map +1 -1
- package/dist/application/modules/core/face/face.utils.d.ts +14 -0
- package/dist/application/modules/core/face/face.utils.js +86 -2
- package/dist/application/modules/core/face/face.utils.js.map +1 -1
- package/dist/application/modules/internal/feature-flag/LDFeatureFlagService.js +0 -1
- package/dist/application/modules/internal/feature-flag/LDFeatureFlagService.js.map +1 -1
- package/dist/application/modules/internal/shared/index.d.ts +1 -0
- package/dist/application/modules/internal/shared/index.js +1 -0
- package/dist/application/modules/internal/shared/index.js.map +1 -1
- package/dist/application/modules/internal/shared/shared.types.d.ts +21 -0
- package/dist/application/modules/internal/shared/shared.types.js +2 -0
- package/dist/application/modules/internal/shared/shared.types.js.map +1 -0
- package/dist/application/modules/internal/shared/shared.utils.d.ts +6 -0
- package/dist/application/modules/internal/shared/shared.utils.js +26 -3
- package/dist/application/modules/internal/shared/shared.utils.js.map +1 -1
- package/dist/application/modules/internal/wasm-orchestrator/WasmOrchestratorService.d.ts +0 -1
- package/dist/application/modules/internal/wasm-orchestrator/WasmOrchestratorService.js +87 -208
- package/dist/application/modules/internal/wasm-orchestrator/WasmOrchestratorService.js.map +1 -1
- package/dist/application/modules/internal/wasm-orchestrator/index.d.ts +1 -2
- package/dist/application/modules/internal/wasm-orchestrator/index.js +0 -2
- package/dist/application/modules/internal/wasm-orchestrator/index.js.map +1 -1
- package/dist/application/modules/internal/wasm-orchestrator/wasm-orchestrator.types.d.ts +7 -19
- package/dist/application/modules/internal/wasm-orchestrator/wasm-orchestrator.utils.d.ts +18 -0
- package/dist/application/modules/internal/wasm-orchestrator/wasm-orchestrator.utils.js +69 -10
- package/dist/application/modules/internal/wasm-orchestrator/wasm-orchestrator.utils.js.map +1 -1
- package/dist/application/modules/internal/wasm-orchestrator/wasm-orchestrator.utils.test.d.ts +1 -0
- package/dist/application/modules/internal/wasm-orchestrator/wasm-orchestrator.utils.test.js +218 -0
- package/dist/application/modules/internal/wasm-orchestrator/wasm-orchestrator.utils.test.js.map +1 -0
- package/dist/application/modules/support/camera/CameraServiceFactory.js +0 -1
- package/dist/application/modules/support/camera/CameraServiceFactory.js.map +1 -1
- package/dist/application/modules/support/camera/camera.types.d.ts +8 -3
- package/dist/application/modules/support/camera/camera.types.js +9 -5
- package/dist/application/modules/support/camera/camera.types.js.map +1 -1
- package/dist/application/modules/support/camera/camera.utils.js +0 -1
- package/dist/application/modules/support/camera/camera.utils.js.map +1 -1
- package/dist/application/modules/support/camera/index.d.ts +2 -1
- package/dist/application/modules/support/camera/index.js +1 -0
- package/dist/application/modules/support/camera/index.js.map +1 -1
- package/dist/application/modules/support/camera/services/BaseCameraService.js +0 -3
- package/dist/application/modules/support/camera/services/BaseCameraService.js.map +1 -1
- package/dist/application/modules/support/camera/services/DesktopCameraService.js +0 -1
- package/dist/application/modules/support/camera/services/DesktopCameraService.js.map +1 -1
- package/dist/application/modules/support/camera/services/FirefoxCameraService.js +0 -1
- package/dist/application/modules/support/camera/services/FirefoxCameraService.js.map +1 -1
- package/dist/application/modules/support/camera/services/MacSafariCameraService.js +0 -1
- package/dist/application/modules/support/camera/services/MacSafariCameraService.js.map +1 -1
- package/dist/application/modules/support/camera/services/MobileCameraService.js +1 -3
- package/dist/application/modules/support/camera/services/MobileCameraService.js.map +1 -1
- package/dist/application/modules/support/engine/EngineService.js +0 -2
- package/dist/application/modules/support/engine/EngineService.js.map +1 -1
- package/dist/application/modules/support/engine/engine.types.d.ts +2 -21
- package/dist/application/modules/support/engine/engine.utils.js +1 -3
- package/dist/application/modules/support/engine/engine.utils.js.map +1 -1
- package/dist/application/modules/support/engine/index.d.ts +1 -1
- package/dist/application/modules/support/permissions/PermissionsService.js +0 -2
- package/dist/application/modules/support/permissions/PermissionsService.js.map +1 -1
- package/dist/application/modules/support/permissions/index.js +0 -1
- package/dist/application/modules/support/permissions/index.js.map +1 -1
- package/dist/application/workers/wasm/WasmWorkerService.d.ts +14 -3
- package/dist/application/workers/wasm/WasmWorkerService.js +270 -206
- package/dist/application/workers/wasm/WasmWorkerService.js.map +1 -1
- package/dist/application/workers/wasm/wasm-worker.types.d.ts +19 -1
- package/dist/application/workers/wasm/wasm-worker.utils.d.ts +28 -1
- package/dist/application/workers/wasm/wasm-worker.utils.js +132 -22
- package/dist/application/workers/wasm/wasm-worker.utils.js.map +1 -1
- package/dist/application/workers/wasm/wasm-worker.utils.test.d.ts +1 -0
- package/dist/application/workers/wasm/wasm-worker.utils.test.js +123 -0
- package/dist/application/workers/wasm/wasm-worker.utils.test.js.map +1 -0
- package/dist/index.d.ts +46 -35
- package/dist/index.js +104 -77
- package/dist/index.js.map +1 -1
- package/package.json +19 -11
- package/wasm/ultra/manifest.json +3 -3
- package/workers/wasm-new.worker.js +1 -1
- package/workers/wasm-new.worker.js.map +3 -3
- package/dist/apiUtils.d.ts +0 -46
- package/dist/apiUtils.js +0 -923
- package/dist/apiUtils.js.map +0 -1
- package/dist/cameraUtils.d.ts +0 -77
- package/dist/cameraUtils.js +0 -362
- package/dist/cameraUtils.js.map +0 -1
- package/dist/constants.d.ts +0 -9
- package/dist/constants.js +0 -14
- package/dist/constants.js.map +0 -1
- package/dist/createCallback.d.ts +0 -57
- package/dist/createCallback.js +0 -336
- package/dist/createCallback.js.map +0 -1
- package/dist/dbUtils.d.ts +0 -14
- package/dist/dbUtils.js +0 -149
- package/dist/dbUtils.js.map +0 -1
- package/dist/envUtils.d.ts +0 -4
- package/dist/envUtils.js +0 -17
- package/dist/envUtils.js.map +0 -1
- package/dist/faceModule.d.ts +0 -233
- package/dist/faceModule.js +0 -1021
- package/dist/faceModule.js.map +0 -1
- package/dist/main.d.ts +0 -48
- package/dist/main.js +0 -111
- package/dist/main.js.map +0 -1
- package/dist/types.d.ts +0 -139
- package/dist/types.js +0 -78
- package/dist/types.js.map +0 -1
- package/dist/utils.d.ts +0 -90
- package/dist/utils.js +0 -587
- 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,
|
|
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
|
-
|
|
169
|
-
//
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
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,
|
|
217
|
+
yield this.initializeWasmSession(params.usageScenario, params.cacheContent);
|
|
288
218
|
this.checkWasmLoaded = true;
|
|
289
219
|
}
|
|
290
|
-
|
|
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
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
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
|
-
|
|
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
|
-
|
|
378
|
-
|
|
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
|
}
|