tdweb: multiple fixes

GitOrigin-RevId: 6ccde11c8f8f5b380dead450e7f68cd0639a7490
This commit is contained in:
Arseny Smirnov 2019-04-29 18:22:46 +03:00
parent ec849f86b2
commit 260d351f07
3 changed files with 308 additions and 119 deletions

View File

@ -70,6 +70,7 @@
},
"dependencies": {
"@babel/runtime": "^7.4.3",
"broadcast-channel": "^2.1.12",
"localforage": "^1.7.3",
"uuid": "^3.3.2"
},

View File

@ -1,6 +1,7 @@
import MyWorker from './worker.js';
import localforage from 'localforage';
import './third_party/broadcastchannel.js';
//import './third_party/broadcastchannel.js';
import BroadcastChannel from 'broadcast-channel';
import uuid4 from 'uuid/v4';
import log from './logger.js';
@ -22,8 +23,6 @@ const sleep = ms => new Promise(res => setTimeout(res, ms));
* 3. Added the possibility to use blobs as input files via the constructor <code>inputFileBlob data:<JavaScript blob> = InputFile;</code>.<br>
* 4. The class <code>filePart</code> contains data as a JavaScript blob instead of a base64-encoded string.<br>
* 5. The methods <code>getStorageStatistics</code>, <code>getStorageStatisticsFast</code>, <code>optimizeStorage</code>, <code>addProxy</code> are not supported.<br>
* 6. Added the field <code>idb_key</code> to <code>file</code> object, which contains the IndexedDB key in which the file content is stored.<br>
* This field is non-empty only for fully downloaded files. IndexedDB database name is chosen during TdClient creation via options.instanceName parameter.<br>
* <br>
*/
class TdClient {
@ -47,9 +46,8 @@ class TdClient {
constructor(options) {
log.setVerbosity(options.jsLogVerbosityLevel);
this.worker = new MyWorker();
var self = this;
this.worker.onmessage = e => {
self.onResponse(e.data);
this.onResponse(e.data);
};
this.query_id = 0;
this.query_callbacks = new Map();
@ -75,10 +73,19 @@ class TdClient {
* @returns {Promise} Promise object represents the result of the query.
*/
send(query) {
return this.doSend(query, true);
}
/** @private */
sendInternal(query) {
return this.doSend(query, false);
}
/** @private */
doSend(query, isExternal) {
this.query_id++;
if (query['@extra']) {
query['@extra'] = {
'@old_extra': JSON.parse(JSON.stringify(query.extra)),
'@old_extra': JSON.parse(JSON.stringify(query['@extra'])),
query_id: this.query_id
};
} else {
@ -91,16 +98,20 @@ class TdClient {
}
log.debug('send to worker: ', query);
let res = new Promise((resolve, reject) => {
const res = new Promise((resolve, reject) => {
this.query_callbacks.set(this.query_id, [resolve, reject]);
});
this.externalPostMessage(query);
if (isExternal) {
this.externalPostMessage(query);
} else {
this.worker.postMessage(query);
}
return res;
}
/** @private */
externalPostMessage(query) {
let unsupportedMethods = [
const unsupportedMethods = [
'getStorageStatistics',
'getStorageStatisticsFast',
'optimizeStorage',
@ -117,16 +128,39 @@ class TdClient {
});
return;
}
if (query['@type'] === 'readFile') {
if (query['@type'] === 'readFile' || query['@type'] == 'readFilePart') {
this.readFile(query);
return;
}
if (query['@type'] === 'deleteFile') {
this.deleteFile(query);
return;
}
this.worker.postMessage(query);
}
/** @private */
async readFile(query) {
let response = await this.fileManager.readFile(query);
const response = await this.fileManager.readFile(query);
this.onResponse(response);
}
/** @private */
async deleteFile(query) {
const response = this.fileManager.deleteFile(query);
try {
if (response.idb_key) {
await this.sendInternal({
'@type': 'deleteIdbKey',
idb_key: response.idb_key
});
delete response.idb_key;
}
await this.sendInternal({
'@type': 'deleteFile',
file_id: query.file_id
});
} catch (e) {}
this.onResponse(response);
}
@ -148,8 +182,8 @@ class TdClient {
response = this.prepareResponse(response);
if ('@extra' in response) {
var query_id = response['@extra'].query_id;
var [resolve, reject] = this.query_callbacks.get(query_id);
const query_id = response['@extra'].query_id;
const [resolve, reject] = this.query_callbacks.get(query_id);
this.query_callbacks.delete(query_id);
if ('@old_extra' in response['@extra']) {
response['@extra'] = response['@extra']['@old_extra'];
@ -188,10 +222,18 @@ class TdClient {
/** @private */
prepareResponse(response) {
if (response['@type'] === 'file') {
if (false && Math.random() < 0.1) {
(async () => {
log.warn('DELETE FILE', response.id);
try {
await this.send({ '@type': 'deleteFile', file_id: response.id });
} catch (e) {}
})();
}
return this.prepareFile(response);
}
for (var key in response) {
let field = response[key];
for (const key in response) {
const field = response[key];
if (field && typeof field === 'object') {
response[key] = this.prepareResponse(field);
}
@ -201,7 +243,8 @@ class TdClient {
/** @private */
onBroadcastMessage(e) {
var message = e.data;
//const message = e.data;
const message = e;
if (message.uid === this.uid) {
log.info('ignore self broadcast message: ', message);
return;
@ -233,8 +276,8 @@ class TdClient {
/** @private */
postState() {
let state = {
id: this.uid,
const state = {
uid: this.uid,
state: this.state,
timestamp: this.timestamp,
isBackground: this.isBackground
@ -272,7 +315,7 @@ class TdClient {
}
this.wantSendStart = false;
this.state = 'active';
let query = { '@type': 'start' };
const query = { '@type': 'start' };
log.info('send to worker: ', query);
this.worker.postMessage(query);
}
@ -306,7 +349,7 @@ class TdClient {
return;
}
let query = { '@type': 'close' };
const query = { '@type': 'close' };
log.info('send to worker: ', query);
this.worker.postMessage(query);
@ -323,19 +366,20 @@ class TdClient {
this.waitSet = new Set();
log.info('close other clients');
this.channel = new BroadcastChannel(options.instanceName);
this.channel = new BroadcastChannel(options.instanceName, {
webWorkerSupport: false
});
this.postState();
var self = this;
this.channel.onmessage = message => {
self.onBroadcastMessage(message);
this.onBroadcastMessage(message);
};
await sleep(300);
if (this.waitSet.size !== 0) {
await new Promise(resolve => {
self.onWaitSetEmpty = resolve;
this.onWaitSetEmpty = resolve;
});
}
this.sendStart();
@ -348,6 +392,43 @@ class TdClient {
}
}
/** @private */
class ListNode {
constructor(value) {
this.value = value;
this.clear();
}
erase() {
this.prev.connect(this.next);
this.clear();
}
clear() {
this.prev = this;
this.next = this;
}
connect(other) {
this.next = other;
other.prev = this;
}
onUsed(other) {
other.usedAt = Date.now();
other.clear();
other.connect(this.next);
log.debug('LRU: used file_id: ', other.value);
this.connect(other);
}
getLru() {
if (this === this.next) {
throw new Error('popLru from empty list');
}
return this.prev;
}
}
/** @private */
class FileManager {
constructor(instanceName) {
@ -355,12 +436,13 @@ class FileManager {
this.cache = new Map();
this.pending = [];
this.transaction_id = 0;
this.totalSize = 0;
this.lru = new ListNode(-1);
}
init() {
let self = this;
this.idb = new Promise((resolve, reject) => {
const request = window.indexedDB.open(self.instanceName);
const request = window.indexedDB.open(this.instanceName);
request.onsuccess = () => resolve(request.result);
request.onerror = () => reject(request.error);
});
@ -370,32 +452,80 @@ class FileManager {
this.isInited = true;
}
unload(info) {
if (info.arr) {
log.debug(
'LRU: delete file_id: ',
info.node.value,
' with arr.length: ',
info.arr.length
);
this.totalSize -= info.arr.length;
delete info.arr;
}
if (info.node) {
info.node.erase();
delete info.node;
}
}
registerFile(file) {
const cached_info = this.cache.get(file.id);
if (cached_info && !file.idb_key) {
delete cached_info.idb_key;
}
if (file.idb_key || file.arr) {
file.is_downloading_completed = true;
var info = {};
let cached_info = this.cache.get(file.id);
if (cached_info !== undefined) {
let info = {};
if (cached_info) {
info = cached_info;
} else {
this.cache.set(file.id, info);
}
if (file.idb_key) {
info.idb_key = file.idb_key;
delete file.idb_key;
}
if (file.arr) {
const now = Date.now();
while (this.totalSize > 10000000) {
const node = this.lru.getLru();
// immunity for 5 seconds
if (node.usedAt + 5 * 1000 > now) {
break;
}
const lru_info = this.cache.get(node.value);
this.unload(lru_info);
}
if (info.arr) {
log.warn('Got file.arr at least twice for the same file');
this.totalSize -= info.arr.length;
}
info.arr = file.arr;
this.totalSize += info.arr.length;
if (!info.node) {
log.debug(
'LRU: create file_id: ',
file.id,
' with arr.length: ',
info.arr.length
);
info.node = new ListNode(file.id);
}
this.lru.onUsed(info.node);
log.info('Total file.arr size: ', this.totalSize);
}
}
return file;
}
async flushLoad() {
let pending = this.pending;
const pending = this.pending;
this.pending = [];
let idb = await this.idb;
let transaction_id = this.transaction_id++;
let read = idb
const idb = await this.idb;
const transaction_id = this.transaction_id++;
const read = idb
.transaction(['keyvaluepairs'], 'readonly')
.objectStore('keyvaluepairs');
log.debug('Load group of files from idb', pending.length);
@ -415,9 +545,8 @@ class FileManager {
load(key, resolve, reject) {
if (this.pending.length === 0) {
let self = this;
setTimeout(() => {
self.flushLoad();
this.flushLoad();
}, 1);
}
this.pending.push({ key: key, resolve: resolve, reject: reject });
@ -427,26 +556,36 @@ class FileManager {
if (info.arr) {
return { data: new Blob([info.arr]), transaction_id: -1 };
}
let idb_key = info.idb_key;
let self = this;
const idb_key = info.idb_key;
//return this.store.getItem(idb_key);
return await new Promise((resolve, reject) => {
self.load(idb_key, resolve, reject);
this.load(idb_key, resolve, reject);
});
}
doDelete(info) {
this.unload(info);
return info.idb_key;
}
async readFile(query) {
try {
if (query.offset || query.size) {
throw new Error('readFilePart: offset and size are not supported yet');
}
if (!this.isInited) {
throw new Error('FileManager is not inited');
}
let info = this.cache.get(query.file_id);
const info = this.cache.get(query.file_id);
if (!info) {
throw new Error('File is not loaded');
}
let response = await this.doLoad(info);
if (info.node) {
this.lru.onUsed(info.node);
}
const response = await this.doLoad(info);
return {
'@type': 'blob',
'@type': 'filePart',
'@extra': query['@extra'],
data: response.data,
transaction_id: response.transaction_id
@ -460,6 +599,27 @@ class FileManager {
};
}
}
deleteFile(query) {
const res = {
'@type': 'ok',
'@extra': query['@extra']
};
try {
if (!this.isInited) {
throw new Error('FileManager is not inited');
}
const info = this.cache.get(query.file_id);
if (!info) {
throw new Error('File is not loaded');
}
const idb_key = this.doDelete(info);
if (idb_key) {
res.idb_key = idb_key;
}
} catch (e) {}
return res;
}
}
export default TdClient;

View File

@ -14,12 +14,12 @@ const localForageDrivers = [
async function initLocalForage() {
// Implement the driver here.
var memoryDriver = {
const memoryDriver = {
_driver: 'memoryDriver',
_initStorage: function(options) {
var dbInfo = {};
const dbInfo = {};
if (options) {
for (var i in options) {
for (const i in options) {
dbInfo[i] = options[i];
}
}
@ -30,7 +30,7 @@ async function initLocalForage() {
this._map.clear();
},
getItem: async function(key) {
let value = this._map.get(key);
const value = this._map.get(key);
console.log('getItem', this._map, key, value);
return value;
},
@ -50,7 +50,7 @@ async function initLocalForage() {
this._map.delete(key);
},
setItem: async function(key, value) {
let originalValue = this._map.get(key);
const originalValue = this._map.get(key);
console.log('setItem', this._map, key, value);
this._map.set(key, value);
return originalValue;
@ -63,16 +63,16 @@ async function initLocalForage() {
async function loadTdlibWasm(onFS) {
console.log('loadTdlibWasm');
let Module = await import('./prebuilt/release/td_wasm.js');
const Module = await import('./prebuilt/release/td_wasm.js');
log.info('got td_wasm.js');
let td_wasm = td_wasm_release;
let module = Module.default({
const td_wasm = td_wasm_release;
const module = Module.default({
onRuntimeInitialized: () => {
log.info('runtime intialized');
},
instantiateWasm: (imports, successCallback) => {
log.info('start instantiateWasm');
let next = instance => {
const next = instance => {
log.info('finish instantiateWasm');
successCallback(instance);
};
@ -83,7 +83,7 @@ async function loadTdlibWasm(onFS) {
});
log.info('Got module', module);
onFS(module.FS);
let TdModule = new Promise((resolve, reject) =>
const TdModule = new Promise((resolve, reject) =>
module.then(m => {
delete m.then;
resolve(m);
@ -95,11 +95,11 @@ async function loadTdlibWasm(onFS) {
async function loadTdlibAsmjs(onFS) {
console.log('loadTdlibAsmjs');
let Module = await import('./prebuilt/release/td_asmjs.js');
const Module = await import('./prebuilt/release/td_asmjs.js');
console.log('got td_asm.js');
let fromFile = 'td_asmjs.js.mem';
let toFile = td_asmjs_mem_release;
let module = Module({
const fromFile = 'td_asmjs.js.mem';
const toFile = td_asmjs_mem_release;
const module = Module({
onRuntimeInitialized: () => {
console.log('runtime intialized');
},
@ -112,7 +112,7 @@ async function loadTdlibAsmjs(onFS) {
ENVIROMENT: 'WORKER'
});
onFS(module.FS);
let TdModule = new Promise((resolve, reject) =>
const TdModule = new Promise((resolve, reject) =>
module.then(m => {
delete m.then;
resolve(m);
@ -164,7 +164,7 @@ class OutboundFileSystem {
FS.mkdir(root);
}
blobToPath(blob, name) {
var dir = this.root + '/' + this.nextFileId;
const dir = this.root + '/' + this.nextFileId;
if (!name) {
name = 'blob';
}
@ -177,7 +177,7 @@ class OutboundFileSystem {
},
dir
);
let path = dir + '/' + name;
const path = dir + '/' + name;
this.files.add(path);
return path;
}
@ -192,9 +192,9 @@ class OutboundFileSystem {
class InboundFileSystem {
static async create(dbName, root, FS_promise) {
let start = performance.now();
const start = performance.now();
try {
let ifs = new InboundFileSystem();
const ifs = new InboundFileSystem();
ifs.root = root;
ifs.store = localforage.createInstance({
@ -204,10 +204,10 @@ class InboundFileSystem {
ifs.load_pids();
let FS = await FS_promise;
const FS = await FS_promise;
ifs.FS = FS;
ifs.FS.mkdir(root);
let create_time = (performance.now() - start) / 1000;
const create_time = (performance.now() - start) / 1000;
log.debug('InboundFileSystem::create ' + create_time);
return ifs;
} catch (e) {
@ -216,10 +216,10 @@ class InboundFileSystem {
}
async load_pids() {
let keys_start = performance.now();
const keys_start = performance.now();
log.debug('InboundFileSystem::create::keys start');
let keys = await this.store.keys();
let keys_time = (performance.now() - keys_start) / 1000;
const keys = await this.store.keys();
const keys_time = (performance.now() - keys_start) / 1000;
log.debug(
'InboundFileSystem::create::keys ' + keys_time + ' ' + keys.length
);
@ -251,15 +251,24 @@ class InboundFileSystem {
log.error('Failed persist ' + path + ' ', e);
}
}
async unlink(pid) {
log.debug('Unlink ' + pid);
try {
this.forget(pid);
await this.store.removeItem(pid);
} catch (e) {
log.error('Failed unlink ' + pid + ' ', e);
}
}
}
class DbFileSystem {
static async create(root, FS_promise, readOnly = false) {
let start = performance.now();
const start = performance.now();
try {
let dbfs = new DbFileSystem();
const dbfs = new DbFileSystem();
dbfs.root = root;
let FS = await FS_promise;
const FS = await FS_promise;
dbfs.FS = FS;
dbfs.syncfs_total_time = 0;
dbfs.readOnly = readOnly;
@ -272,9 +281,9 @@ class DbFileSystem {
});
});
let rmrf = path => {
const rmrf = path => {
log.debug('rmrf ', path);
var info;
let info;
try {
info = FS.lookupPath(path);
} catch (e) {
@ -282,7 +291,7 @@ class DbFileSystem {
}
log.debug('rmrf ', path, info);
if (info.node.isFolder) {
for (var key in info.node.contents) {
for (const key in info.node.contents) {
rmrf(info.path + '/' + info.node.contents[key].name);
}
log.debug('rmdir ', path);
@ -292,19 +301,19 @@ class DbFileSystem {
FS.unlink(path);
}
};
//var dirs = ['thumbnails', 'profile_photos', 'secret', 'stickers', 'temp', 'wallpapers', 'secret_thumbnails', 'passport'];
var dirs = [];
let root_dir = FS.lookupPath(root);
for (var key in root_dir.node.contents) {
let value = root_dir.node.contents[key];
//const dirs = ['thumbnails', 'profile_photos', 'secret', 'stickers', 'temp', 'wallpapers', 'secret_thumbnails', 'passport'];
const dirs = [];
const root_dir = FS.lookupPath(root);
for (const key in root_dir.node.contents) {
const value = root_dir.node.contents[key];
log.debug('node ', key, value);
if (!value.isFolder) {
continue;
}
dirs.push(root_dir.path + '/' + value.name);
}
for (let i in dirs) {
let dir = dirs[i];
for (const i in dirs) {
const dir = dirs[i];
rmrf(dir);
//FS.mkdir(dir);
//FS.mount(FS.filesystems.MEMFS, {}, dir);
@ -312,7 +321,7 @@ class DbFileSystem {
dbfs.syncfsInterval = setInterval(() => {
dbfs.sync();
}, 5000);
let create_time = (performance.now() - start) / 1000;
const create_time = (performance.now() - start) / 1000;
log.debug('DbFileSystem::create ' + create_time);
return dbfs;
} catch (e) {
@ -323,10 +332,10 @@ class DbFileSystem {
if (this.readOnly) {
return;
}
let start = performance.now();
const start = performance.now();
await new Promise((resolve, reject) => {
this.FS.syncfs(false, () => {
let syncfs_time = (performance.now() - start) / 1000;
const syncfs_time = (performance.now() - start) / 1000;
this.syncfs_total_time += syncfs_time;
log.debug('SYNC: ' + syncfs_time);
log.debug('SYNC total: ' + this.syncfs_total_time);
@ -344,7 +353,7 @@ class DbFileSystem {
return;
}
this.FS.unmount(this.root);
var req = indexedDB.deleteDatabase(this.root);
const req = indexedDB.deleteDatabase(this.root);
await new Promise((resolve, reject) => {
req.onsuccess = function(e) {
log.info('SUCCESS');
@ -364,32 +373,32 @@ class DbFileSystem {
class TdFileSystem {
static async init_fs(prefix, FS_promise) {
let FS = await FS_promise;
const FS = await FS_promise;
FS.mkdir(prefix);
return FS;
}
static async create(instanceName, FS_promise, readOnly = false) {
try {
let tdfs = new TdFileSystem();
let prefix = '/' + instanceName;
const tdfs = new TdFileSystem();
const prefix = '/' + instanceName;
tdfs.prefix = prefix;
FS_promise = TdFileSystem.init_fs(prefix, FS_promise);
//MEMFS. Store to IDB and delete files as soon as possible
let inboundFileSystem = InboundFileSystem.create(
const inboundFileSystem = InboundFileSystem.create(
instanceName,
prefix + '/inboundfs',
FS_promise
);
//IDBFS. MEMFS which is flushed to IDB from time to time
let dbFileSystem = DbFileSystem.create(
const dbFileSystem = DbFileSystem.create(
prefix + '/dbfs',
FS_promise,
readOnly
);
let FS = await FS_promise;
const FS = await FS_promise;
tdfs.FS = FS;
//WORKERFS. Temporary stores Blobs for outbound files
@ -421,7 +430,7 @@ class TdClient {
async testLocalForage() {
await initLocalForage();
var DRIVERS = [
const DRIVERS = [
localforage.INDEXEDDB,
'memoryDriver',
localforage.LOCALSTORAGE,
@ -435,7 +444,7 @@ class TdClient {
console.log('A');
await localforage.setItem('hello', 'world');
console.log('B');
let x = await localforage.getItem('hello');
const x = await localforage.getItem('hello');
console.log('got ', x);
await localforage.clear();
console.log('C');
@ -454,15 +463,13 @@ class TdClient {
this.wasInit = true;
options = options || {};
let mode = 'wasm';
mode = options.mode || mode;
const mode = options.mode || 'wasm';
var self = this;
let FS_promise = new Promise(resolve => {
self.onFS = resolve;
const FS_promise = new Promise(resolve => {
this.onFS = resolve;
});
let tdfs_promise = TdFileSystem.create(
const tdfs_promise = TdFileSystem.create(
options.instanceName,
FS_promise,
options.readOnly
@ -474,7 +481,7 @@ class TdClient {
}
log.info('load TdModule');
this.TdModule = await loadTdlib(mode, self.onFS);
this.TdModule = await loadTdlib(mode, this.onFS);
log.info('got TdModule');
this.td_functions = {
td_create: this.TdModule.cwrap('td_create', 'number', []),
@ -520,7 +527,7 @@ class TdClient {
// wait till it is allowed to start
this.callback({ '@type': 'inited' });
await new Promise(resolve => {
self.onStart = resolve;
this.onStart = resolve;
});
this.isStarted = true;
@ -570,8 +577,8 @@ class TdClient {
path: this.tdfs.outboundFileSystem.blobToPath(query.data, query.name)
};
}
for (var key in query) {
let field = query[key];
for (const key in query) {
const field = query[key];
if (field && typeof field === 'object') {
query[key] = this.prepareQueryRecursive(field);
}
@ -584,7 +591,7 @@ class TdClient {
query.parameters.database_directory = this.tdfs.dbFileSystem.root;
query.parameters.files_directory = this.tdfs.inboundFileSystem.root;
let useDb = this.useDatabase;
const useDb = this.useDatabase;
query.parameters.use_file_database = useDb;
query.parameters.use_chat_info_database = useDb;
query.parameters.use_message_database = useDb;
@ -602,12 +609,29 @@ class TdClient {
log.info('ignore on_start');
}
readFilePart(query) {
var res;
deleteIdbKey(query) {
try {
//let file_size = this.FS.stat(query.path).size;
var stream = this.FS.open(query.path, 'r');
var buf = new Uint8Array(query.size);
} catch (e) {
this.callback({
'@type': 'error',
'@extra': query['@extra'],
code: 400,
message: e
});
return;
}
this.callback({
'@type': 'ok',
'@extra': query['@extra']
});
}
readFilePart(query) {
let res;
try {
//const file_size = this.FS.stat(query.path).size;
const stream = this.FS.open(query.path, 'r');
const buf = new Uint8Array(query.size);
this.FS.read(stream, buf, 0, query.size, query.offset);
this.FS.close(stream);
res = buf;
@ -636,7 +660,7 @@ class TdClient {
}
if (this.wasFatalError) {
if (query['@type'] === 'destroy') {
this.destroy({ '@type': 'Ok', '@extra': query['@extra'] });
this.destroy({ '@type': 'ok', '@extra': query['@extra'] });
}
return;
}
@ -671,6 +695,10 @@ class TdClient {
this.readFilePart(query);
return;
}
if (query['@type'] === 'deleteIdbKey') {
this.deleteIdbKey(query);
return;
}
query = this.prepareQuery(query);
this.td_functions.td_send(this.client, JSON.stringify(query));
this.scheduleReceiveSoon();
@ -678,8 +706,8 @@ class TdClient {
execute(query) {
try {
let res = this.td_functions.td_execute(0, JSON.stringify(query));
let response = JSON.parse(res);
const res = this.td_functions.td_execute(0, JSON.stringify(query));
const response = JSON.parse(res);
this.callback(response);
} catch (error) {
this.onFatalError(error);
@ -692,11 +720,11 @@ class TdClient {
}
try {
while (true) {
let msg = this.td_functions.td_receive(this.client);
const msg = this.td_functions.td_receive(this.client);
if (!msg) {
break;
}
let response = this.prepareResponse(JSON.parse(msg));
const response = this.prepareResponse(JSON.parse(msg));
if (
response['@type'] === 'updateAuthorizationState' &&
response.authorization_state['@type'] === 'authorizationStateClosed'
@ -733,7 +761,7 @@ class TdClient {
return;
}
this.cancelReceive();
let timeout = this.td_functions.td_get_timeout();
const timeout = this.td_functions.td_get_timeout();
this.scheduleReceiveIn(timeout);
}
scheduleReceiveIn(timeout) {
@ -782,13 +810,13 @@ class TdClient {
}
saveFile(pid, file) {
let isSaving = this.savingFiles.has(pid);
const isSaving = this.savingFiles.has(pid);
this.savingFiles.set(pid, file);
if (isSaving) {
return file;
}
try {
var arr = this.FS.readFile(file.local.path);
const arr = this.FS.readFile(file.local.path);
if (arr) {
file = Object.assign({}, file);
file.arr = arr;
@ -810,7 +838,7 @@ class TdClient {
}
prepareFile(file) {
let pid = file.remote.id;
const pid = file.remote.id;
if (!pid) {
return file;
}
@ -832,8 +860,8 @@ class TdClient {
if (response['@type'] === 'file') {
return this.prepareFile(response);
}
for (var key in response) {
let field = response[key];
for (const key in response) {
const field = response[key];
if (field && typeof field === 'object') {
response[key] = this.prepareResponse(field);
}
@ -843,13 +871,13 @@ class TdClient {
flushPendingQueries() {
this.isPending = false;
for (let query of this.pendingQueries) {
for (const query of this.pendingQueries) {
this.send(query);
}
}
}
var client = new TdClient((e, t = []) => postMessage(e, t));
const client = new TdClient((e, t = []) => postMessage(e, t));
onmessage = function(e) {
try {