@universe/util
Advanced tools
Comparing version 0.2.4 to 0.2.5
@@ -64,1 +64,2 @@ export declare const isNull: (v: unknown) => v is null; | ||
export declare function relativeDate(input: Date | number): string; | ||
export declare const deepClone: <T>(data: T) => Promise<T>; |
@@ -31,2 +31,16 @@ "use strict"; | ||
}); | ||
it('no debounce memory leak', async function () { | ||
this.timeout(120000); | ||
const func = index_1.debounce((arr) => { | ||
arr[0] = arr[1]; | ||
}, 1); | ||
const before = process.memoryUsage().heapUsed / 1024 / 1024; | ||
for (let i = 0; i < 2000; i++) { | ||
await func(new Array(1000000).fill(1)); | ||
} | ||
global.gc(); | ||
await new Promise(resolve => setTimeout(resolve, 3000)); | ||
const after = process.memoryUsage().heapUsed / 1024 / 1024; | ||
assert.ok(after <= before, 'memory usage does not grow with many debounce calls'); | ||
}); | ||
it('runs md5', function () { | ||
@@ -45,2 +59,2 @@ assert.strictEqual(index_1.md5('hello'), '5d41402abc4b2a76b9719d911017c592'); | ||
}); | ||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90ZXN0L2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQUEseUJBQXlCO0FBQ3pCLHlCQUF5QjtBQUN6Qiw2QkFBNkI7QUFFN0Isd0NBQStFO0FBRS9FLGlDQUFpQztBQUVqQyxRQUFRLENBQUMsT0FBTyxFQUFFO0lBQ2hCLFFBQVEsQ0FBQyxpQkFBaUIsRUFBRTtRQUMxQixFQUFFLENBQUMsY0FBYyxFQUFFLEtBQUs7WUFDdEIsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDO1lBQ3pCLElBQUksTUFBTSxHQUFHLENBQUMsQ0FBQztZQUNmLE1BQU0sZ0JBQVEsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxFQUFFLElBQUksQ0FBQyxFQUFFLENBQUM7WUFDbEQsTUFBTSxDQUFDLEVBQUUsQ0FBQyxNQUFNLEdBQUcsS0FBSyxJQUFJLElBQUksQ0FBQyxDQUFDO1FBQ3BDLENBQUMsQ0FBQyxDQUFDO1FBQ0gsRUFBRSxDQUFDLDZCQUE2QixFQUFFLEtBQUs7WUFDckMsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDO1lBQ3pCLElBQUksTUFBTSxHQUFHLENBQUMsQ0FBQztZQUNmLElBQUksS0FBSyxHQUFHLENBQUMsQ0FBQztZQUNkLE1BQU0sSUFBSSxHQUFHLGdCQUFRLENBQUMsR0FBRyxFQUFFO2dCQUN6QixLQUFLLEVBQUUsQ0FBQztnQkFDUixNQUFNLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDO1lBQ3RCLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQztZQUNULElBQUksRUFBRSxDQUFDO1lBQ1AsSUFBSSxFQUFFLENBQUM7WUFDUCxJQUFJLEVBQUUsQ0FBQztZQUNQLE1BQU0sSUFBSSxFQUFFLENBQUM7WUFDYixNQUFNLENBQUMsRUFBRSxDQUFDLE1BQU0sR0FBRyxLQUFLLElBQUksSUFBSSxDQUFDLENBQUM7WUFDbEMsTUFBTSxDQUFDLFdBQVcsQ0FBQyxLQUFLLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDL0IsQ0FBQyxDQUFDLENBQUM7UUFDSCxFQUFFLENBQUMsVUFBVSxFQUFFO1lBQ2IsTUFBTSxDQUFDLFdBQVcsQ0FBQyxXQUFHLENBQUMsT0FBTyxDQUFDLEVBQUUsa0NBQWtDLENBQUMsQ0FBQztZQUNyRSxNQUFNLENBQUMsV0FBVyxDQUFDLFdBQUcsQ0FBQywwRUFBMEUsQ0FBQyxFQUFFLGtDQUFrQyxDQUFDLENBQUM7WUFDeEksTUFBTSxDQUFDLFdBQVcsQ0FBQyxXQUFHLENBQUMsRUFBRSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSwwQkFBMEIsQ0FBQyxFQUFFLFFBQVEsQ0FBQyxDQUFDLEVBQUUsa0NBQWtDLENBQUMsQ0FBQztRQUMzSSxDQUFDLENBQUMsQ0FBQztRQUNILEVBQUUsQ0FBQyxnQkFBZ0IsRUFBRTtZQUNuQixNQUFNLENBQUMsV0FBVyxDQUFDLHVCQUFlLENBQUMsYUFBYSxDQUFDLEVBQUUsaUJBQWlCLENBQUMsQ0FBQztZQUN0RSxNQUFNLENBQUMsV0FBVyxDQUFDLHVCQUFlLENBQUMsdUJBQWUsQ0FBQyxhQUFhLENBQUMsQ0FBQyxFQUFFLGFBQWEsQ0FBQyxDQUFDO1lBRW5GLE1BQU0sQ0FBQyxXQUFXLENBQUMsdUJBQWUsQ0FBQyxPQUFPLENBQUMsRUFBRSxTQUFTLENBQUMsQ0FBQztZQUN4RCxNQUFNLENBQUMsV0FBVyxDQUFDLHVCQUFlLENBQUMsdUJBQWUsQ0FBQyxPQUFPLENBQUMsQ0FBQyxFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBQ3pFLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qIGdsb2JhbCBkZXNjcmliZSwgaXQgKi9cbmltcG9ydCAqIGFzIGZzIGZyb20gJ2ZzJztcbmltcG9ydCAqIGFzIHBhdGggZnJvbSAncGF0aCc7XG5cbmltcG9ydCB7IGRlYm91bmNlLCBtZDUsIGJhc2U2NFVybERlY29kZSwgYmFzZTY0VXJsRW5jb2RlIH0gZnJvbSAnLi4vc3JjL2luZGV4JztcblxuaW1wb3J0ICogYXMgYXNzZXJ0IGZyb20gJ2Fzc2VydCc7XG5cbmRlc2NyaWJlKCdVdGlscycsIGZ1bmN0aW9uKCkge1xuICBkZXNjcmliZSgnZGVib3VuY2Ugc2hvdWxkJywgZnVuY3Rpb24oKSB7XG4gICAgaXQoJ2RlbGF5IGEgY2FsbCcsIGFzeW5jIGZ1bmN0aW9uKCkge1xuICAgICAgY29uc3QgZmlyc3QgPSBEYXRlLm5vdygpO1xuICAgICAgbGV0IHNlY29uZCA9IDA7XG4gICAgICBhd2FpdCBkZWJvdW5jZSgoKSA9PiBzZWNvbmQgPSBEYXRlLm5vdygpLCAxMDAwKSgpO1xuICAgICAgYXNzZXJ0Lm9rKHNlY29uZCAtIGZpcnN0ID49IDEwMDApO1xuICAgIH0pO1xuICAgIGl0KCdvbmx5IGNhbGwgdGhlIGZ1bmN0aW9uIG9uY2UnLCBhc3luYyBmdW5jdGlvbigpIHtcbiAgICAgIGNvbnN0IGZpcnN0ID0gRGF0ZS5ub3coKTtcbiAgICAgIGxldCBzZWNvbmQgPSAwO1xuICAgICAgbGV0IGNvdW50ID0gMDtcbiAgICAgIGNvbnN0IGZ1bmMgPSBkZWJvdW5jZSgoKSA9PiB7XG4gICAgICAgIGNvdW50Kys7XG4gICAgICAgIHNlY29uZCA9IERhdGUubm93KCk7XG4gICAgICB9LCAxMDAwKTtcbiAgICAgIGZ1bmMoKTtcbiAgICAgIGZ1bmMoKTtcbiAgICAgIGZ1bmMoKTtcbiAgICAgIGF3YWl0IGZ1bmMoKTtcbiAgICAgIGFzc2VydC5vayhzZWNvbmQgLSBmaXJzdCA+PSAxMDAwKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChjb3VudCwgMSk7XG4gICAgfSk7XG4gICAgaXQoJ3J1bnMgbWQ1JywgZnVuY3Rpb24oKSB7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwobWQ1KCdoZWxsbycpLCAnNWQ0MTQwMmFiYzRiMmE3NmI5NzE5ZDkxMTAxN2M1OTInKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChtZDUoJzAxMjM0NTY3ODlhYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ekFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaMDEyMzQ1Njc4OScpLCAnYzE5MDZmYTRlYzcxZWJkYzAyYzQ5YzVkMTk5MDhhMzknKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChtZDUoZnMucmVhZEZpbGVTeW5jKHBhdGguam9pbihfX2Rpcm5hbWUsICcuLi8uLi9maXh0dXJlcy9zaGFyZS5qcGcnKSwgJ2JpbmFyeScpKSwgJzdiNTU0NDZhZDg3Mjk3M2M1ZGI1MDA2OTA1Y2M5MmFhJyk7XG4gICAgfSk7XG4gICAgaXQoJ3J1bnMgYmFzZTY0VXJsJywgZnVuY3Rpb24oKSB7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoYmFzZTY0VXJsRW5jb2RlKCdBZGFtIE1pbGxlcicpLCAnUVdSaGJTQk5hV3hzWlhJJyk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoYmFzZTY0VXJsRGVjb2RlKGJhc2U2NFVybEVuY29kZSgnQWRhbSBNaWxsZXInKSksICdBZGFtIE1pbGxlcicpO1xuXG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoYmFzZTY0VXJsRW5jb2RlKCdLZWxseScpLCAnUzJWc2JIaycpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKGJhc2U2NFVybERlY29kZShiYXNlNjRVcmxFbmNvZGUoJ0tlbGx5JykpLCAnS2VsbHknKTtcbiAgICB9KTtcbiAgfSk7XG59KTtcbiJdfQ== | ||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90ZXN0L2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQUEseUJBQXlCO0FBQ3pCLHlCQUF5QjtBQUN6Qiw2QkFBNkI7QUFFN0Isd0NBQStFO0FBRS9FLGlDQUFpQztBQUVqQyxRQUFRLENBQUMsT0FBTyxFQUFFO0lBQ2hCLFFBQVEsQ0FBQyxpQkFBaUIsRUFBRTtRQUMxQixFQUFFLENBQUMsY0FBYyxFQUFFLEtBQUs7WUFDdEIsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDO1lBQ3pCLElBQUksTUFBTSxHQUFHLENBQUMsQ0FBQztZQUNmLE1BQU0sZ0JBQVEsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxFQUFFLElBQUksQ0FBQyxFQUFFLENBQUM7WUFDbEQsTUFBTSxDQUFDLEVBQUUsQ0FBQyxNQUFNLEdBQUcsS0FBSyxJQUFJLElBQUksQ0FBQyxDQUFDO1FBQ3BDLENBQUMsQ0FBQyxDQUFDO1FBQ0gsRUFBRSxDQUFDLDZCQUE2QixFQUFFLEtBQUs7WUFDckMsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDO1lBQ3pCLElBQUksTUFBTSxHQUFHLENBQUMsQ0FBQztZQUNmLElBQUksS0FBSyxHQUFHLENBQUMsQ0FBQztZQUNkLE1BQU0sSUFBSSxHQUFHLGdCQUFRLENBQUMsR0FBRyxFQUFFO2dCQUN6QixLQUFLLEVBQUUsQ0FBQztnQkFDUixNQUFNLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDO1lBQ3RCLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQztZQUNULElBQUksRUFBRSxDQUFDO1lBQ1AsSUFBSSxFQUFFLENBQUM7WUFDUCxJQUFJLEVBQUUsQ0FBQztZQUNQLE1BQU0sSUFBSSxFQUFFLENBQUM7WUFDYixNQUFNLENBQUMsRUFBRSxDQUFDLE1BQU0sR0FBRyxLQUFLLElBQUksSUFBSSxDQUFDLENBQUM7WUFDbEMsTUFBTSxDQUFDLFdBQVcsQ0FBQyxLQUFLLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDL0IsQ0FBQyxDQUFDLENBQUM7UUFDSCxFQUFFLENBQUMseUJBQXlCLEVBQUUsS0FBSztZQUNqQyxJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQ3JCLE1BQU0sSUFBSSxHQUFHLGdCQUFRLENBQUMsQ0FBQyxHQUFhLEVBQUUsRUFBRTtnQkFDdEMsR0FBRyxDQUFDLENBQUMsQ0FBQyxHQUFHLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUNsQixDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7WUFDTixNQUFNLE1BQU0sR0FBRyxPQUFPLENBQUMsV0FBVyxFQUFFLENBQUMsUUFBUSxHQUFHLElBQUksR0FBRyxJQUFJLENBQUM7WUFDNUQsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLElBQUksRUFBRSxDQUFDLEVBQUUsRUFBRTtnQkFDN0IsTUFBTSxJQUFJLENBQUMsSUFBSSxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7YUFDeEM7WUFDRCxNQUFNLENBQUMsRUFBRSxFQUFFLENBQUM7WUFDWixNQUFNLElBQUksT0FBTyxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsVUFBVSxDQUFDLE9BQU8sRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDO1lBQ3hELE1BQU0sS0FBSyxHQUFHLE9BQU8sQ0FBQyxXQUFXLEVBQUUsQ0FBQyxRQUFRLEdBQUcsSUFBSSxHQUFHLElBQUksQ0FBQztZQUMzRCxNQUFNLENBQUMsRUFBRSxDQUFDLEtBQUssSUFBSSxNQUFNLEVBQUUscURBQXFELENBQUMsQ0FBQztRQUNwRixDQUFDLENBQUMsQ0FBQztRQUNILEVBQUUsQ0FBQyxVQUFVLEVBQUU7WUFDYixNQUFNLENBQUMsV0FBVyxDQUFDLFdBQUcsQ0FBQyxPQUFPLENBQUMsRUFBRSxrQ0FBa0MsQ0FBQyxDQUFDO1lBQ3JFLE1BQU0sQ0FBQyxXQUFXLENBQUMsV0FBRyxDQUFDLDBFQUEwRSxDQUFDLEVBQUUsa0NBQWtDLENBQUMsQ0FBQztZQUN4SSxNQUFNLENBQUMsV0FBVyxDQUFDLFdBQUcsQ0FBQyxFQUFFLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLDBCQUEwQixDQUFDLEVBQUUsUUFBUSxDQUFDLENBQUMsRUFBRSxrQ0FBa0MsQ0FBQyxDQUFDO1FBQzNJLENBQUMsQ0FBQyxDQUFDO1FBQ0gsRUFBRSxDQUFDLGdCQUFnQixFQUFFO1lBQ25CLE1BQU0sQ0FBQyxXQUFXLENBQUMsdUJBQWUsQ0FBQyxhQUFhLENBQUMsRUFBRSxpQkFBaUIsQ0FBQyxDQUFDO1lBQ3RFLE1BQU0sQ0FBQyxXQUFXLENBQUMsdUJBQWUsQ0FBQyx1QkFBZSxDQUFDLGFBQWEsQ0FBQyxDQUFDLEVBQUUsYUFBYSxDQUFDLENBQUM7WUFFbkYsTUFBTSxDQUFDLFdBQVcsQ0FBQyx1QkFBZSxDQUFDLE9BQU8sQ0FBQyxFQUFFLFNBQVMsQ0FBQyxDQUFDO1lBQ3hELE1BQU0sQ0FBQyxXQUFXLENBQUMsdUJBQWUsQ0FBQyx1QkFBZSxDQUFDLE9BQU8sQ0FBQyxDQUFDLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFDekUsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztBQUNMLENBQUMsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyogZ2xvYmFsIGRlc2NyaWJlLCBpdCAqL1xuaW1wb3J0ICogYXMgZnMgZnJvbSAnZnMnO1xuaW1wb3J0ICogYXMgcGF0aCBmcm9tICdwYXRoJztcblxuaW1wb3J0IHsgZGVib3VuY2UsIG1kNSwgYmFzZTY0VXJsRGVjb2RlLCBiYXNlNjRVcmxFbmNvZGUgfSBmcm9tICcuLi9zcmMvaW5kZXgnO1xuXG5pbXBvcnQgKiBhcyBhc3NlcnQgZnJvbSAnYXNzZXJ0JztcblxuZGVzY3JpYmUoJ1V0aWxzJywgZnVuY3Rpb24oKSB7XG4gIGRlc2NyaWJlKCdkZWJvdW5jZSBzaG91bGQnLCBmdW5jdGlvbigpIHtcbiAgICBpdCgnZGVsYXkgYSBjYWxsJywgYXN5bmMgZnVuY3Rpb24oKSB7XG4gICAgICBjb25zdCBmaXJzdCA9IERhdGUubm93KCk7XG4gICAgICBsZXQgc2Vjb25kID0gMDtcbiAgICAgIGF3YWl0IGRlYm91bmNlKCgpID0+IHNlY29uZCA9IERhdGUubm93KCksIDEwMDApKCk7XG4gICAgICBhc3NlcnQub2soc2Vjb25kIC0gZmlyc3QgPj0gMTAwMCk7XG4gICAgfSk7XG4gICAgaXQoJ29ubHkgY2FsbCB0aGUgZnVuY3Rpb24gb25jZScsIGFzeW5jIGZ1bmN0aW9uKCkge1xuICAgICAgY29uc3QgZmlyc3QgPSBEYXRlLm5vdygpO1xuICAgICAgbGV0IHNlY29uZCA9IDA7XG4gICAgICBsZXQgY291bnQgPSAwO1xuICAgICAgY29uc3QgZnVuYyA9IGRlYm91bmNlKCgpID0+IHtcbiAgICAgICAgY291bnQrKztcbiAgICAgICAgc2Vjb25kID0gRGF0ZS5ub3coKTtcbiAgICAgIH0sIDEwMDApO1xuICAgICAgZnVuYygpO1xuICAgICAgZnVuYygpO1xuICAgICAgZnVuYygpO1xuICAgICAgYXdhaXQgZnVuYygpO1xuICAgICAgYXNzZXJ0Lm9rKHNlY29uZCAtIGZpcnN0ID49IDEwMDApO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKGNvdW50LCAxKTtcbiAgICB9KTtcbiAgICBpdCgnbm8gZGVib3VuY2UgbWVtb3J5IGxlYWsnLCBhc3luYyBmdW5jdGlvbigpIHtcbiAgICAgIHRoaXMudGltZW91dCgxMjAwMDApO1xuICAgICAgY29uc3QgZnVuYyA9IGRlYm91bmNlKChhcnI6IG51bWJlcltdKSA9PiB7XG4gICAgICAgIGFyclswXSA9IGFyclsxXTtcbiAgICAgIH0sIDEpO1xuICAgICAgY29uc3QgYmVmb3JlID0gcHJvY2Vzcy5tZW1vcnlVc2FnZSgpLmhlYXBVc2VkIC8gMTAyNCAvIDEwMjQ7XG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IDIwMDA7IGkrKykge1xuICAgICAgICBhd2FpdCBmdW5jKG5ldyBBcnJheSgxMDAwMDAwKS5maWxsKDEpKTtcbiAgICAgIH1cbiAgICAgIGdsb2JhbC5nYygpO1xuICAgICAgYXdhaXQgbmV3IFByb21pc2UocmVzb2x2ZSA9PiBzZXRUaW1lb3V0KHJlc29sdmUsIDMwMDApKTtcbiAgICAgIGNvbnN0IGFmdGVyID0gcHJvY2Vzcy5tZW1vcnlVc2FnZSgpLmhlYXBVc2VkIC8gMTAyNCAvIDEwMjQ7XG4gICAgICBhc3NlcnQub2soYWZ0ZXIgPD0gYmVmb3JlLCAnbWVtb3J5IHVzYWdlIGRvZXMgbm90IGdyb3cgd2l0aCBtYW55IGRlYm91bmNlIGNhbGxzJyk7XG4gICAgfSk7XG4gICAgaXQoJ3J1bnMgbWQ1JywgZnVuY3Rpb24oKSB7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwobWQ1KCdoZWxsbycpLCAnNWQ0MTQwMmFiYzRiMmE3NmI5NzE5ZDkxMTAxN2M1OTInKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChtZDUoJzAxMjM0NTY3ODlhYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ekFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaMDEyMzQ1Njc4OScpLCAnYzE5MDZmYTRlYzcxZWJkYzAyYzQ5YzVkMTk5MDhhMzknKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChtZDUoZnMucmVhZEZpbGVTeW5jKHBhdGguam9pbihfX2Rpcm5hbWUsICcuLi8uLi9maXh0dXJlcy9zaGFyZS5qcGcnKSwgJ2JpbmFyeScpKSwgJzdiNTU0NDZhZDg3Mjk3M2M1ZGI1MDA2OTA1Y2M5MmFhJyk7XG4gICAgfSk7XG4gICAgaXQoJ3J1bnMgYmFzZTY0VXJsJywgZnVuY3Rpb24oKSB7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoYmFzZTY0VXJsRW5jb2RlKCdBZGFtIE1pbGxlcicpLCAnUVdSaGJTQk5hV3hzWlhJJyk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoYmFzZTY0VXJsRGVjb2RlKGJhc2U2NFVybEVuY29kZSgnQWRhbSBNaWxsZXInKSksICdBZGFtIE1pbGxlcicpO1xuXG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoYmFzZTY0VXJsRW5jb2RlKCdLZWxseScpLCAnUzJWc2JIaycpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKGJhc2U2NFVybERlY29kZShiYXNlNjRVcmxFbmNvZGUoJ0tlbGx5JykpLCAnS2VsbHknKTtcbiAgICB9KTtcbiAgfSk7XG59KTtcbiJdfQ== |
{ | ||
"name": "@universe/util", | ||
"version": "0.2.4", | ||
"version": "0.2.5", | ||
"main": "dist/src/index.js", | ||
@@ -12,5 +12,4 @@ "description": "Universe development utilities.", | ||
"pretest": "yarn run build", | ||
"test": "mocha dist/test", | ||
"watch": "watch 'yarn run test' './src' './test' --wait=3", | ||
"prepublish": "yarn test" | ||
"test": "mocha --expose-gc dist/test", | ||
"watch": "watch 'yarn run test' './src' './test' --wait=3" | ||
}, | ||
@@ -17,0 +16,0 @@ "dependencies": {}, |
@@ -0,1 +1,6 @@ | ||
/* global MessageChannel */ | ||
import { MessageChannel as IMessageChannel } from 'worker_threads'; | ||
const IS_BROWSER = typeof window === 'object'; | ||
// Generics type checking utils. | ||
@@ -50,5 +55,5 @@ export const isNull = (v: unknown): v is null => v === null; | ||
// Cross environment utility functions. | ||
const btoa = typeof window === 'object' ? window.btoa : (str: string) => Buffer.from(str, 'utf8').toString('base64'); | ||
const atob = typeof window === 'object' ? window.atob : (str: string) => Buffer.from(str, 'base64').toString('utf8'); | ||
const rand = typeof window === 'object' ? window.crypto.getRandomValues.bind(window.crypto) : require('crypto').randomFillSync; | ||
const btoa = IS_BROWSER ? window.btoa : (str: string) => Buffer.from(str, 'utf8').toString('base64'); | ||
const atob = IS_BROWSER ? window.atob : (str: string) => Buffer.from(str, 'base64').toString('utf8'); | ||
const rand = IS_BROWSER ? window.crypto.getRandomValues.bind(window.crypto) : require('crypto').randomFillSync; | ||
@@ -74,9 +79,16 @@ // https://stackoverflow.com/questions/105034/create-guid-uuid-in-javascript | ||
export const debounce = <F extends (...args: any) => any>(func: F, timeout: number) => { | ||
let ref: NodeJS.Timeout; | ||
let promise: Promise<ReturnType<F>> | undefined; | ||
let finish: (val: ReturnType<F>) => void; | ||
let ref: NodeJS.Timeout | null = null; | ||
let promise: Promise<ReturnType<F>> | null = null; | ||
let finish: ((val: ReturnType<F>) => void) | null = null; | ||
return function(this: ThisParameterType<F>, ...args: Parameters<F>): Promise<ReturnType<F>> { | ||
promise = promise || new Promise((resolve) => finish = resolve); | ||
clearTimeout(ref); | ||
ref = setTimeout(() => (promise = undefined) || finish(func.apply(this, args)), timeout); | ||
ref && clearTimeout(ref); | ||
ref = setTimeout(() => { | ||
const resolve = finish; | ||
promise = ref = finish = null; | ||
ref = null; | ||
finish = null; | ||
const res = func.apply(this, args); | ||
resolve && resolve(res); | ||
}, timeout); | ||
return promise; | ||
@@ -263,1 +275,49 @@ }; | ||
} | ||
/* eslint-disable-next-line */ | ||
// @ts-ignore | ||
const NewMessageChannel: typeof IMessageChannel = IS_BROWSER ? MessageChannel : require('worker_threads').MessageChannel; | ||
let mid = 0; | ||
const { port1, port2 } = new NewMessageChannel(); | ||
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */ | ||
const cloneCallbacks: Map<number, ((dat: any) => void)> = new Map(); | ||
const resolveClone = (message: { mid: number; data: object}) => { | ||
const cb = cloneCallbacks.get(message.mid); | ||
cloneCallbacks.delete(message.mid); | ||
cb && cb(message.data); | ||
}; | ||
if (!IS_BROWSER) { | ||
port1.unref(); | ||
port2.unref(); | ||
port2.on('message', resolveClone); | ||
} | ||
// Use native V8 structured clone through worker thread message channels. | ||
export const deepClone = async<T>(data: T): Promise<T> => { | ||
if (typeof data !== 'object') { return data; } | ||
if (!data) { return data; } | ||
if (!IS_BROWSER) { | ||
// In Node.js it works better to re-use the same message channel. If we re-create the message channel for every clone | ||
// like in the browser it actually duplicates ALL objects (including primitives like strings) when passing it from one | ||
// context to the next. In high-load situations this puts a lot of pressure on the garbage collector and results in massive | ||
// memory spikes. | ||
return new Promise((resolve) => { | ||
cloneCallbacks.set(mid, resolve); | ||
port1.postMessage({ mid, data }); | ||
mid = mid + 1 % Number.MAX_SAFE_INTEGER; | ||
}); | ||
} | ||
else { | ||
// In the browser its better to create a new message channel for each clone. It does not (for whatever reason...) have the | ||
// same primitive cloning overhead as Node.js, and because it is more sync under the hood, re-using th same message channel | ||
// actually causes a backup, crashing the browser in high-load situations. | ||
return new Promise((resolve) => { | ||
const { port1, port2 } = new NewMessageChannel(); | ||
/* eslint-disable-next-line */ | ||
// @ts-ignore | ||
port2.onmessage = (o) => resolve(o.data); | ||
port1.postMessage(data); | ||
}); | ||
} | ||
}; |
@@ -32,2 +32,16 @@ /* global describe, it */ | ||
}); | ||
it('no debounce memory leak', async function() { | ||
this.timeout(120000); | ||
const func = debounce((arr: number[]) => { | ||
arr[0] = arr[1]; | ||
}, 1); | ||
const before = process.memoryUsage().heapUsed / 1024 / 1024; | ||
for (let i = 0; i < 2000; i++) { | ||
await func(new Array(1000000).fill(1)); | ||
} | ||
global.gc(); | ||
await new Promise(resolve => setTimeout(resolve, 3000)); | ||
const after = process.memoryUsage().heapUsed / 1024 / 1024; | ||
assert.ok(after <= before, 'memory usage does not grow with many debounce calls'); | ||
}); | ||
it('runs md5', function() { | ||
@@ -34,0 +48,0 @@ assert.strictEqual(md5('hello'), '5d41402abc4b2a76b9719d911017c592'); |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
AI-detected possible typosquat
Supply chain riskAI has identified this package as a potential typosquat of a more popular package. This suggests that the package may be intentionally mimicking another package's name, description, or other metadata.
Found 1 instance in 1 package
431772
824
1