1/* 2 * Copyright (C) 2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16importScripts('trace_streamer_builtin.js'); 17import { execProtoForWorker } from './data-trafic/utils/ExecProtoForWorker'; 18import { QueryEnum, TraficEnum } from './data-trafic/utils/QueryEnum'; 19import { temp_init_sql_list } from './TempSql'; 20// @ts-ignore 21import { BatchSphData } from '../proto/SphBaseData'; 22 23let Module: any = null; 24let enc = new TextEncoder(); 25let dec = new TextDecoder(); 26let arr: Uint8Array | undefined; 27let start: number; 28const REQ_BUF_SIZE = 4 * 1024 * 1024; 29let reqBufferAddr: number = -1; 30let bufferSlice: Array<any> = []; 31let json: string; 32 33let headUnitArray: Uint8Array | undefined; 34let thirdWasmMap = new Map(); 35let thirdJsonResult = new Map(); 36 37let CONTENT_TYPE_CMDLINES = 2; 38let CONTENT_TYPE_TGIDS = 3; 39 40let arkTsData: Array<Uint8Array> = []; 41let arkTsDataSize: number = 0; 42 43let currentAction: string = ''; 44let currentActionId: string = ''; 45let ffrtFileCacheKey = '-1'; 46 47let protoDataMap: Map<QueryEnum, any> = new Map<QueryEnum, any>(); 48function clear() { 49 if (Module != null) { 50 Module._TraceStreamerReset(); 51 Module = null; 52 } 53 if (arr) { 54 arr = undefined; 55 } 56 if (headUnitArray) { 57 headUnitArray = undefined; 58 } 59 if (bufferSlice) { 60 bufferSlice.length = 0; 61 } 62 thirdWasmMap.clear(); 63 thirdJsonResult.clear(); 64} 65 66self.addEventListener('unhandledrejection', (err) => { 67 self.postMessage({ 68 id: currentActionId, 69 action: currentAction, 70 init: false, 71 status: false, 72 msg: err.reason.message, 73 }); 74}); 75 76function initWASM() { 77 return new Promise((resolve, reject) => { 78 //@ts-ignore 79 let wasm = trace_streamer_builtin_wasm; 80 Module = wasm({ 81 locateFile: (s: any) => { 82 return s; 83 }, 84 print: (line: any) => {}, 85 printErr: (line: any) => {}, 86 onRuntimeInitialized: () => { 87 resolve('ok'); 88 }, 89 onAbort: () => { 90 reject('on abort'); 91 }, 92 }); 93 }); 94} 95 96function initThirdWASM(wasmFunctionName: string) { 97 function callModelFun(functionName: string) { 98 let func = eval(functionName); 99 return new func({ 100 locateFile: (s: any) => { 101 return s; 102 }, 103 print: (line: any) => {}, 104 printErr: (line: any) => {}, 105 onRuntimeInitialized: () => {}, 106 onAbort: () => {}, 107 }); 108 } 109 110 return callModelFun(wasmFunctionName); 111} 112 113let merged = () => { 114 let length = 0; 115 bufferSlice.forEach((item) => { 116 length += item.length; 117 }); 118 let mergedArray = new Uint8Array(length); 119 let offset = 0; 120 bufferSlice.forEach((item) => { 121 mergedArray.set(item, offset); 122 offset += item.length; 123 }); 124 return mergedArray; 125}; 126 127let translateJsonString = (str: string): string => { 128 return str // .padding 129 .replace(/[\t|\r|\n]/g, ''); 130}; 131 132let convertJSON = () => { 133 try { 134 let str = dec.decode(arr); 135 let jsonArray: Array<any> = []; 136 str = str.substring(str.indexOf('\n') + 1); 137 if (!str) { 138 } else { 139 let parse; 140 let tansStr: string; 141 try { 142 tansStr = str.replace(/[\t\r\n]/g, ''); 143 parse = JSON.parse(tansStr); 144 } catch { 145 try { 146 tansStr = tansStr!.replace(/[^\x20-\x7E]/g, '?'); //匹配乱码字 符,将其转换为? 147 parse = JSON.parse(tansStr); 148 } catch { 149 tansStr = tansStr!.replace(/\\/g, '\\\\'); 150 parse = JSON.parse(tansStr); 151 } 152 } 153 let columns = parse.columns; 154 let values = parse.values; 155 for (let i = 0; i < values.length; i++) { 156 let obj: any = {}; 157 for (let j = 0; j < columns.length; j++) { 158 obj[columns[j]] = values[i][j]; 159 } 160 jsonArray.push(obj); 161 } 162 } 163 return jsonArray; 164 } catch (e) { 165 self.postMessage({ 166 id: currentActionId, 167 action: currentAction, 168 init: false, 169 status: false, 170 msg: (e as any).message, 171 }); 172 return []; 173 } 174}; 175 176/** 177 * 计算预留缓存空间,如果空间不够,则删除部分缓存 178 * @param size 179 */ 180function saveTraceFileBuffer(key: string, buffer: ArrayBuffer): void { 181 obligateFileBufferSpace(buffer.byteLength).then(() => { 182 caches.open(key).then((cache) => { 183 let headers = new Headers(); 184 headers.append('Content-Length', `${buffer.byteLength}`); 185 headers.append('Content-Type', 'application/octet-stream'); 186 cache 187 .put( 188 key, 189 new Response(buffer, { 190 status: 200, 191 headers: headers, 192 }) 193 ) 194 .then(); 195 }); 196 }); 197} 198 199async function obligateFileBufferSpace(size: number): Promise<void> { 200 let es = await navigator.storage.estimate(); 201 let remainderByte = (es.quota || 0) - (es.usage || 0) - 20 * 1024 * 1024; 202 if (remainderByte < size) { 203 let keys = await caches.keys(); 204 keys.sort((keyA, keyB) => { 205 if (keyA.includes('/') && keyB.includes('/')) { 206 let splitA = keyA.split('/'); 207 let splitB = keyB.split('/'); 208 let timeA = splitA[splitA.length - 1].split('-')[0]; 209 let timeB = splitB[splitB.length - 1].split('-')[0]; 210 return parseInt(timeA) - parseInt(timeB); 211 } else { 212 return 0; 213 } 214 }); 215 let needSize = size - remainderByte; 216 for (let key of keys) { 217 await caches.delete(key); 218 let keySize = parseInt(key.split('-')[1]); 219 if (keySize > needSize) { 220 return; 221 } else { 222 needSize -= keySize; 223 } 224 } 225 } 226} 227 228self.onmessage = async (e: MessageEvent) => { 229 currentAction = e.data.action; 230 currentActionId = e.data.id; 231 let typeLength = 4; 232 if (e.data.action === 'reset') { 233 clear(); 234 } else if (e.data.action === 'open') { 235 await initWASM(); 236 ffrtFileCacheKey = '-1'; 237 // @ts-ignore 238 self.postMessage({ 239 id: e.data.id, 240 action: e.data.action, 241 ready: true, 242 index: 0, 243 }); 244 let uint8Array = new Uint8Array(e.data.buffer); 245 let callback = (heapPtr: number, size: number, isEnd: number) => { 246 let out: Uint8Array = Module.HEAPU8.slice(heapPtr, heapPtr + size); 247 bufferSlice.push(out); 248 if (isEnd == 1) { 249 arr = merged(); 250 bufferSlice.length = 0; 251 } 252 }; 253 let fn = Module.addFunction(callback, 'viii'); 254 reqBufferAddr = Module._Initialize(fn, REQ_BUF_SIZE); 255 let ffrtConvertCallback = (heapPtr: number, size: number, isEnd: number) => { 256 if (isEnd !== 1) { 257 let out: Uint8Array = Module.HEAPU8.slice(heapPtr, heapPtr + size); 258 bufferSlice.push(out); 259 } else { 260 arr = merged(); 261 bufferSlice.length = 0; 262 ffrtFileCacheKey = `ffrt/${new Date().getTime()}-${arr.buffer.byteLength}`; 263 saveTraceFileBuffer(ffrtFileCacheKey, arr.buffer); 264 } 265 }; 266 let tlvResultCallback = (heapPtr: number, size: number, type: number, isEnd: number) => { 267 let out: Uint8Array = Module.HEAPU8.slice(heapPtr, heapPtr + size); 268 protoDataMap.set(type, BatchSphData.decode(out).values); 269 }; 270 let fn1 = Module.addFunction(callback, 'viii'); 271 let fn2 = Module.addFunction(ffrtConvertCallback, 'viii'); 272 let tlvResultFun = Module.addFunction(tlvResultCallback, 'viiii'); 273 Module._TraceStreamer_Set_Log_Level(5); 274 reqBufferAddr = Module._Initialize(REQ_BUF_SIZE, fn1, tlvResultFun, fn2); 275 let parseConfig = e.data.parseConfig; 276 if (parseConfig !== '') { 277 let parseConfigArray = enc.encode(parseConfig); 278 let parseConfigAddr = Module._InitializeParseConfig(1024); 279 Module.HEAPU8.set(parseConfigArray, parseConfigAddr); 280 Module._TraceStreamerParserConfigEx(parseConfigArray.length); 281 } 282 let wasmConfigStr = e.data.wasmConfig; 283 if (wasmConfigStr != '' && wasmConfigStr.indexOf('WasmFiles') != -1) { 284 let wasmConfig = JSON.parse(wasmConfigStr); 285 let wasmConfigs = wasmConfig.WasmFiles; 286 let itemArray = wasmConfigs.map((item: any) => { 287 return item.componentId + ';' + item.pluginName; 288 }); 289 let thirdWasmStr: string = itemArray.join(';'); 290 let configUintArray = enc.encode(thirdWasmStr + ';'); 291 Module.HEAPU8.set(configUintArray, reqBufferAddr); 292 Module._TraceStreamer_Init_ThirdParty_Config(configUintArray.length); 293 let first = true; 294 let sendDataCallback = (heapPtr: number, size: number, componentID: number) => { 295 if (componentID === 100) { 296 if (first) { 297 first = false; 298 headUnitArray = Module.HEAPU8.slice(heapPtr, heapPtr + size); 299 } 300 return; 301 } 302 let configs = wasmConfigs.filter((wasmConfig: any) => { 303 return wasmConfig.componentId == componentID; 304 }); 305 if (configs.length > 0) { 306 let config = configs[0]; 307 let model = thirdWasmMap.get(componentID); 308 if (!model && config.componentId === componentID) { 309 importScripts(config.wasmJsName); 310 setThirdWasmMap(config, heapPtr, size, componentID); 311 } else { 312 let mm = model.model; 313 let out: Uint8Array = Module.HEAPU8.slice(heapPtr, heapPtr + size); 314 mm.HEAPU8.set(out, model.bufferAddr); 315 mm._ParserData(out.length, componentID); 316 } 317 } 318 }; 319 let fn1 = Module.addFunction(sendDataCallback, 'viii'); 320 let reqBufferAddr1 = Module._TraceStreamer_Set_ThirdParty_DataDealer(fn1, REQ_BUF_SIZE); 321 } 322 function initTraceRange(thirdMode: any): any { 323 let updateTraceTimeCallBack = (heapPtr: number, size: number) => { 324 let out: Uint8Array = thirdMode.HEAPU8.slice(heapPtr, heapPtr + size); 325 Module.HEAPU8.set(out, reqBufferAddr); 326 Module._UpdateTraceTime(out.length); 327 }; 328 let traceRangeFn = thirdMode.addFunction(updateTraceTimeCallBack, 'vii'); 329 let mm = thirdMode._InitTraceRange(traceRangeFn, 1024); 330 return mm; 331 } 332 function setThirdWasmMap(config: any, heapPtr: number, size: number, componentID: number) { 333 let thirdMode = initThirdWASM(config.wasmName); 334 let configPluginName = config.pluginName; 335 let pluginNameUintArray = enc.encode(configPluginName); 336 let pluginNameBuffer = thirdMode._InitPluginName(pluginNameUintArray.length); 337 thirdMode.HEAPU8.set(pluginNameUintArray, pluginNameBuffer); 338 thirdMode._TraceStreamerGetPluginNameEx(configPluginName.length); 339 let thirdQueryDataCallBack = (heapPtr: number, size: number, isEnd: number, isConfig: number) => { 340 if (isConfig == 1) { 341 let out: Uint8Array = thirdMode.HEAPU8.slice(heapPtr, heapPtr + size); 342 thirdJsonResult.set(componentID, { 343 jsonConfig: dec.decode(out), 344 disPlayName: config.disPlayName, 345 pluginName: config.pluginName, 346 }); 347 } else { 348 let out: Uint8Array = thirdMode.HEAPU8.slice(heapPtr, heapPtr + size); 349 bufferSlice.push(out); 350 if (isEnd == 1) { 351 arr = merged(); 352 bufferSlice.length = 0; 353 } 354 } 355 }; 356 let fn = thirdMode.addFunction(thirdQueryDataCallBack, 'viiii'); 357 let thirdreqBufferAddr = thirdMode._Init(fn, REQ_BUF_SIZE); 358 let mm = initTraceRange(thirdMode); 359 thirdMode._TraceStreamer_In_JsonConfig(); 360 thirdMode.HEAPU8.set(headUnitArray, thirdreqBufferAddr); 361 thirdMode._ParserData(headUnitArray!.length, 100); 362 let out: Uint8Array = Module.HEAPU8.slice(heapPtr, heapPtr + size); 363 thirdMode.HEAPU8.set(out, thirdreqBufferAddr); 364 thirdMode._ParserData(out.length, componentID); 365 thirdWasmMap.set(componentID, { 366 model: thirdMode, 367 bufferAddr: thirdreqBufferAddr, 368 }); 369 } 370 let wrSize = 0; 371 let r2 = -1; 372 let rowTraceStr = Array.from(new Uint16Array(e.data.buffer.slice(0, 2))); 373 if (rowTraceStr[0] === 57161) { 374 let commonDataOffsetList: Array<{ 375 startOffset: number; 376 endOffset: number; 377 }> = []; 378 let offset = 12; 379 let tlvTypeLength = 4; 380 let headArray = uint8Array.slice(0, offset); 381 let commonTotalLength = 0; 382 while (offset < uint8Array.length) { 383 let commonDataOffset = { 384 startOffset: offset, 385 endOffset: offset, 386 }; 387 let dataTypeData = e.data.buffer.slice(offset, offset + tlvTypeLength); 388 offset += tlvTypeLength; 389 let dataType = Array.from(new Uint32Array(dataTypeData)); 390 let currentLData = e.data.buffer.slice(offset, offset + tlvTypeLength); 391 offset += tlvTypeLength; 392 let currentVLength = Array.from(new Uint32Array(currentLData)); 393 offset += currentVLength[0]; 394 commonDataOffset.endOffset = offset; 395 if (dataType[0] === CONTENT_TYPE_CMDLINES || dataType[0] === CONTENT_TYPE_TGIDS) { 396 commonTotalLength += commonDataOffset.endOffset - commonDataOffset.startOffset; 397 commonDataOffsetList.push(commonDataOffset); 398 } 399 } 400 let frontData = new Uint8Array(headArray.byteLength + commonTotalLength); 401 // HeadArray 402 frontData.set(headArray, 0); 403 let lengthOffset = headArray.byteLength; 404 // common Data 405 commonDataOffsetList.forEach((item) => { 406 let commonData = uint8Array.slice(item.startOffset, item.endOffset); 407 frontData.set(commonData, lengthOffset); 408 lengthOffset += commonData.byteLength; 409 }); 410 let freeData = uint8Array.slice(12); 411 let final = new Uint8Array(frontData.length + freeData.length); 412 final.set(frontData); 413 final.set(freeData, frontData.length); 414 wrSize = 0; 415 while (wrSize < final.length) { 416 const sliceLen = Math.min(final.length - wrSize, REQ_BUF_SIZE); 417 const dataSlice = final.subarray(wrSize, wrSize + sliceLen); 418 Module.HEAPU8.set(dataSlice, reqBufferAddr); 419 wrSize += sliceLen; 420 r2 = Module._TraceStreamerParseDataEx(sliceLen, wrSize === final.length ? 1 : 0); 421 if (r2 === -1) { 422 break; 423 } 424 } 425 } else { 426 while (wrSize < uint8Array.length) { 427 const sliceLen = Math.min(uint8Array.length - wrSize, REQ_BUF_SIZE); 428 const dataSlice = uint8Array.subarray(wrSize, wrSize + sliceLen); 429 Module.HEAPU8.set(dataSlice, reqBufferAddr); 430 wrSize += sliceLen; 431 r2 = Module._TraceStreamerParseDataEx(sliceLen, wrSize === uint8Array.length ? 1 : 0); 432 if (r2 == -1) { 433 break; 434 } 435 } 436 } 437 Module._TraceStreamerParseDataOver(); 438 for (let value of thirdWasmMap.values()) { 439 value.model._TraceStreamer_In_ParseDataOver(); 440 } 441 if (r2 == -1) { 442 // @ts-ignore 443 self.postMessage({ 444 id: e.data.id, 445 action: e.data.action, 446 init: false, 447 msg: 'parse data error', 448 }); 449 return; 450 } 451 temp_init_sql_list.forEach((item, index) => { 452 let r = createView(item); 453 // @ts-ignore 454 self.postMessage({ id: e.data.id, ready: true, index: index + 1 }); 455 }); 456 self.postMessage( 457 { 458 id: e.data.id, 459 action: e.data.action, 460 init: true, 461 msg: 'ok', 462 configSqlMap: thirdJsonResult, 463 buffer: e.data.buffer, 464 fileKey: ffrtFileCacheKey, 465 }, 466 // @ts-ignore 467 [e.data.buffer] 468 ); 469 } else if (e.data.action === 'exec') { 470 query(e.data.name, e.data.sql, e.data.params); 471 let jsonArray = convertJSON(); 472 // @ts-ignore 473 self.postMessage({ 474 id: e.data.id, 475 action: e.data.action, 476 results: jsonArray, 477 }); 478 } else if (e.data.action === 'exec-proto') { 479 execProtoForWorker(e.data, (sql: string) => { 480 let sqlUintArray = enc.encode(sql); 481 if (e.data.params.trafic !== TraficEnum.ProtoBuffer) { 482 Module.HEAPU8.set(sqlUintArray, reqBufferAddr); 483 Module._TraceStreamerSqlQueryEx(sqlUintArray.length); 484 let jsonArray = convertJSON(); 485 return jsonArray; 486 } else { 487 let allArray = new Uint8Array(typeLength + sqlUintArray.length); 488 allArray[0] = e.data.name; 489 allArray.set(sqlUintArray, typeLength); 490 Module.HEAPU8.set(allArray, reqBufferAddr); 491 Module._TraceStreamerSqlQueryToProtoCallback(allArray.length); 492 let finalArrayBuffer = []; 493 if (protoDataMap.has(e.data.name)) { 494 finalArrayBuffer = protoDataMap.get(e.data.name); 495 protoDataMap.delete(e.data.name); 496 } 497 return finalArrayBuffer; 498 } 499 }); 500 } else if (e.data.action == 'exec-buf') { 501 query(e.data.name, e.data.sql, e.data.params); 502 self.postMessage( 503 { id: e.data.id, action: e.data.action, results: arr!.buffer }, 504 // @ts-ignore 505 [arr.buffer] 506 ); 507 } else if (e.data.action.startsWith('exec-sdk')) { 508 querySdk(e.data.name, e.data.sql, e.data.params, e.data.action); 509 let jsonArray = convertJSON(); 510 // @ts-ignore 511 self.postMessage({ 512 id: e.data.id, 513 action: e.data.action, 514 results: jsonArray, 515 }); 516 } else if (e.data.action.startsWith('exec-metric')) { 517 queryMetric(e.data.sql); 518 let metricResult = dec.decode(arr); 519 // @ts-ignore 520 self.postMessage({ 521 id: e.data.id, 522 action: e.data.action, 523 results: metricResult, 524 }); 525 } else if (e.data.action == 'init-port') { 526 let port = e.ports[0]; 527 port.onmessage = (me) => { 528 query(me.data.action, me.data.sql, me.data.params); 529 let msg = { 530 id: me.data.id, 531 action: me.data.action, 532 results: arr!.buffer, 533 }; 534 port.postMessage(msg, [arr!.buffer]); 535 }; 536 } else if (e.data.action == 'download-db') { 537 let bufferSliceUint: Array<any> = []; 538 let mergedUint = () => { 539 let length = 0; 540 bufferSliceUint.forEach((item) => { 541 length += item.length; 542 }); 543 let mergedArray = new Uint8Array(length); 544 let offset = 0; 545 bufferSliceUint.forEach((item) => { 546 mergedArray.set(item, offset); 547 offset += item.length; 548 }); 549 return mergedArray; 550 }; 551 let getDownloadDb = (heapPtr: number, size: number, isEnd: number) => { 552 let out: Uint8Array = Module.HEAPU8.slice(heapPtr, heapPtr + size); 553 bufferSliceUint.push(out); 554 if (isEnd == 1) { 555 let arr: Uint8Array = mergedUint(); 556 self.postMessage({ 557 id: e.data.id, 558 action: e.data.action, 559 results: arr, 560 }); 561 } 562 }; 563 let fn1 = Module.addFunction(getDownloadDb, 'viii'); 564 Module._WasmExportDatabase(fn1); 565 } else if (e.data.action === 'upload-so') { 566 uploadSoActionId = e.data.id; 567 let fileList = e.data.params as Array<File>; 568 if (fileList) { 569 soFileList = fileList; 570 uploadFileIndex = 0; 571 if (!uploadSoCallbackFn) { 572 uploadSoCallbackFn = Module.addFunction(uploadSoCallBack, 'viii'); 573 } 574 uploadSoFile(soFileList[uploadFileIndex]).then(); 575 } 576 } else if (e.data.action === 'cut-file') { 577 cutFileByRange(e); 578 } else if (e.data.action === 'long_trace') { 579 await initWASM(); 580 let result = {}; 581 let headArray = e.data.params.headArray; 582 let timStamp = e.data.params.timeStamp; 583 let allIndexDataList = e.data.params.splitDataList; 584 let splitFileInfos = e.data.params.splitFileInfo as Array<{ 585 fileType: string; 586 startIndex: number; 587 endIndex: number; 588 size: number; 589 }>; 590 let maxSize = 48 * 1024 * 1024; 591 let maxPageNum = headArray.length / 1024; 592 let currentPageNum = 0; 593 let splitReqBufferAddr: number; 594 if (splitFileInfos) { 595 let splitFileInfo = splitFileInfos.filter((splitFileInfo) => splitFileInfo.fileType !== 'trace'); 596 if (splitFileInfo && splitFileInfo.length > 0) { 597 let traceFileType: string = ''; 598 let db = await openDB(); 599 let newCutFilePageInfo: Map< 600 string, 601 { 602 traceFileType: string; 603 dataArray: [{ data: Uint8Array | Array<{ offset: number; size: number }>; dataTypes: string }]; 604 } 605 > = new Map(); 606 let cutFileCallBack = (heapPtr: number, size: number, dataType: number, isEnd: number) => { 607 let key = `${traceFileType}_${currentPageNum}`; 608 let out: Uint8Array = Module.HEAPU8.slice(heapPtr, heapPtr + size); 609 if (DataTypeEnum.data === dataType) { 610 if (traceFileType === 'arkts') { 611 arkTsData.push(out); 612 arkTsDataSize += size; 613 } else { 614 if (newCutFilePageInfo.has(key)) { 615 let newVar = newCutFilePageInfo.get(key); 616 newVar?.dataArray.push({ data: out, dataTypes: 'data' }); 617 } else { 618 newCutFilePageInfo.set(key, { 619 traceFileType: traceFileType, 620 dataArray: [{ data: out, dataTypes: 'data' }], 621 }); 622 } 623 } 624 } else if (DataTypeEnum.json === dataType) { 625 let cutFilePageInfo = newCutFilePageInfo.get(key); 626 if (cutFilePageInfo) { 627 let jsonStr: string = dec.decode(out); 628 let jsonObj = JSON.parse(jsonStr); 629 let valueArray: Array<{ offset: number; size: number }> = jsonObj.value; 630 cutFilePageInfo.dataArray.push({ data: valueArray, dataTypes: 'json' }); 631 } 632 } 633 }; 634 splitReqBufferAddr = Module._InitializeSplitFile(Module.addFunction(cutFileCallBack, 'viiii'), REQ_BUF_SIZE); 635 Module.HEAPU8.set(headArray, splitReqBufferAddr); 636 Module._TraceStreamerGetLongTraceTimeSnapEx(headArray.length); 637 for (let fileIndex = 0; fileIndex < splitFileInfo.length; fileIndex++) { 638 let fileInfo = splitFileInfo[fileIndex]; 639 traceFileType = fileInfo.fileType; 640 for (let pageNum = 0; pageNum < maxPageNum; pageNum++) { 641 currentPageNum = pageNum; 642 await splitFileAndSave( 643 timStamp, 644 fileInfo.fileType, 645 fileInfo.startIndex, 646 fileInfo.endIndex, 647 fileInfo.size, 648 db, 649 pageNum, 650 maxSize, 651 splitReqBufferAddr 652 ); 653 await initWASM(); 654 splitReqBufferAddr = Module._InitializeSplitFile( 655 Module.addFunction(cutFileCallBack, 'viiii'), 656 REQ_BUF_SIZE 657 ); 658 Module.HEAPU8.set(headArray, splitReqBufferAddr); 659 Module._TraceStreamerGetLongTraceTimeSnapEx(headArray.length); 660 } 661 } 662 for (const [fileTypePageNum, fileMessage] of newCutFilePageInfo) { 663 let fileTypePageNumArr = fileTypePageNum.split('_'); 664 let fileType = fileTypePageNumArr[0]; 665 let pageNum = Number(fileTypePageNumArr[1]); 666 let saveIndex = 0; 667 let saveStartOffset = 0; 668 let dataArray = fileMessage.dataArray; 669 let currentChunk = new Uint8Array(maxSize); 670 let currentChunkOffset = 0; 671 for (let fileDataIndex = 0; fileDataIndex < dataArray.length; fileDataIndex++) { 672 let receiveData = dataArray[fileDataIndex]; 673 if (receiveData.dataTypes === 'data') { 674 let receiveDataArray = receiveData.data as Uint8Array; 675 if (currentChunkOffset + receiveDataArray.length > maxSize) { 676 let freeSize = maxSize - currentChunkOffset; 677 let freeSaveData = receiveDataArray.slice(0, freeSize); 678 currentChunk.set(freeSaveData, currentChunkOffset); 679 await addDataToIndexeddb(db, { 680 buf: currentChunk, 681 id: `${fileType}_new_${timStamp}_${pageNum}_${saveIndex}`, 682 fileType: `${fileType}_new`, 683 pageNum: pageNum, 684 startOffset: saveStartOffset, 685 endOffset: saveStartOffset + maxSize, 686 index: saveIndex, 687 timStamp: timStamp, 688 }); 689 saveStartOffset += maxSize; 690 saveIndex++; 691 currentChunk = new Uint8Array(maxSize); 692 let remnantArray = receiveDataArray.slice(freeSize); 693 currentChunkOffset = 0; 694 currentChunk.set(remnantArray, currentChunkOffset); 695 currentChunkOffset += remnantArray.length; 696 } else { 697 currentChunk.set(receiveDataArray, currentChunkOffset); 698 currentChunkOffset += receiveDataArray.length; 699 } 700 } else { 701 if (receiveData.data.length > 0) { 702 let needCutMessage = receiveData.data as Array<{ offset: number; size: number }>; 703 let startOffset = needCutMessage[0].offset; 704 let nowCutInfoList: Array<any> = []; 705 let isBeforeCutFinish = false; 706 for (let needCutIndex = 0; needCutIndex < needCutMessage.length; needCutIndex++) { 707 let cutInfo = needCutMessage[needCutIndex]; 708 if (isBeforeCutFinish) { 709 startOffset = cutInfo.offset; 710 isBeforeCutFinish = false; 711 nowCutInfoList.length = 0; 712 } 713 if ( 714 cutInfo.offset + cutInfo.size - startOffset >= maxSize * 10 || 715 needCutIndex === needCutMessage.length - 1 716 ) { 717 nowCutInfoList.push(cutInfo); 718 let nowStartCutOffset = nowCutInfoList[0].offset; 719 let nowEndCutOffset = cutInfo.offset + cutInfo.size; 720 let searchDataInfo = allIndexDataList.filter( 721 (value: { 722 fileType: string; 723 index: number; 724 pageNum: number; 725 startOffsetSize: number; 726 endOffsetSize: number; 727 }) => { 728 return ( 729 value.fileType === fileType && 730 value.startOffsetSize <= nowEndCutOffset && 731 value.endOffsetSize >= nowStartCutOffset 732 ); 733 } 734 ); 735 let startIndex = searchDataInfo[0].index; 736 let endIndex = searchDataInfo[searchDataInfo.length - 1].index; 737 let transaction = db.transaction(STORE_NAME, 'readonly'); 738 let store = transaction.objectStore(STORE_NAME); 739 let index = store.index('QueryCompleteFile'); 740 let range = IDBKeyRange.bound( 741 [timStamp, fileType, 0, startIndex], 742 [timStamp, fileType, 0, endIndex], 743 false, 744 false 745 ); 746 const getRequest = index.openCursor(range); 747 let queryAllData = await queryDataFromIndexeddb(getRequest); 748 let mergeData = indexedDataToBufferData(queryAllData); 749 for (let cutOffsetObjIndex = 0; cutOffsetObjIndex < nowCutInfoList.length; cutOffsetObjIndex++) { 750 let cutUseOffsetObj = nowCutInfoList[cutOffsetObjIndex]; 751 let endOffset = cutUseOffsetObj.offset + cutUseOffsetObj.size; 752 let sliceData = mergeData.slice( 753 cutUseOffsetObj.offset - searchDataInfo[0].startOffsetSize, 754 endOffset - searchDataInfo[0].startOffsetSize 755 ); 756 let sliceDataLength = sliceData.length; 757 if (currentChunkOffset + sliceDataLength >= maxSize) { 758 let handleCurrentData = new Uint8Array(currentChunkOffset + sliceDataLength); 759 let freeSaveArray = currentChunk.slice(0, currentChunkOffset); 760 handleCurrentData.set(freeSaveArray, 0); 761 handleCurrentData.set(sliceData, freeSaveArray.length); 762 let newSliceDataLength: number = Math.ceil(handleCurrentData.length / maxSize); 763 for (let newSliceIndex = 0; newSliceIndex < newSliceDataLength; newSliceIndex++) { 764 let newSliceSize = newSliceIndex * maxSize; 765 let number = Math.min(newSliceSize + maxSize, handleCurrentData.length); 766 let saveArray = handleCurrentData.slice(newSliceSize, number); 767 if (newSliceIndex === newSliceDataLength - 1 && number - newSliceSize < maxSize) { 768 currentChunk = new Uint8Array(maxSize); 769 currentChunkOffset = 0; 770 currentChunk.set(saveArray, currentChunkOffset); 771 currentChunkOffset += saveArray.length; 772 } else { 773 await addDataToIndexeddb(db, { 774 buf: saveArray, 775 id: `${fileType}_new_${timStamp}_${pageNum}_${saveIndex}`, 776 fileType: `${fileType}_new`, 777 pageNum: pageNum, 778 startOffset: saveStartOffset, 779 endOffset: saveStartOffset + maxSize, 780 index: saveIndex, 781 timStamp: timStamp, 782 }); 783 saveStartOffset += maxSize; 784 saveIndex++; 785 } 786 } 787 } else { 788 currentChunk.set(sliceData, currentChunkOffset); 789 currentChunkOffset += sliceDataLength; 790 } 791 } 792 isBeforeCutFinish = true; 793 } else { 794 nowCutInfoList.push(cutInfo); 795 } 796 } 797 } 798 } 799 } 800 if (currentChunkOffset !== 0) { 801 let freeArray = currentChunk.slice(0, currentChunkOffset); 802 await addDataToIndexeddb(db, { 803 buf: freeArray, 804 id: `${fileType}_new_${timStamp}_${pageNum}_${saveIndex}`, 805 fileType: `${fileType}_new`, 806 pageNum: pageNum, 807 startOffset: saveStartOffset, 808 endOffset: saveStartOffset + maxSize, 809 index: saveIndex, 810 timStamp: timStamp, 811 }); 812 saveStartOffset += maxSize; 813 saveIndex++; 814 } 815 } 816 } 817 } 818 self.postMessage({ 819 id: e.data.id, 820 action: e.data.action, 821 results: result, 822 }); 823 return; 824 } 825}; 826 827function indexedDataToBufferData(sourceData: any): Uint8Array { 828 let uintArrayLength = 0; 829 let uintDataList = sourceData.map((item: any) => { 830 let currentBufData = new Uint8Array(item.buf); 831 uintArrayLength += currentBufData.length; 832 return currentBufData; 833 }); 834 let resultUintArray = new Uint8Array(uintArrayLength); 835 let offset = 0; 836 uintDataList.forEach((currentArray: Uint8Array) => { 837 resultUintArray.set(currentArray, offset); 838 offset += currentArray.length; 839 }); 840 return resultUintArray; 841} 842 843async function splitFileAndSaveArkTs( 844 maxSize: number, 845 currentChunkOffset: number, 846 currentChunk: Uint8Array, 847 fileType: string, 848 pageNum: number, 849 saveStartOffset: number, 850 saveIndex: number, 851 timStamp: number, 852 db: IDBDatabase 853) { 854 for (let arkTsAllDataIndex = 0; arkTsAllDataIndex < arkTsData.length; arkTsAllDataIndex++) { 855 let currentArkTsData = arkTsData[arkTsAllDataIndex]; 856 let freeSize = maxSize - currentChunkOffset; 857 if (currentArkTsData.length > freeSize) { 858 let freeSaveData = currentArkTsData.slice(0, freeSize); 859 currentChunk.set(freeSaveData, currentChunkOffset); 860 let arg2 = setArg(currentChunk, fileType, pageNum, saveStartOffset, saveIndex, maxSize, timStamp); 861 await addDataToIndexeddb(db, arg2); 862 saveStartOffset += maxSize; 863 saveIndex++; 864 let remnantData = currentArkTsData.slice(freeSize); 865 let remnantDataLength: number = Math.ceil(remnantData.length / maxSize); 866 for (let newSliceIndex = 0; newSliceIndex < remnantDataLength; newSliceIndex++) { 867 let newSliceSize = newSliceIndex * maxSize; 868 let number = Math.min(newSliceSize + maxSize, remnantData.length); 869 let saveArray = remnantData.slice(newSliceSize, number); 870 if (newSliceIndex === remnantDataLength - 1 && number - newSliceSize < maxSize) { 871 currentChunk = new Uint8Array(maxSize); 872 currentChunkOffset = 0; 873 currentChunk.set(saveArray, currentChunkOffset); 874 currentChunkOffset += saveArray.length; 875 } else { 876 let arg2 = setArg(saveArray, fileType, pageNum, saveStartOffset, saveIndex, maxSize, timStamp); 877 await addDataToIndexeddb(db, arg2); 878 saveStartOffset += maxSize; 879 saveIndex++; 880 } 881 } 882 } else { 883 currentChunk.set(currentArkTsData, currentChunkOffset); 884 currentChunkOffset += currentArkTsData.length; 885 } 886 } 887} 888 889const splitFileAndSave = async ( 890 timStamp: number, 891 fileType: string, 892 startIndex: number, 893 endIndex: number, 894 fileSize: number, 895 db: IDBDatabase, 896 pageNum: number, 897 maxSize: number, 898 splitReqBufferAddr?: any 899): Promise<void> => { 900 let queryStartIndex = startIndex; 901 let queryEndIndex = startIndex; 902 let saveIndex = 0; 903 let saveStartOffset = 0; 904 let currentChunk = new Uint8Array(maxSize); 905 let currentChunkOffset = 0; 906 let resultFileSize = 0; 907 do { 908 queryEndIndex = queryStartIndex + 9; 909 if (queryEndIndex > endIndex) { 910 queryEndIndex = endIndex; 911 } 912 const transaction = db.transaction(STORE_NAME, 'readonly'); 913 const store = transaction.objectStore(STORE_NAME); 914 const index = store.index('QueryCompleteFile'); 915 let range = getRange(timStamp, fileType, queryStartIndex, queryEndIndex); 916 const getRequest = index.openCursor(range); 917 let res = await queryDataFromIndexeddb(getRequest); 918 queryStartIndex = queryEndIndex + 1; 919 for (let i = 0; i < res.length; i++) { 920 let arrayBuffer = res[i]; 921 let uint8Array = new Uint8Array(arrayBuffer.buf); 922 let cutFileSize = 0; 923 while (cutFileSize < uint8Array.length) { 924 const sliceLen = Math.min(uint8Array.length - cutFileSize, REQ_BUF_SIZE); 925 const dataSlice = uint8Array.subarray(cutFileSize, cutFileSize + sliceLen); 926 Module.HEAPU8.set(dataSlice, splitReqBufferAddr); 927 cutFileSize += sliceLen; 928 resultFileSize += sliceLen; 929 if (resultFileSize >= fileSize) { 930 Module._TraceStreamerLongTraceSplitFileEx(sliceLen, 1, pageNum); 931 } else { 932 Module._TraceStreamerLongTraceSplitFileEx(sliceLen, 0, pageNum); 933 } 934 if (arkTsDataSize > 0 && fileType === 'arkts') { 935 splitFileAndSaveArkTs( 936 maxSize, 937 currentChunkOffset, 938 currentChunk, 939 fileType, 940 pageNum, 941 saveStartOffset, 942 saveIndex, 943 timStamp, 944 db 945 ); 946 } 947 } 948 } 949 } while (queryEndIndex < endIndex); 950 if (fileType === 'arkts' && currentChunkOffset > 0) { 951 let remnantArray = new Uint8Array(currentChunkOffset); 952 let remnantChunk = currentChunk.slice(0, currentChunkOffset); 953 remnantArray.set(remnantChunk, 0); 954 let arg2 = setArg(remnantArray, fileType, pageNum, saveStartOffset, saveIndex, maxSize, timStamp); 955 await addDataToIndexeddb(db, arg2); 956 arkTsDataSize = 0; 957 arkTsData.length = 0; 958 } 959}; 960 961function setArg( 962 remnantArray: Uint8Array, 963 fileType: string, 964 pageNum: number, 965 saveStartOffset: number, 966 saveIndex: number, 967 maxSize: number, 968 timStamp: number 969): any { 970 return { 971 buf: remnantArray, 972 id: `${fileType}_new_${timStamp}_${pageNum}_${saveIndex}`, 973 fileType: `${fileType}_new`, 974 pageNum: pageNum, 975 startOffset: saveStartOffset, 976 endOffset: saveStartOffset + maxSize, 977 index: saveIndex, 978 timStamp: timStamp, 979 }; 980} 981function getRange(timStamp: number, fileType: string, queryStartIndex: number, queryEndIndex: number) { 982 return IDBKeyRange.bound( 983 [timStamp, fileType, 0, queryStartIndex], 984 [timStamp, fileType, 0, queryEndIndex], 985 false, 986 false 987 ); 988} 989 990enum DataTypeEnum { 991 data, 992 json, 993} 994 995let uploadSoActionId: string = ''; 996let uploadFileIndex: number = 0; 997let uploadSoCallbackFn: any; 998let soFileList: Array<File | null> = []; 999const uploadSoFile = async (file: File | null): Promise<void> => { 1000 if (file) { 1001 let fileNameBuffer: Uint8Array | null = enc.encode(file.webkitRelativePath); 1002 let fileNameLength = fileNameBuffer.length; 1003 let addr = Module._InitFileName(uploadSoCallbackFn, fileNameBuffer.length); 1004 Module.HEAPU8.set(fileNameBuffer, addr); 1005 let writeSize = 0; 1006 let upRes = -1; 1007 while (writeSize < file.size) { 1008 let sliceLen = Math.min(file.size - writeSize, REQ_BUF_SIZE); 1009 let blob: Blob | null = file.slice(writeSize, writeSize + sliceLen); 1010 let buffer: ArrayBuffer | null = await blob.arrayBuffer(); 1011 let data: Uint8Array | null = new Uint8Array(buffer); 1012 let size = file.size; 1013 let lastFile = uploadFileIndex === soFileList.length - 1 ? 1 : 0; 1014 Module.HEAPU8.set(data, reqBufferAddr); 1015 writeSize += sliceLen; 1016 upRes = Module._TraceStreamerDownloadELFEx(size, fileNameLength, sliceLen, lastFile); 1017 data = null; 1018 buffer = null; 1019 blob = null; 1020 } 1021 file = null; 1022 soFileList[uploadFileIndex] = null; 1023 fileNameBuffer = null; 1024 } 1025}; 1026 1027const uploadSoCallBack = (heapPtr: number, size: number, isFinish: number): void => { 1028 let out: Uint8Array | null = Module.HEAPU8.slice(heapPtr, heapPtr + size); 1029 if (out) { 1030 let res = dec.decode(out); 1031 out = null; 1032 if (res.includes('file send over')) { 1033 if (uploadFileIndex < soFileList.length - 1) { 1034 uploadFileIndex = uploadFileIndex + 1; 1035 uploadSoFile(soFileList[uploadFileIndex]).then(); 1036 } 1037 } else { 1038 soFileList.length = 0; 1039 self.postMessage({ 1040 id: uploadSoActionId, 1041 action: 'upload-so', 1042 results: res.includes('ok') ? 'ok' : 'failed', 1043 }); 1044 } 1045 } 1046}; 1047 1048let splitReqBufferAddr = -1; 1049 1050enum FileTypeEnum { 1051 data, 1052 json, 1053} 1054 1055function cutFileBufferByOffSet(out: Uint8Array, uint8Array: Uint8Array) { 1056 let jsonStr: string = dec.decode(out); 1057 let jsonObj = JSON.parse(jsonStr); 1058 let valueArray: Array<{ offset: number; size: number }> = jsonObj.value; 1059 const sum = valueArray.reduce((total, obj) => total + obj.size, 0); 1060 let cutBuffer = new Uint8Array(sum); 1061 let offset = 0; 1062 valueArray.forEach((item, index) => { 1063 const dataSlice = uint8Array.subarray(item.offset, item.offset + item.size); 1064 cutBuffer.set(dataSlice, offset); 1065 offset += item.size; 1066 }); 1067 return cutBuffer; 1068} 1069 1070function cutFileByRange(e: MessageEvent) { 1071 let cutLeftTs = e.data.leftTs; 1072 let cutRightTs = e.data.rightTs; 1073 let uint8Array = new Uint8Array(e.data.buffer); 1074 let resultBuffer: Array<any> = []; 1075 let cutFileCallBack = cutFileCallBackFunc(resultBuffer, uint8Array, e); 1076 splitReqBufferAddr = Module._InitializeSplitFile(Module.addFunction(cutFileCallBack, 'viiii'), REQ_BUF_SIZE); 1077 let cutTimeRange = `${cutLeftTs};${cutRightTs};`; 1078 let cutTimeRangeBuffer = enc.encode(cutTimeRange); 1079 Module.HEAPU8.set(cutTimeRangeBuffer, splitReqBufferAddr); 1080 Module._TraceStreamerSplitFileEx(cutTimeRangeBuffer.length); 1081 let cutFileSize = 0; 1082 let receiveFileResult = -1; 1083 while (cutFileSize < uint8Array.length) { 1084 const sliceLen = Math.min(uint8Array.length - cutFileSize, REQ_BUF_SIZE); 1085 const dataSlice = uint8Array.subarray(cutFileSize, cutFileSize + sliceLen); 1086 Module.HEAPU8.set(dataSlice, splitReqBufferAddr); 1087 cutFileSize += sliceLen; 1088 try { 1089 if (cutFileSize >= uint8Array.length) { 1090 receiveFileResult = Module._TraceStreamerReciveFileEx(sliceLen, 1); 1091 } else { 1092 receiveFileResult = Module._TraceStreamerReciveFileEx(sliceLen, 0); 1093 } 1094 } catch (error) { 1095 self.postMessage( 1096 { 1097 id: e.data.id, 1098 action: e.data.action, 1099 cutStatus: false, 1100 msg: 'split failed', 1101 buffer: e.data.buffer, 1102 }, 1103 // @ts-ignore 1104 [e.data.buffer] 1105 ); 1106 } 1107 } 1108} 1109function cutFileCallBackFunc(resultBuffer: Array<any>, uint8Array: Uint8Array, e: MessageEvent): Function { 1110 return (heapPtr: number, size: number, fileType: number, isEnd: number) => { 1111 let out: Uint8Array = Module.HEAPU8.slice(heapPtr, heapPtr + size); 1112 if (FileTypeEnum.data === fileType) { 1113 resultBuffer.push(out); 1114 } else if (FileTypeEnum.json === fileType) { 1115 let cutBuffer = cutFileBufferByOffSet(out, uint8Array); 1116 resultBuffer.push(cutBuffer); 1117 } 1118 if (isEnd) { 1119 const cutResultFileLength = resultBuffer.reduce((total, obj) => total + obj.length, 0); 1120 let cutBuffer = new Uint8Array(cutResultFileLength); 1121 let offset = 0; 1122 resultBuffer.forEach((item) => { 1123 cutBuffer.set(item, offset); 1124 offset += item.length; 1125 }); 1126 resultBuffer.length = 0; 1127 self.postMessage( 1128 { 1129 id: e.data.id, 1130 action: e.data.action, 1131 cutStatus: true, 1132 msg: 'split success', 1133 buffer: e.data.buffer, 1134 cutBuffer: cutBuffer.buffer, 1135 }, 1136 // @ts-ignore 1137 [e.data.buffer, cutBuffer.buffer] 1138 ); 1139 } 1140 }; 1141} 1142 1143function createView(sql: string) { 1144 let array = enc.encode(sql); 1145 Module.HEAPU8.set(array, reqBufferAddr); 1146 let res = Module._TraceStreamerSqlOperateEx(array.length); 1147 return res; 1148} 1149 1150function queryJSON(name: string, sql: string, params: any) { 1151 query(name, sql, params); 1152 return convertJSON(); 1153} 1154 1155function query(name: string, sql: string, params: any): void { 1156 if (params) { 1157 Reflect.ownKeys(params).forEach((key: any) => { 1158 if (typeof params[key] === 'string') { 1159 sql = sql.replace(new RegExp(`\\${key}`, 'g'), `'${params[key]}'`); 1160 } else { 1161 sql = sql.replace(new RegExp(`\\${key}`, 'g'), params[key]); 1162 } 1163 }); 1164 } 1165 start = new Date().getTime(); 1166 let sqlUintArray = enc.encode(sql); 1167 Module.HEAPU8.set(sqlUintArray, reqBufferAddr); 1168 Module._TraceStreamerSqlQueryEx(sqlUintArray.length); 1169} 1170 1171function querySdk(name: string, sql: string, sdkParams: any, action: string) { 1172 if (sdkParams) { 1173 Reflect.ownKeys(sdkParams).forEach((key: any) => { 1174 if (typeof sdkParams[key] === 'string') { 1175 sql = sql.replace(new RegExp(`\\${key}`, 'g'), `'${sdkParams[key]}'`); 1176 } else { 1177 sql = sql.replace(new RegExp(`\\${key}`, 'g'), sdkParams[key]); 1178 } 1179 }); 1180 } 1181 let sqlUintArray = enc.encode(sql); 1182 let commentId = action.substring(action.lastIndexOf('-') + 1); 1183 let key = Number(commentId); 1184 let wasm = thirdWasmMap.get(key); 1185 if (wasm != undefined) { 1186 let wasmModel = wasm.model; 1187 wasmModel.HEAPU8.set(sqlUintArray, wasm.bufferAddr); 1188 wasmModel._TraceStreamerSqlQueryEx(sqlUintArray.length); 1189 } 1190} 1191 1192function queryMetric(name: string): void { 1193 start = new Date().getTime(); 1194 let metricArray = enc.encode(name); 1195 Module.HEAPU8.set(metricArray, reqBufferAddr); 1196 Module._TraceStreamerSqlMetricsQuery(metricArray.length); 1197} 1198 1199const DB_NAME = 'sp'; 1200const DB_VERSION = 1; 1201const STORE_NAME = 'longTable'; 1202 1203function openDB(): Promise<IDBDatabase> { 1204 return new Promise((resolve, reject) => { 1205 const openRequest = indexedDB.open(DB_NAME, DB_VERSION); 1206 openRequest.onerror = () => reject(openRequest.error); 1207 openRequest.onsuccess = () => { 1208 resolve(openRequest.result); 1209 }; 1210 }); 1211} 1212 1213function queryDataFromIndexeddb(getRequest: IDBRequest<IDBCursorWithValue | null>): Promise<any> { 1214 return new Promise((resolve, reject) => { 1215 let results: any[] = []; 1216 getRequest.onerror = (event) => { 1217 // @ts-ignore 1218 reject(event.target.error); 1219 }; 1220 getRequest.onsuccess = (event) => { 1221 // @ts-ignore 1222 const cursor = event.target!.result; 1223 if (cursor) { 1224 results.push(cursor.value); 1225 cursor['continue'](); 1226 } else { 1227 // @ts-ignore 1228 resolve(results); 1229 } 1230 }; 1231 }); 1232} 1233 1234function addDataToIndexeddb(db: IDBDatabase, value: any, key?: IDBValidKey) { 1235 return new Promise((resolve, reject) => { 1236 const transaction = db.transaction(STORE_NAME, 'readwrite'); 1237 const objectStore = transaction.objectStore(STORE_NAME); 1238 const request = objectStore.add(value, key); 1239 request.onsuccess = function (event) { 1240 // @ts-ignore 1241 resolve(event.target.result); 1242 }; 1243 request.onerror = (event) => { 1244 reject(event); 1245 }; 1246 }); 1247} 1248