• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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