Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@fluidframework/common-utils

Package Overview
Dependencies
Maintainers
3
Versions
44
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@fluidframework/common-utils - npm Package Compare versions

Comparing version 1.0.0 to 1.1.0

dist/idleTaskScheduler.d.ts

26

.eslintrc.js

@@ -7,15 +7,15 @@ /*!

module.exports = {
extends: [require.resolve("@fluidframework/eslint-config-fluid"), "prettier"],
parserOptions: {
project: [
"./tsconfig.json",
"./src/test/mocha/tsconfig.json",
"./src/test/jest/tsconfig.json",
"./src/test/types/tsconfig.json",
],
},
rules: {
// TODO: Remove once this config extends `recommended` or `strict` above.
"@typescript-eslint/explicit-function-return-type": "error",
},
extends: [require.resolve("@fluidframework/eslint-config-fluid/minimal"), "prettier"],
parserOptions: {
project: [
"./tsconfig.json",
"./src/test/mocha/tsconfig.json",
"./src/test/jest/tsconfig.json",
"./src/test/types/tsconfig.json",
],
},
rules: {
// TODO: Remove once this config extends `recommended` or `strict` above.
"@typescript-eslint/explicit-function-return-type": "error",
},
};
{
"$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json",
"extends": "@fluidframework/build-common/api-extractor-common-strict.json",
"apiReport": {
"enabled": true,
"reportFolder": "<projectFolder>/api-report/"
},
"docModel": {
"enabled": true,
"apiJsonFilePath": "<projectFolder>/_api-extractor-temp/doc-models/<unscopedPackageName>.api.json"
}
"$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json",
"extends": "@fluidframework/build-common/api-extractor-common-strict.json",
"apiReport": {
"enabled": true,
"reportFolder": "<projectFolder>/api-report/"
},
"docModel": {
"enabled": true,
"apiJsonFilePath": "<projectFolder>/_api-extractor-temp/doc-models/<unscopedPackageName>.api.json"
}
}

@@ -23,3 +23,3 @@ ## API Report File for "@fluidframework/common-utils"

// @public
// @public @deprecated
export class BaseTelemetryNullLogger implements ITelemetryBaseLogger {

@@ -263,3 +263,3 @@ send(event: ITelemetryBaseEvent): void;

// @public
// @public @deprecated
export class TelemetryNullLogger implements ITelemetryLogger {

@@ -266,0 +266,0 @@ // (undocumented)

@@ -1,5 +0,4 @@

{"/mnt/vss/_work/1/s/common/lib/common-utils/src/assert.ts": {"path":"/mnt/vss/_work/1/s/common/lib/common-utils/src/assert.ts","statementMap":{"0":{"start":{"line":16,"column":4},"end":{"line":20,"column":null}},"1":{"start":{"line":17,"column":8},"end":{"line":19,"column":10}},"2":{"start":{"line":15,"column":0},"end":{"line":15,"column":16}}},"fnMap":{"0":{"name":"assert","decl":{"start":{"line":15,"column":16},"end":{"line":15,"column":22}},"loc":{"start":{"line":15,"column":67},"end":{"line":21,"column":1}}}},"branchMap":{"0":{"loc":{"start":{"line":16,"column":4},"end":{"line":20,"column":null}},"type":"if","locations":[{"start":{"line":16,"column":4},"end":{"line":20,"column":null}},{"start":{"line":16,"column":4},"end":{"line":20,"column":null}}]},"1":{"loc":{"start":{"line":18,"column":42},"end":{"line":18,"column":86}},"type":"cond-expr","locations":[{"start":{"line":18,"column":42},"end":{"line":18,"column":86}},{"start":{"line":18,"column":89},"end":{"line":18,"column":96}}]}},"s":{"0":4,"1":0,"2":1},"f":{"0":4},"b":{"0":[0,4],"1":[0,0]}}
,"/mnt/vss/_work/1/s/common/lib/common-utils/src/bufferBrowser.ts": {"path":"/mnt/vss/_work/1/s/common/lib/common-utils/src/bufferBrowser.ts","statementMap":{"0":{"start":{"line":6,"column":0},"end":{"line":6,"column":38}},"1":{"start":{"line":7,"column":0},"end":{"line":7,"column":34}},"2":{"start":{"line":19,"column":4},"end":{"line":31,"column":null}},"3":{"start":{"line":21,"column":12},"end":{"line":21,"column":47}},"4":{"start":{"line":26,"column":12},"end":{"line":26,"column":49}},"5":{"start":{"line":29,"column":12},"end":{"line":29,"column":60}},"6":{"start":{"line":18,"column":0},"end":{"line":18,"column":16}},"7":{"start":{"line":40,"column":30},"end":{"line":41,"column":42}},"8":{"start":{"line":41,"column":4},"end":{"line":41,"column":42}},"9":{"start":{"line":40,"column":13},"end":{"line":40,"column":30}},"10":{"start":{"line":50,"column":30},"end":{"line":51,"column":43}},"11":{"start":{"line":51,"column":4},"end":{"line":51,"column":43}},"12":{"start":{"line":50,"column":13},"end":{"line":50,"column":30}},"13":{"start":{"line":66,"column":18},"end":{"line":66,"column":81}},"14":{"start":{"line":67,"column":4},"end":{"line":75,"column":6}},"15":{"start":{"line":65,"column":0},"end":{"line":65,"column":16}},"16":{"start":{"line":90,"column":8},"end":{"line":90,"column":50}},"17":{"start":{"line":99,"column":8},"end":{"line":118,"column":null}},"18":{"start":{"line":100,"column":12},"end":{"line":100,"column":87}},"19":{"start":{"line":102,"column":15},"end":{"line":118,"column":null}},"20":{"start":{"line":104,"column":12},"end":{"line":104,"column":88}},"21":{"start":{"line":105,"column":12},"end":{"line":108,"column":14}},"22":{"start":{"line":109,"column":12},"end":{"line":113,"column":14}},"23":{"start":{"line":114,"column":15},"end":{"line":118,"column":null}},"24":{"start":{"line":115,"column":12},"end":{"line":115,"column":100}},"25":{"start":{"line":117,"column":12},"end":{"line":117,"column":34}},"26":{"start":{"line":126,"column":23},"end":{"line":126,"column":38}},"27":{"start":{"line":127,"column":28},"end":{"line":127,"column":73}},"28":{"start":{"line":128,"column":8},"end":{"line":135,"column":null}},"29":{"start":{"line":134,"column":12},"end":{"line":134,"column":35}},"30":{"start":{"line":137,"column":8},"end":{"line":137,"column":63}},"31":{"start":{"line":141,"column":8},"end":{"line":156,"column":null}},"32":{"start":{"line":143,"column":40},"end":{"line":143,"column":64}},"33":{"start":{"line":144,"column":32},"end":{"line":144,"column":69}},"34":{"start":{"line":145,"column":16},"end":{"line":145,"column":53}},"35":{"start":{"line":150,"column":32},"end":{"line":150,"column":61}},"36":{"start":{"line":151,"column":16},"end":{"line":151,"column":53}},"37":{"start":{"line":154,"column":16},"end":{"line":154,"column":64}},"38":{"start":{"line":160,"column":8},"end":{"line":160,"column":41}},"39":{"start":{"line":169,"column":27},"end":{"line":169,"column":30}},"40":{"start":{"line":172,"column":8},"end":{"line":172,"column":50}},"41":{"start":{"line":176,"column":8},"end":{"line":176,"column":61}},"42":{"start":{"line":180,"column":8},"end":{"line":183,"column":null}},"43":{"start":{"line":181,"column":33},"end":{"line":181,"column":55}},"44":{"start":{"line":182,"column":12},"end":{"line":182,"column":66}},"45":{"start":{"line":184,"column":8},"end":{"line":184,"column":28}},"46":{"start":{"line":81,"column":0},"end":{"line":81,"column":13}}},"fnMap":{"0":{"name":"Uint8ArrayToString","decl":{"start":{"line":18,"column":16},"end":{"line":18,"column":34}},"loc":{"start":{"line":18,"column":69},"end":{"line":32,"column":1}}},"1":{"name":"(anonymous_7)","decl":{"start":{"line":40,"column":30},"end":{"line":40,"column":31}},"loc":{"start":{"line":41,"column":4},"end":{"line":41,"column":42}}},"2":{"name":"(anonymous_8)","decl":{"start":{"line":50,"column":30},"end":{"line":50,"column":31}},"loc":{"start":{"line":51,"column":4},"end":{"line":51,"column":43}}},"3":{"name":"isArrayBuffer","decl":{"start":{"line":65,"column":16},"end":{"line":65,"column":29}},"loc":{"start":{"line":65,"column":38},"end":{"line":76,"column":1}}},"4":{"name":"(anonymous_10)","decl":{"start":{"line":89,"column":11},"end":{"line":89,"column":19}},"loc":{"start":{"line":89,"column":37},"end":{"line":91,"column":5}}},"5":{"name":"(anonymous_11)","decl":{"start":{"line":98,"column":4},"end":{"line":98,"column":10}},"loc":{"start":{"line":98,"column":49},"end":{"line":119,"column":5}}},"6":{"name":"(anonymous_12)","decl":{"start":{"line":121,"column":4},"end":{"line":121,"column":10}},"loc":{"start":{"line":124,"column":27},"end":{"line":138,"column":5}}},"7":{"name":"(anonymous_13)","decl":{"start":{"line":140,"column":4},"end":{"line":140,"column":10}},"loc":{"start":{"line":140,"column":52},"end":{"line":157,"column":5}}},"8":{"name":"(anonymous_14)","decl":{"start":{"line":159,"column":4},"end":{"line":159,"column":10}},"loc":{"start":{"line":159,"column":28},"end":{"line":161,"column":5}}},"9":{"name":"(anonymous_15)","decl":{"start":{"line":168,"column":12},"end":{"line":168,"column":18}},"loc":{"start":{"line":168,"column":45},"end":{"line":185,"column":5}}}},"branchMap":{"0":{"loc":{"start":{"line":20,"column":8},"end":{"line":22,"column":null}},"type":"switch","locations":[{"start":{"line":20,"column":8},"end":{"line":22,"column":null}},{"start":{"line":23,"column":8},"end":{"line":23,"column":20}},{"start":{"line":24,"column":8},"end":{"line":24,"column":21}},{"start":{"line":25,"column":8},"end":{"line":27,"column":null}},{"start":{"line":28,"column":8},"end":{"line":30,"column":null}}]},"1":{"loc":{"start":{"line":68,"column":8},"end":{"line":68,"column":34}},"type":"binary-expr","locations":[{"start":{"line":68,"column":8},"end":{"line":68,"column":34}},{"start":{"line":69,"column":9},"end":{"line":69,"column":34}},{"start":{"line":70,"column":12},"end":{"line":70,"column":26}},{"start":{"line":71,"column":12},"end":{"line":71,"column":48}},{"start":{"line":72,"column":12},"end":{"line":72,"column":45}},{"start":{"line":73,"column":12},"end":{"line":73,"column":42}},{"start":{"line":74,"column":12},"end":{"line":74,"column":38}}]},"2":{"loc":{"start":{"line":99,"column":8},"end":{"line":118,"column":null}},"type":"if","locations":[{"start":{"line":99,"column":8},"end":{"line":118,"column":null}},{"start":{"line":99,"column":8},"end":{"line":118,"column":null}}]},"3":{"loc":{"start":{"line":102,"column":15},"end":{"line":118,"column":null}},"type":"if","locations":[{"start":{"line":102,"column":15},"end":{"line":118,"column":null}},{"start":{"line":102,"column":15},"end":{"line":118,"column":null}}]},"4":{"loc":{"start":{"line":102,"column":19},"end":{"line":102,"column":33}},"type":"binary-expr","locations":[{"start":{"line":102,"column":19},"end":{"line":102,"column":33}},{"start":{"line":102,"column":37},"end":{"line":102,"column":62}},{"start":{"line":102,"column":66},"end":{"line":102,"column":93}}]},"5":{"loc":{"start":{"line":114,"column":15},"end":{"line":118,"column":null}},"type":"if","locations":[{"start":{"line":114,"column":15},"end":{"line":118,"column":null}},{"start":{"line":114,"column":15},"end":{"line":118,"column":null}}]},"6":{"loc":{"start":{"line":126,"column":23},"end":{"line":126,"column":33}},"type":"cond-expr","locations":[{"start":{"line":126,"column":23},"end":{"line":126,"column":33}},{"start":{"line":126,"column":37},"end":{"line":126,"column":38}}]},"7":{"loc":{"start":{"line":126,"column":23},"end":{"line":126,"column":37}},"type":"binary-expr","locations":[{"start":{"line":126,"column":23},"end":{"line":126,"column":37}},{"start":{"line":126,"column":23},"end":{"line":126,"column":37}}]},"8":{"loc":{"start":{"line":127,"column":28},"end":{"line":127,"column":38}},"type":"cond-expr","locations":[{"start":{"line":127,"column":28},"end":{"line":127,"column":38}},{"start":{"line":127,"column":42},"end":{"line":127,"column":73}}]},"9":{"loc":{"start":{"line":127,"column":28},"end":{"line":127,"column":42}},"type":"binary-expr","locations":[{"start":{"line":127,"column":28},"end":{"line":127,"column":42}},{"start":{"line":127,"column":28},"end":{"line":127,"column":42}}]},"10":{"loc":{"start":{"line":128,"column":8},"end":{"line":135,"column":null}},"type":"if","locations":[{"start":{"line":128,"column":8},"end":{"line":135,"column":null}},{"start":{"line":128,"column":8},"end":{"line":135,"column":null}}]},"11":{"loc":{"start":{"line":129,"column":12},"end":{"line":129,"column":22}},"type":"binary-expr","locations":[{"start":{"line":129,"column":12},"end":{"line":129,"column":22}},{"start":{"line":130,"column":12},"end":{"line":130,"column":43}},{"start":{"line":131,"column":12},"end":{"line":131,"column":27}},{"start":{"line":132,"column":12},"end":{"line":132,"column":57}}]},"12":{"loc":{"start":{"line":142,"column":12},"end":{"line":146,"column":null}},"type":"switch","locations":[{"start":{"line":142,"column":12},"end":{"line":146,"column":null}},{"start":{"line":147,"column":12},"end":{"line":147,"column":24}},{"start":{"line":148,"column":12},"end":{"line":148,"column":25}},{"start":{"line":149,"column":12},"end":{"line":152,"column":null}},{"start":{"line":153,"column":12},"end":{"line":155,"column":null}}]},"13":{"loc":{"start":{"line":180,"column":8},"end":{"line":183,"column":null}},"type":"if","locations":[{"start":{"line":180,"column":8},"end":{"line":183,"column":null}},{"start":{"line":180,"column":8},"end":{"line":183,"column":null}}]}},"s":{"0":1,"1":1,"2":42,"3":21,"4":21,"5":0,"6":1,"7":1,"8":4,"9":1,"10":1,"11":6,"12":1,"13":18,"14":18,"15":1,"16":40,"17":42,"18":32,"19":10,"20":2,"21":2,"22":2,"23":8,"24":8,"25":0,"26":10,"27":10,"28":10,"29":0,"30":10,"31":32,"32":17,"33":17,"34":17,"35":15,"36":15,"37":0,"38":0,"39":17,"40":17,"41":17,"42":17,"43":9,"44":9,"45":17,"46":1},"f":{"0":42,"1":4,"2":6,"3":18,"4":40,"5":42,"6":10,"7":32,"8":0,"9":17},"b":{"0":[21,4,6,21,0],"1":[18,8,0,0,0,0,0],"2":[32,10],"3":[2,8],"4":[10,10,10],"5":[8,0],"6":[0,10],"7":[10,10],"8":[0,10],"9":[10,10],"10":[0,10],"11":[10,10,10,10],"12":[17,2,2,15,0],"13":[9,8]}}
,"/mnt/vss/_work/1/s/common/lib/common-utils/src/bufferNode.ts": {"path":"/mnt/vss/_work/1/s/common/lib/common-utils/src/bufferNode.ts","statementMap":{"0":{"start":{"line":21,"column":13},"end":{"line":21,"column":32}},"1":{"start":{"line":34,"column":4},"end":{"line":34,"column":95}},"2":{"start":{"line":32,"column":0},"end":{"line":32,"column":16}},"3":{"start":{"line":42,"column":16},"end":{"line":42,"column":47}},"4":{"start":{"line":46,"column":4},"end":{"line":48,"column":76}},"5":{"start":{"line":41,"column":0},"end":{"line":41,"column":16}},"6":{"start":{"line":58,"column":30},"end":{"line":59,"column":43}},"7":{"start":{"line":59,"column":4},"end":{"line":59,"column":43}},"8":{"start":{"line":58,"column":13},"end":{"line":58,"column":30}}},"fnMap":{"0":{"name":"Uint8ArrayToString","decl":{"start":{"line":32,"column":16},"end":{"line":32,"column":34}},"loc":{"start":{"line":32,"column":69},"end":{"line":35,"column":1}}},"1":{"name":"stringToBuffer","decl":{"start":{"line":41,"column":16},"end":{"line":41,"column":30}},"loc":{"start":{"line":41,"column":62},"end":{"line":49,"column":1}}},"2":{"name":"(anonymous_2)","decl":{"start":{"line":58,"column":30},"end":{"line":58,"column":31}},"loc":{"start":{"line":59,"column":4},"end":{"line":59,"column":43}}}},"branchMap":{"0":{"loc":{"start":{"line":34,"column":34},"end":{"line":34,"column":56}},"type":"cond-expr","locations":[{"start":{"line":34,"column":34},"end":{"line":34,"column":56}},{"start":{"line":34,"column":59},"end":{"line":34,"column":94}}]},"1":{"loc":{"start":{"line":47,"column":10},"end":{"line":47,"column":20}},"type":"cond-expr","locations":[{"start":{"line":47,"column":10},"end":{"line":47,"column":20}},{"start":{"line":48,"column":10},"end":{"line":48,"column":75}}]}},"s":{"0":1,"1":2,"2":1,"3":4,"4":4,"5":1,"6":1,"7":6,"8":1},"f":{"0":2,"1":4,"2":6},"b":{"0":[0,2],"1":[0,4]}}
,"/mnt/vss/_work/1/s/common/lib/common-utils/src/hashFileNode.ts": {"path":"/mnt/vss/_work/1/s/common/lib/common-utils/src/hashFileNode.ts","statementMap":{"0":{"start":{"line":7,"column":0},"end":{"line":7,"column":31}},"1":{"start":{"line":9,"column":0},"end":{"line":9,"column":35}},"2":{"start":{"line":30,"column":4},"end":{"line":39,"column":null}},"3":{"start":{"line":32,"column":12},"end":{"line":32,"column":32}},"4":{"start":{"line":33,"column":12},"end":{"line":33,"column":18}},"5":{"start":{"line":36,"column":12},"end":{"line":36,"column":34}},"6":{"start":{"line":37,"column":12},"end":{"line":37,"column":18}},"7":{"start":{"line":40,"column":4},"end":{"line":40,"column":62}},"8":{"start":{"line":23,"column":0},"end":{"line":23,"column":7}},"9":{"start":{"line":51,"column":17},"end":{"line":51,"column":32}},"10":{"start":{"line":52,"column":23},"end":{"line":52,"column":73}},"11":{"start":{"line":53,"column":19},"end":{"line":53,"column":29}},"12":{"start":{"line":54,"column":4},"end":{"line":54,"column":74}},"13":{"start":{"line":50,"column":0},"end":{"line":50,"column":7}}},"fnMap":{"0":{"name":"hashFile","decl":{"start":{"line":23,"column":22},"end":{"line":23,"column":30}},"loc":{"start":{"line":26,"column":42},"end":{"line":41,"column":1}}},"1":{"name":"gitHashFile","decl":{"start":{"line":50,"column":22},"end":{"line":50,"column":33}},"loc":{"start":{"line":50,"column":49},"end":{"line":55,"column":1}}}},"branchMap":{"0":{"loc":{"start":{"line":25,"column":37},"end":{"line":25,"column":44}},"type":"default-arg","locations":[{"start":{"line":25,"column":37},"end":{"line":25,"column":44}}]},"1":{"loc":{"start":{"line":26,"column":37},"end":{"line":26,"column":42}},"type":"default-arg","locations":[{"start":{"line":26,"column":37},"end":{"line":26,"column":42}}]},"2":{"loc":{"start":{"line":31,"column":8},"end":{"line":34,"column":null}},"type":"switch","locations":[{"start":{"line":31,"column":8},"end":{"line":34,"column":null}},{"start":{"line":35,"column":8},"end":{"line":38,"column":null}}]}},"s":{"0":1,"1":1,"2":3,"3":1,"4":1,"5":2,"6":2,"7":3,"8":1,"9":6,"10":6,"11":6,"12":6,"13":1},"f":{"0":3,"1":6},"b":{"0":[0],"1":[1],"2":[1,2]}}
{"/mnt/vss/_work/1/s/common/lib/common-utils/src/bufferBrowser.ts": {"path":"/mnt/vss/_work/1/s/common/lib/common-utils/src/bufferBrowser.ts","statementMap":{"0":{"start":{"line":6,"column":0},"end":{"line":6,"column":38}},"1":{"start":{"line":18,"column":1},"end":{"line":30,"column":null}},"2":{"start":{"line":20,"column":3},"end":{"line":20,"column":38}},"3":{"start":{"line":25,"column":3},"end":{"line":25,"column":40}},"4":{"start":{"line":28,"column":3},"end":{"line":28,"column":51}},"5":{"start":{"line":17,"column":0},"end":{"line":17,"column":16}},"6":{"start":{"line":39,"column":30},"end":{"line":40,"column":39}},"7":{"start":{"line":40,"column":1},"end":{"line":40,"column":39}},"8":{"start":{"line":39,"column":13},"end":{"line":39,"column":30}},"9":{"start":{"line":49,"column":30},"end":{"line":50,"column":40}},"10":{"start":{"line":50,"column":1},"end":{"line":50,"column":40}},"11":{"start":{"line":49,"column":13},"end":{"line":49,"column":30}},"12":{"start":{"line":65,"column":15},"end":{"line":65,"column":78}},"13":{"start":{"line":66,"column":1},"end":{"line":74,"column":3}},"14":{"start":{"line":64,"column":0},"end":{"line":64,"column":16}},"15":{"start":{"line":89,"column":2},"end":{"line":89,"column":44}},"16":{"start":{"line":98,"column":2},"end":{"line":110,"column":null}},"17":{"start":{"line":99,"column":3},"end":{"line":99,"column":78}},"18":{"start":{"line":101,"column":9},"end":{"line":110,"column":null}},"19":{"start":{"line":105,"column":3},"end":{"line":105,"column":86}},"20":{"start":{"line":106,"column":9},"end":{"line":110,"column":null}},"21":{"start":{"line":107,"column":3},"end":{"line":107,"column":91}},"22":{"start":{"line":109,"column":3},"end":{"line":109,"column":25}},"23":{"start":{"line":118,"column":17},"end":{"line":118,"column":32}},"24":{"start":{"line":119,"column":22},"end":{"line":119,"column":67}},"25":{"start":{"line":120,"column":2},"end":{"line":127,"column":null}},"26":{"start":{"line":126,"column":3},"end":{"line":126,"column":26}},"27":{"start":{"line":129,"column":2},"end":{"line":129,"column":57}},"28":{"start":{"line":133,"column":2},"end":{"line":148,"column":null}},"29":{"start":{"line":135,"column":28},"end":{"line":135,"column":52}},"30":{"start":{"line":136,"column":20},"end":{"line":136,"column":57}},"31":{"start":{"line":137,"column":4},"end":{"line":137,"column":41}},"32":{"start":{"line":142,"column":20},"end":{"line":142,"column":49}},"33":{"start":{"line":143,"column":4},"end":{"line":143,"column":41}},"34":{"start":{"line":146,"column":4},"end":{"line":146,"column":52}},"35":{"start":{"line":152,"column":2},"end":{"line":152,"column":35}},"36":{"start":{"line":161,"column":21},"end":{"line":161,"column":24}},"37":{"start":{"line":164,"column":2},"end":{"line":164,"column":44}},"38":{"start":{"line":168,"column":2},"end":{"line":168,"column":55}},"39":{"start":{"line":172,"column":2},"end":{"line":175,"column":null}},"40":{"start":{"line":173,"column":24},"end":{"line":173,"column":46}},"41":{"start":{"line":174,"column":3},"end":{"line":174,"column":57}},"42":{"start":{"line":176,"column":2},"end":{"line":176,"column":22}},"43":{"start":{"line":80,"column":0},"end":{"line":80,"column":13}}},"fnMap":{"0":{"name":"Uint8ArrayToString","decl":{"start":{"line":17,"column":16},"end":{"line":17,"column":34}},"loc":{"start":{"line":17,"column":69},"end":{"line":31,"column":1}}},"1":{"name":"(anonymous_7)","decl":{"start":{"line":39,"column":30},"end":{"line":39,"column":31}},"loc":{"start":{"line":40,"column":1},"end":{"line":40,"column":39}}},"2":{"name":"(anonymous_8)","decl":{"start":{"line":49,"column":30},"end":{"line":49,"column":31}},"loc":{"start":{"line":50,"column":1},"end":{"line":50,"column":40}}},"3":{"name":"isArrayBuffer","decl":{"start":{"line":64,"column":16},"end":{"line":64,"column":29}},"loc":{"start":{"line":64,"column":38},"end":{"line":75,"column":1}}},"4":{"name":"(anonymous_10)","decl":{"start":{"line":88,"column":8},"end":{"line":88,"column":16}},"loc":{"start":{"line":88,"column":34},"end":{"line":90,"column":2}}},"5":{"name":"(anonymous_11)","decl":{"start":{"line":97,"column":1},"end":{"line":97,"column":7}},"loc":{"start":{"line":97,"column":46},"end":{"line":111,"column":2}}},"6":{"name":"(anonymous_12)","decl":{"start":{"line":113,"column":1},"end":{"line":113,"column":7}},"loc":{"start":{"line":116,"column":21},"end":{"line":130,"column":2}}},"7":{"name":"(anonymous_13)","decl":{"start":{"line":132,"column":1},"end":{"line":132,"column":7}},"loc":{"start":{"line":132,"column":49},"end":{"line":149,"column":2}}},"8":{"name":"(anonymous_14)","decl":{"start":{"line":151,"column":1},"end":{"line":151,"column":7}},"loc":{"start":{"line":151,"column":25},"end":{"line":153,"column":2}}},"9":{"name":"(anonymous_15)","decl":{"start":{"line":160,"column":9},"end":{"line":160,"column":15}},"loc":{"start":{"line":160,"column":42},"end":{"line":177,"column":2}}}},"branchMap":{"0":{"loc":{"start":{"line":19,"column":2},"end":{"line":21,"column":null}},"type":"switch","locations":[{"start":{"line":19,"column":2},"end":{"line":21,"column":null}},{"start":{"line":22,"column":2},"end":{"line":22,"column":14}},{"start":{"line":23,"column":2},"end":{"line":23,"column":15}},{"start":{"line":24,"column":2},"end":{"line":26,"column":null}},{"start":{"line":27,"column":2},"end":{"line":29,"column":null}}]},"1":{"loc":{"start":{"line":67,"column":2},"end":{"line":67,"column":28}},"type":"binary-expr","locations":[{"start":{"line":67,"column":2},"end":{"line":67,"column":28}},{"start":{"line":68,"column":3},"end":{"line":68,"column":28}},{"start":{"line":69,"column":3},"end":{"line":69,"column":17}},{"start":{"line":70,"column":3},"end":{"line":70,"column":39}},{"start":{"line":71,"column":3},"end":{"line":71,"column":36}},{"start":{"line":72,"column":3},"end":{"line":72,"column":33}},{"start":{"line":73,"column":3},"end":{"line":73,"column":29}}]},"2":{"loc":{"start":{"line":98,"column":2},"end":{"line":110,"column":null}},"type":"if","locations":[{"start":{"line":98,"column":2},"end":{"line":110,"column":null}},{"start":{"line":98,"column":2},"end":{"line":110,"column":null}}]},"3":{"loc":{"start":{"line":101,"column":9},"end":{"line":110,"column":null}},"type":"if","locations":[{"start":{"line":101,"column":9},"end":{"line":110,"column":null}},{"start":{"line":101,"column":9},"end":{"line":110,"column":null}}]},"4":{"loc":{"start":{"line":101,"column":13},"end":{"line":101,"column":27}},"type":"binary-expr","locations":[{"start":{"line":101,"column":13},"end":{"line":101,"column":27}},{"start":{"line":101,"column":31},"end":{"line":101,"column":56}},{"start":{"line":101,"column":60},"end":{"line":101,"column":87}}]},"5":{"loc":{"start":{"line":106,"column":9},"end":{"line":110,"column":null}},"type":"if","locations":[{"start":{"line":106,"column":9},"end":{"line":110,"column":null}},{"start":{"line":106,"column":9},"end":{"line":110,"column":null}}]},"6":{"loc":{"start":{"line":118,"column":17},"end":{"line":118,"column":27}},"type":"cond-expr","locations":[{"start":{"line":118,"column":17},"end":{"line":118,"column":27}},{"start":{"line":118,"column":31},"end":{"line":118,"column":32}}]},"7":{"loc":{"start":{"line":118,"column":17},"end":{"line":118,"column":31}},"type":"binary-expr","locations":[{"start":{"line":118,"column":17},"end":{"line":118,"column":31}},{"start":{"line":118,"column":17},"end":{"line":118,"column":31}}]},"8":{"loc":{"start":{"line":119,"column":22},"end":{"line":119,"column":32}},"type":"cond-expr","locations":[{"start":{"line":119,"column":22},"end":{"line":119,"column":32}},{"start":{"line":119,"column":36},"end":{"line":119,"column":67}}]},"9":{"loc":{"start":{"line":119,"column":22},"end":{"line":119,"column":36}},"type":"binary-expr","locations":[{"start":{"line":119,"column":22},"end":{"line":119,"column":36}},{"start":{"line":119,"column":22},"end":{"line":119,"column":36}}]},"10":{"loc":{"start":{"line":120,"column":2},"end":{"line":127,"column":null}},"type":"if","locations":[{"start":{"line":120,"column":2},"end":{"line":127,"column":null}},{"start":{"line":120,"column":2},"end":{"line":127,"column":null}}]},"11":{"loc":{"start":{"line":121,"column":3},"end":{"line":121,"column":13}},"type":"binary-expr","locations":[{"start":{"line":121,"column":3},"end":{"line":121,"column":13}},{"start":{"line":122,"column":3},"end":{"line":122,"column":34}},{"start":{"line":123,"column":3},"end":{"line":123,"column":18}},{"start":{"line":124,"column":3},"end":{"line":124,"column":48}}]},"12":{"loc":{"start":{"line":134,"column":3},"end":{"line":138,"column":null}},"type":"switch","locations":[{"start":{"line":134,"column":3},"end":{"line":138,"column":null}},{"start":{"line":139,"column":3},"end":{"line":139,"column":15}},{"start":{"line":140,"column":3},"end":{"line":140,"column":16}},{"start":{"line":141,"column":3},"end":{"line":144,"column":null}},{"start":{"line":145,"column":3},"end":{"line":147,"column":null}}]},"13":{"loc":{"start":{"line":172,"column":2},"end":{"line":175,"column":null}},"type":"if","locations":[{"start":{"line":172,"column":2},"end":{"line":175,"column":null}},{"start":{"line":172,"column":2},"end":{"line":175,"column":null}}]}},"s":{"0":1,"1":74,"2":33,"3":41,"4":0,"5":1,"6":1,"7":4,"8":1,"9":1,"10":22,"11":1,"12":42,"13":42,"14":1,"15":72,"16":66,"17":32,"18":34,"19":26,"20":8,"21":8,"22":0,"23":34,"24":34,"25":34,"26":0,"27":34,"28":32,"29":17,"30":17,"31":17,"32":15,"33":15,"34":0,"35":0,"36":17,"37":17,"38":17,"39":17,"40":9,"41":9,"42":17,"43":1},"f":{"0":74,"1":4,"2":22,"3":42,"4":72,"5":66,"6":34,"7":32,"8":0,"9":17},"b":{"0":[33,16,18,41,0],"1":[42,8,0,0,0,0,0],"2":[32,34],"3":[26,8],"4":[34,34,34],"5":[8,0],"6":[26,8],"7":[34,34],"8":[26,8],"9":[34,34],"10":[0,34],"11":[34,34,34,34],"12":[17,2,2,15,0],"13":[9,8]}}
,"/mnt/vss/_work/1/s/common/lib/common-utils/src/bufferNode.ts": {"path":"/mnt/vss/_work/1/s/common/lib/common-utils/src/bufferNode.ts","statementMap":{"0":{"start":{"line":21,"column":13},"end":{"line":21,"column":32}},"1":{"start":{"line":34,"column":1},"end":{"line":34,"column":92}},"2":{"start":{"line":32,"column":0},"end":{"line":32,"column":16}},"3":{"start":{"line":42,"column":13},"end":{"line":42,"column":44}},"4":{"start":{"line":46,"column":1},"end":{"line":48,"column":70}},"5":{"start":{"line":41,"column":0},"end":{"line":41,"column":16}},"6":{"start":{"line":58,"column":30},"end":{"line":59,"column":40}},"7":{"start":{"line":59,"column":1},"end":{"line":59,"column":40}},"8":{"start":{"line":58,"column":13},"end":{"line":58,"column":30}}},"fnMap":{"0":{"name":"Uint8ArrayToString","decl":{"start":{"line":32,"column":16},"end":{"line":32,"column":34}},"loc":{"start":{"line":32,"column":69},"end":{"line":35,"column":1}}},"1":{"name":"stringToBuffer","decl":{"start":{"line":41,"column":16},"end":{"line":41,"column":30}},"loc":{"start":{"line":41,"column":62},"end":{"line":49,"column":1}}},"2":{"name":"(anonymous_2)","decl":{"start":{"line":58,"column":30},"end":{"line":58,"column":31}},"loc":{"start":{"line":59,"column":1},"end":{"line":59,"column":40}}}},"branchMap":{"0":{"loc":{"start":{"line":34,"column":31},"end":{"line":34,"column":53}},"type":"cond-expr","locations":[{"start":{"line":34,"column":31},"end":{"line":34,"column":53}},{"start":{"line":34,"column":56},"end":{"line":34,"column":91}}]},"1":{"loc":{"start":{"line":47,"column":4},"end":{"line":47,"column":14}},"type":"cond-expr","locations":[{"start":{"line":47,"column":4},"end":{"line":47,"column":14}},{"start":{"line":48,"column":4},"end":{"line":48,"column":69}}]}},"s":{"0":1,"1":2,"2":1,"3":4,"4":4,"5":1,"6":1,"7":22,"8":1},"f":{"0":2,"1":4,"2":22},"b":{"0":[0,2],"1":[0,4]}}
,"/mnt/vss/_work/1/s/common/lib/common-utils/src/hashFileNode.ts": {"path":"/mnt/vss/_work/1/s/common/lib/common-utils/src/hashFileNode.ts","statementMap":{"0":{"start":{"line":7,"column":0},"end":{"line":7,"column":31}},"1":{"start":{"line":9,"column":0},"end":{"line":9,"column":35}},"2":{"start":{"line":30,"column":1},"end":{"line":39,"column":null}},"3":{"start":{"line":32,"column":3},"end":{"line":32,"column":23}},"4":{"start":{"line":33,"column":3},"end":{"line":33,"column":9}},"5":{"start":{"line":36,"column":3},"end":{"line":36,"column":25}},"6":{"start":{"line":37,"column":3},"end":{"line":37,"column":9}},"7":{"start":{"line":40,"column":1},"end":{"line":40,"column":59}},"8":{"start":{"line":23,"column":0},"end":{"line":23,"column":7}},"9":{"start":{"line":51,"column":14},"end":{"line":51,"column":29}},"10":{"start":{"line":52,"column":20},"end":{"line":52,"column":70}},"11":{"start":{"line":53,"column":16},"end":{"line":53,"column":26}},"12":{"start":{"line":54,"column":1},"end":{"line":54,"column":71}},"13":{"start":{"line":50,"column":0},"end":{"line":50,"column":7}}},"fnMap":{"0":{"name":"hashFile","decl":{"start":{"line":23,"column":22},"end":{"line":23,"column":30}},"loc":{"start":{"line":26,"column":39},"end":{"line":41,"column":1}}},"1":{"name":"gitHashFile","decl":{"start":{"line":50,"column":22},"end":{"line":50,"column":33}},"loc":{"start":{"line":50,"column":49},"end":{"line":55,"column":1}}}},"branchMap":{"0":{"loc":{"start":{"line":25,"column":34},"end":{"line":25,"column":41}},"type":"default-arg","locations":[{"start":{"line":25,"column":34},"end":{"line":25,"column":41}}]},"1":{"loc":{"start":{"line":26,"column":34},"end":{"line":26,"column":39}},"type":"default-arg","locations":[{"start":{"line":26,"column":34},"end":{"line":26,"column":39}}]},"2":{"loc":{"start":{"line":31,"column":2},"end":{"line":34,"column":null}},"type":"switch","locations":[{"start":{"line":31,"column":2},"end":{"line":34,"column":null}},{"start":{"line":35,"column":2},"end":{"line":38,"column":null}}]}},"s":{"0":1,"1":1,"2":3,"3":1,"4":1,"5":2,"6":2,"7":3,"8":1,"9":6,"10":6,"11":6,"12":6,"13":1},"f":{"0":3,"1":6},"b":{"0":[0],"1":[1],"2":[1,2]}}
}

@@ -28,3 +28,2 @@ "use strict";

const base64js = __importStar(require("base64-js"));
const assert_1 = require("./assert");
/**

@@ -120,6 +119,6 @@ * Converts a Uint8Array to a string of the provided encoding

else if (value !== null && typeof value === "object" && isArrayBuffer(value.buffer)) {
// Support currently for full array, no view ports! (though it can be added in future)
(0, assert_1.assert)(value.byteOffset === 0, 0x000 /* "nonzero isobuffer byte offset" */);
(0, assert_1.assert)(value.byteLength === value.buffer.byteLength, 0x001 /* "unexpected isobuffer byte length" */);
return IsoBuffer.fromArrayBuffer(value.buffer, encodingOrOffset, length);
// The version of the from function for the node buffer, which takes a buffer or typed array
// as first parameter, does not have any offset or length parameters. Those are just silently
// ignored and not taken into account
return IsoBuffer.fromArrayBuffer(value.buffer, value.byteOffset, value.byteLength);
}

@@ -126,0 +125,0 @@ else if (isArrayBuffer(value)) {

@@ -6,26 +6,26 @@ /*!

/**
* This package contains common utility functions and classes used by the Fluid Framework.
* This library contains common utility functions and classes used by the Fluid Framework.
*
* @packageDocumentation
*/
export * from "./assert";
export * from "./indexNode";
export * from "./base64Encoding";
export * from "./disposal";
export * from "./eventForwarder";
export * from "./heap";
export * from "./logger";
export * from "./promiseCache";
export * from "./promises";
export * from "./rangeTracker";
export * from "./rateLimiter";
export * from "./safeParser";
export * from "./timer";
export * from "./trace";
export * from "./typedEventEmitter";
export * from "./unreachable";
export * from "./lazy";
export * from "./performanceIsomorphic";
export * from "./delay";
export * from "./bufferShared";
export { assert } from "./assert";
export { fromBase64ToUtf8, fromUtf8ToBase64, toUtf8 } from "./base64Encoding";
export { Uint8ArrayToArrayBuffer } from "./bufferShared";
export { delay } from "./delay";
export { doIfNotDisposed } from "./disposal";
export { EventForwarder } from "./eventForwarder";
export { Heap, IComparer, IHeapNode, NumberComparer } from "./heap";
export { Buffer, bufferToString, gitHashFile, hashFile, IsoBuffer, performance, stringToBuffer, Uint8ArrayToString, } from "./indexNode";
export { Lazy } from "./lazy";
export { BaseTelemetryNullLogger, TelemetryNullLogger } from "./logger";
export { IsomorphicPerformance } from "./performanceIsomorphic";
export { PromiseCache, PromiseCacheExpiry, PromiseCacheOptions } from "./promiseCache";
export { Deferred, LazyPromise } from "./promises";
export { IRange, IRangeTrackerSnapshot, RangeTracker } from "./rangeTracker";
export { RateLimiter } from "./rateLimiter";
export { safelyParseJSON } from "./safeParser";
export { IPromiseTimer, IPromiseTimerResult, ITimer, PromiseTimer, setLongTimeout, Timer, } from "./timer";
export { ITraceEvent, Trace } from "./trace";
export { EventEmitterEventType, TypedEventEmitter, TypedEventTransform } from "./typedEventEmitter";
export { unreachableCase } from "./unreachable";
//# sourceMappingURL=index.d.ts.map

@@ -6,38 +6,61 @@ "use strict";

*/
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.unreachableCase = exports.TypedEventEmitter = exports.Trace = exports.Timer = exports.setLongTimeout = exports.PromiseTimer = exports.safelyParseJSON = exports.RateLimiter = exports.RangeTracker = exports.LazyPromise = exports.Deferred = exports.PromiseCache = exports.TelemetryNullLogger = exports.BaseTelemetryNullLogger = exports.Lazy = exports.Uint8ArrayToString = exports.stringToBuffer = exports.performance = exports.IsoBuffer = exports.hashFile = exports.gitHashFile = exports.bufferToString = exports.Buffer = exports.NumberComparer = exports.Heap = exports.EventForwarder = exports.doIfNotDisposed = exports.delay = exports.Uint8ArrayToArrayBuffer = exports.toUtf8 = exports.fromUtf8ToBase64 = exports.fromBase64ToUtf8 = exports.assert = void 0;
/**
* This package contains common utility functions and classes used by the Fluid Framework.
* This library contains common utility functions and classes used by the Fluid Framework.
*
* @packageDocumentation
*/
__exportStar(require("./assert"), exports);
__exportStar(require("./indexNode"), exports);
__exportStar(require("./base64Encoding"), exports);
__exportStar(require("./disposal"), exports);
__exportStar(require("./eventForwarder"), exports);
__exportStar(require("./heap"), exports);
__exportStar(require("./logger"), exports);
__exportStar(require("./promiseCache"), exports);
__exportStar(require("./promises"), exports);
__exportStar(require("./rangeTracker"), exports);
__exportStar(require("./rateLimiter"), exports);
__exportStar(require("./safeParser"), exports);
__exportStar(require("./timer"), exports);
__exportStar(require("./trace"), exports);
__exportStar(require("./typedEventEmitter"), exports);
__exportStar(require("./unreachable"), exports);
__exportStar(require("./lazy"), exports);
__exportStar(require("./performanceIsomorphic"), exports);
__exportStar(require("./delay"), exports);
__exportStar(require("./bufferShared"), exports);
var assert_1 = require("./assert");
Object.defineProperty(exports, "assert", { enumerable: true, get: function () { return assert_1.assert; } });
var base64Encoding_1 = require("./base64Encoding");
Object.defineProperty(exports, "fromBase64ToUtf8", { enumerable: true, get: function () { return base64Encoding_1.fromBase64ToUtf8; } });
Object.defineProperty(exports, "fromUtf8ToBase64", { enumerable: true, get: function () { return base64Encoding_1.fromUtf8ToBase64; } });
Object.defineProperty(exports, "toUtf8", { enumerable: true, get: function () { return base64Encoding_1.toUtf8; } });
var bufferShared_1 = require("./bufferShared");
Object.defineProperty(exports, "Uint8ArrayToArrayBuffer", { enumerable: true, get: function () { return bufferShared_1.Uint8ArrayToArrayBuffer; } });
var delay_1 = require("./delay");
Object.defineProperty(exports, "delay", { enumerable: true, get: function () { return delay_1.delay; } });
var disposal_1 = require("./disposal");
Object.defineProperty(exports, "doIfNotDisposed", { enumerable: true, get: function () { return disposal_1.doIfNotDisposed; } });
var eventForwarder_1 = require("./eventForwarder");
Object.defineProperty(exports, "EventForwarder", { enumerable: true, get: function () { return eventForwarder_1.EventForwarder; } });
var heap_1 = require("./heap");
Object.defineProperty(exports, "Heap", { enumerable: true, get: function () { return heap_1.Heap; } });
Object.defineProperty(exports, "NumberComparer", { enumerable: true, get: function () { return heap_1.NumberComparer; } });
var indexNode_1 = require("./indexNode");
Object.defineProperty(exports, "Buffer", { enumerable: true, get: function () { return indexNode_1.Buffer; } });
Object.defineProperty(exports, "bufferToString", { enumerable: true, get: function () { return indexNode_1.bufferToString; } });
Object.defineProperty(exports, "gitHashFile", { enumerable: true, get: function () { return indexNode_1.gitHashFile; } });
Object.defineProperty(exports, "hashFile", { enumerable: true, get: function () { return indexNode_1.hashFile; } });
Object.defineProperty(exports, "IsoBuffer", { enumerable: true, get: function () { return indexNode_1.IsoBuffer; } });
Object.defineProperty(exports, "performance", { enumerable: true, get: function () { return indexNode_1.performance; } });
Object.defineProperty(exports, "stringToBuffer", { enumerable: true, get: function () { return indexNode_1.stringToBuffer; } });
Object.defineProperty(exports, "Uint8ArrayToString", { enumerable: true, get: function () { return indexNode_1.Uint8ArrayToString; } });
var lazy_1 = require("./lazy");
Object.defineProperty(exports, "Lazy", { enumerable: true, get: function () { return lazy_1.Lazy; } });
var logger_1 = require("./logger");
Object.defineProperty(exports, "BaseTelemetryNullLogger", { enumerable: true, get: function () { return logger_1.BaseTelemetryNullLogger; } });
Object.defineProperty(exports, "TelemetryNullLogger", { enumerable: true, get: function () { return logger_1.TelemetryNullLogger; } });
var promiseCache_1 = require("./promiseCache");
Object.defineProperty(exports, "PromiseCache", { enumerable: true, get: function () { return promiseCache_1.PromiseCache; } });
var promises_1 = require("./promises");
Object.defineProperty(exports, "Deferred", { enumerable: true, get: function () { return promises_1.Deferred; } });
Object.defineProperty(exports, "LazyPromise", { enumerable: true, get: function () { return promises_1.LazyPromise; } });
var rangeTracker_1 = require("./rangeTracker");
Object.defineProperty(exports, "RangeTracker", { enumerable: true, get: function () { return rangeTracker_1.RangeTracker; } });
var rateLimiter_1 = require("./rateLimiter");
Object.defineProperty(exports, "RateLimiter", { enumerable: true, get: function () { return rateLimiter_1.RateLimiter; } });
var safeParser_1 = require("./safeParser");
Object.defineProperty(exports, "safelyParseJSON", { enumerable: true, get: function () { return safeParser_1.safelyParseJSON; } });
var timer_1 = require("./timer");
Object.defineProperty(exports, "PromiseTimer", { enumerable: true, get: function () { return timer_1.PromiseTimer; } });
Object.defineProperty(exports, "setLongTimeout", { enumerable: true, get: function () { return timer_1.setLongTimeout; } });
Object.defineProperty(exports, "Timer", { enumerable: true, get: function () { return timer_1.Timer; } });
var trace_1 = require("./trace");
Object.defineProperty(exports, "Trace", { enumerable: true, get: function () { return trace_1.Trace; } });
var typedEventEmitter_1 = require("./typedEventEmitter");
Object.defineProperty(exports, "TypedEventEmitter", { enumerable: true, get: function () { return typedEventEmitter_1.TypedEventEmitter; } });
var unreachable_1 = require("./unreachable");
Object.defineProperty(exports, "unreachableCase", { enumerable: true, get: function () { return unreachable_1.unreachableCase; } });
//# sourceMappingURL=index.js.map

@@ -5,5 +5,5 @@ /*!

*/
export * from "./bufferBrowser";
export * from "./hashFileBrowser";
export * from "./performanceBrowser";
export { bufferToString, isArrayBuffer, IsoBuffer, stringToBuffer, Uint8ArrayToString, } from "./bufferBrowser";
export { gitHashFile, hashFile } from "./hashFileBrowser";
export { performance } from "./performanceBrowser";
//# sourceMappingURL=indexBrowser.d.ts.map

@@ -6,16 +6,15 @@ "use strict";

*/
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
__exportStar(require("./bufferBrowser"), exports);
__exportStar(require("./hashFileBrowser"), exports);
__exportStar(require("./performanceBrowser"), exports);
exports.performance = exports.hashFile = exports.gitHashFile = exports.Uint8ArrayToString = exports.stringToBuffer = exports.IsoBuffer = exports.isArrayBuffer = exports.bufferToString = void 0;
var bufferBrowser_1 = require("./bufferBrowser");
Object.defineProperty(exports, "bufferToString", { enumerable: true, get: function () { return bufferBrowser_1.bufferToString; } });
Object.defineProperty(exports, "isArrayBuffer", { enumerable: true, get: function () { return bufferBrowser_1.isArrayBuffer; } });
Object.defineProperty(exports, "IsoBuffer", { enumerable: true, get: function () { return bufferBrowser_1.IsoBuffer; } });
Object.defineProperty(exports, "stringToBuffer", { enumerable: true, get: function () { return bufferBrowser_1.stringToBuffer; } });
Object.defineProperty(exports, "Uint8ArrayToString", { enumerable: true, get: function () { return bufferBrowser_1.Uint8ArrayToString; } });
var hashFileBrowser_1 = require("./hashFileBrowser");
Object.defineProperty(exports, "gitHashFile", { enumerable: true, get: function () { return hashFileBrowser_1.gitHashFile; } });
Object.defineProperty(exports, "hashFile", { enumerable: true, get: function () { return hashFileBrowser_1.hashFile; } });
var performanceBrowser_1 = require("./performanceBrowser");
Object.defineProperty(exports, "performance", { enumerable: true, get: function () { return performanceBrowser_1.performance; } });
//# sourceMappingURL=indexBrowser.js.map

@@ -5,5 +5,5 @@ /*!

*/
export * from "./bufferNode";
export * from "./hashFileNode";
export * from "./performanceNode";
export { Buffer, bufferToString, IsoBuffer, stringToBuffer, Uint8ArrayToString, } from "./bufferNode";
export { gitHashFile, hashFile } from "./hashFileNode";
export { performance } from "./performanceNode";
//# sourceMappingURL=indexNode.d.ts.map

@@ -6,16 +6,15 @@ "use strict";

*/
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
__exportStar(require("./bufferNode"), exports);
__exportStar(require("./hashFileNode"), exports);
__exportStar(require("./performanceNode"), exports);
exports.performance = exports.hashFile = exports.gitHashFile = exports.Uint8ArrayToString = exports.stringToBuffer = exports.IsoBuffer = exports.bufferToString = exports.Buffer = void 0;
var bufferNode_1 = require("./bufferNode");
Object.defineProperty(exports, "Buffer", { enumerable: true, get: function () { return bufferNode_1.Buffer; } });
Object.defineProperty(exports, "bufferToString", { enumerable: true, get: function () { return bufferNode_1.bufferToString; } });
Object.defineProperty(exports, "IsoBuffer", { enumerable: true, get: function () { return bufferNode_1.IsoBuffer; } });
Object.defineProperty(exports, "stringToBuffer", { enumerable: true, get: function () { return bufferNode_1.stringToBuffer; } });
Object.defineProperty(exports, "Uint8ArrayToString", { enumerable: true, get: function () { return bufferNode_1.Uint8ArrayToString; } });
var hashFileNode_1 = require("./hashFileNode");
Object.defineProperty(exports, "gitHashFile", { enumerable: true, get: function () { return hashFileNode_1.gitHashFile; } });
Object.defineProperty(exports, "hashFile", { enumerable: true, get: function () { return hashFileNode_1.hashFile; } });
var performanceNode_1 = require("./performanceNode");
Object.defineProperty(exports, "performance", { enumerable: true, get: function () { return performanceNode_1.performance; } });
//# sourceMappingURL=indexNode.js.map

@@ -9,2 +9,3 @@ /*!

* It can be used in places where logger instance is required, but events should be not send over.
* @deprecated BaseTelemetryNullLogger has been moved to the \@fluidframework/telemetry-utils package.
*/

@@ -22,2 +23,3 @@ export declare class BaseTelemetryNullLogger implements ITelemetryBaseLogger {

* It can be used in places where logger instance is required, but events should be not send over.
* @deprecated TelemetryNullLogger has been moved to the \@fluidframework/telemetry-utils package.
*/

@@ -24,0 +26,0 @@ export declare class TelemetryNullLogger implements ITelemetryLogger {

@@ -11,2 +11,3 @@ "use strict";

* It can be used in places where logger instance is required, but events should be not send over.
* @deprecated BaseTelemetryNullLogger has been moved to the \@fluidframework/telemetry-utils package.
*/

@@ -27,2 +28,3 @@ class BaseTelemetryNullLogger {

* It can be used in places where logger instance is required, but events should be not send over.
* @deprecated TelemetryNullLogger has been moved to the \@fluidframework/telemetry-utils package.
*/

@@ -29,0 +31,0 @@ class TelemetryNullLogger {

@@ -8,3 +8,3 @@ /*!

export declare const pkgName = "@fluidframework/common-utils";
export declare const pkgVersion = "1.0.0";
export declare const pkgVersion = "1.1.0";
//# sourceMappingURL=packageVersion.d.ts.map

@@ -11,3 +11,3 @@ "use strict";

exports.pkgName = "@fluidframework/common-utils";
exports.pkgVersion = "1.0.0";
exports.pkgVersion = "1.1.0";
//# sourceMappingURL=packageVersion.js.map

@@ -8,3 +8,3 @@ "use strict";

exports.performance = void 0;
exports.performance = window.performance;
exports.performance = globalThis.performance;
//# sourceMappingURL=performanceBrowser.js.map

@@ -8,4 +8,5 @@ "use strict";

exports.performance = void 0;
// eslint-disable-next-line import/no-nodejs-modules
const perf_hooks_1 = require("perf_hooks");
exports.performance = perf_hooks_1.performance;
//# sourceMappingURL=performanceNode.js.map

@@ -29,3 +29,3 @@ "use strict";

else {
timeoutId = setTimeout(() => timeoutFn(), timeoutMs);
timeoutId = setTimeout(() => timeoutFn(), Math.max(timeoutMs, 0));
}

@@ -32,0 +32,0 @@ setTimeoutIdFn === null || setTimeoutIdFn === void 0 ? void 0 : setTimeoutIdFn(timeoutId);

@@ -7,8 +7,8 @@ /*!

module.exports = {
launch: {
args: ["--no-sandbox", "--disable-setuid-sandbox"], // https://github.com/puppeteer/puppeteer/blob/master/docs/troubleshooting.md#setting-up-chrome-linux-sandbox
dumpio: true, // output browser console to cmd line
// slowMo: 500, // slows down process for easier viewing
// headless: false, // run in the browser
},
launch: {
args: ["--no-sandbox", "--disable-setuid-sandbox"], // https://github.com/puppeteer/puppeteer/blob/master/docs/troubleshooting.md#setting-up-chrome-linux-sandbox
dumpio: true, // output browser console to cmd line
// slowMo: 500, // slows down process for easier viewing
// headless: false, // run in the browser
},
};

@@ -7,5 +7,5 @@ /*!

module.exports = {
preset: "jest-puppeteer",
testMatch: ["**/dist/test/jest/?(*.)+(spec|test).js"],
testPathIgnorePatterns: ["/node_modules/"],
preset: "jest-puppeteer",
testMatch: ["**/dist/test/jest/?(*.)+(spec|test).js"],
testPathIgnorePatterns: ["/node_modules/"],
};

@@ -6,3 +6,2 @@ /*!

import * as base64js from "base64-js";
import { assert } from "./assert";
/**

@@ -94,6 +93,6 @@ * Converts a Uint8Array to a string of the provided encoding

else if (value !== null && typeof value === "object" && isArrayBuffer(value.buffer)) {
// Support currently for full array, no view ports! (though it can be added in future)
assert(value.byteOffset === 0, 0x000 /* "nonzero isobuffer byte offset" */);
assert(value.byteLength === value.buffer.byteLength, 0x001 /* "unexpected isobuffer byte length" */);
return IsoBuffer.fromArrayBuffer(value.buffer, encodingOrOffset, length);
// The version of the from function for the node buffer, which takes a buffer or typed array
// as first parameter, does not have any offset or length parameters. Those are just silently
// ignored and not taken into account
return IsoBuffer.fromArrayBuffer(value.buffer, value.byteOffset, value.byteLength);
}

@@ -100,0 +99,0 @@ else if (isArrayBuffer(value)) {

@@ -6,26 +6,26 @@ /*!

/**
* This package contains common utility functions and classes used by the Fluid Framework.
* This library contains common utility functions and classes used by the Fluid Framework.
*
* @packageDocumentation
*/
export * from "./assert";
export * from "./indexNode";
export * from "./base64Encoding";
export * from "./disposal";
export * from "./eventForwarder";
export * from "./heap";
export * from "./logger";
export * from "./promiseCache";
export * from "./promises";
export * from "./rangeTracker";
export * from "./rateLimiter";
export * from "./safeParser";
export * from "./timer";
export * from "./trace";
export * from "./typedEventEmitter";
export * from "./unreachable";
export * from "./lazy";
export * from "./performanceIsomorphic";
export * from "./delay";
export * from "./bufferShared";
export { assert } from "./assert";
export { fromBase64ToUtf8, fromUtf8ToBase64, toUtf8 } from "./base64Encoding";
export { Uint8ArrayToArrayBuffer } from "./bufferShared";
export { delay } from "./delay";
export { doIfNotDisposed } from "./disposal";
export { EventForwarder } from "./eventForwarder";
export { Heap, IComparer, IHeapNode, NumberComparer } from "./heap";
export { Buffer, bufferToString, gitHashFile, hashFile, IsoBuffer, performance, stringToBuffer, Uint8ArrayToString, } from "./indexNode";
export { Lazy } from "./lazy";
export { BaseTelemetryNullLogger, TelemetryNullLogger } from "./logger";
export { IsomorphicPerformance } from "./performanceIsomorphic";
export { PromiseCache, PromiseCacheExpiry, PromiseCacheOptions } from "./promiseCache";
export { Deferred, LazyPromise } from "./promises";
export { IRange, IRangeTrackerSnapshot, RangeTracker } from "./rangeTracker";
export { RateLimiter } from "./rateLimiter";
export { safelyParseJSON } from "./safeParser";
export { IPromiseTimer, IPromiseTimerResult, ITimer, PromiseTimer, setLongTimeout, Timer, } from "./timer";
export { ITraceEvent, Trace } from "./trace";
export { EventEmitterEventType, TypedEventEmitter, TypedEventTransform } from "./typedEventEmitter";
export { unreachableCase } from "./unreachable";
//# sourceMappingURL=index.d.ts.map

@@ -6,26 +6,25 @@ /*!

/**
* This package contains common utility functions and classes used by the Fluid Framework.
* This library contains common utility functions and classes used by the Fluid Framework.
*
* @packageDocumentation
*/
export * from "./assert";
export * from "./indexNode";
export * from "./base64Encoding";
export * from "./disposal";
export * from "./eventForwarder";
export * from "./heap";
export * from "./logger";
export * from "./promiseCache";
export * from "./promises";
export * from "./rangeTracker";
export * from "./rateLimiter";
export * from "./safeParser";
export * from "./timer";
export * from "./trace";
export * from "./typedEventEmitter";
export * from "./unreachable";
export * from "./lazy";
export * from "./performanceIsomorphic";
export * from "./delay";
export * from "./bufferShared";
export { assert } from "./assert";
export { fromBase64ToUtf8, fromUtf8ToBase64, toUtf8 } from "./base64Encoding";
export { Uint8ArrayToArrayBuffer } from "./bufferShared";
export { delay } from "./delay";
export { doIfNotDisposed } from "./disposal";
export { EventForwarder } from "./eventForwarder";
export { Heap, NumberComparer } from "./heap";
export { Buffer, bufferToString, gitHashFile, hashFile, IsoBuffer, performance, stringToBuffer, Uint8ArrayToString, } from "./indexNode";
export { Lazy } from "./lazy";
export { BaseTelemetryNullLogger, TelemetryNullLogger } from "./logger";
export { PromiseCache } from "./promiseCache";
export { Deferred, LazyPromise } from "./promises";
export { RangeTracker } from "./rangeTracker";
export { RateLimiter } from "./rateLimiter";
export { safelyParseJSON } from "./safeParser";
export { PromiseTimer, setLongTimeout, Timer, } from "./timer";
export { Trace } from "./trace";
export { TypedEventEmitter } from "./typedEventEmitter";
export { unreachableCase } from "./unreachable";
//# sourceMappingURL=index.js.map

@@ -5,5 +5,5 @@ /*!

*/
export * from "./bufferBrowser";
export * from "./hashFileBrowser";
export * from "./performanceBrowser";
export { bufferToString, isArrayBuffer, IsoBuffer, stringToBuffer, Uint8ArrayToString, } from "./bufferBrowser";
export { gitHashFile, hashFile } from "./hashFileBrowser";
export { performance } from "./performanceBrowser";
//# sourceMappingURL=indexBrowser.d.ts.map

@@ -5,5 +5,5 @@ /*!

*/
export * from "./bufferBrowser";
export * from "./hashFileBrowser";
export * from "./performanceBrowser";
export { bufferToString, isArrayBuffer, IsoBuffer, stringToBuffer, Uint8ArrayToString, } from "./bufferBrowser";
export { gitHashFile, hashFile } from "./hashFileBrowser";
export { performance } from "./performanceBrowser";
//# sourceMappingURL=indexBrowser.js.map

@@ -5,5 +5,5 @@ /*!

*/
export * from "./bufferNode";
export * from "./hashFileNode";
export * from "./performanceNode";
export { Buffer, bufferToString, IsoBuffer, stringToBuffer, Uint8ArrayToString, } from "./bufferNode";
export { gitHashFile, hashFile } from "./hashFileNode";
export { performance } from "./performanceNode";
//# sourceMappingURL=indexNode.d.ts.map

@@ -5,5 +5,5 @@ /*!

*/
export * from "./bufferNode";
export * from "./hashFileNode";
export * from "./performanceNode";
export { Buffer, bufferToString, IsoBuffer, stringToBuffer, Uint8ArrayToString, } from "./bufferNode";
export { gitHashFile, hashFile } from "./hashFileNode";
export { performance } from "./performanceNode";
//# sourceMappingURL=indexNode.js.map

@@ -9,2 +9,3 @@ /*!

* It can be used in places where logger instance is required, but events should be not send over.
* @deprecated BaseTelemetryNullLogger has been moved to the \@fluidframework/telemetry-utils package.
*/

@@ -22,2 +23,3 @@ export declare class BaseTelemetryNullLogger implements ITelemetryBaseLogger {

* It can be used in places where logger instance is required, but events should be not send over.
* @deprecated TelemetryNullLogger has been moved to the \@fluidframework/telemetry-utils package.
*/

@@ -24,0 +26,0 @@ export declare class TelemetryNullLogger implements ITelemetryLogger {

@@ -8,2 +8,3 @@ /*!

* It can be used in places where logger instance is required, but events should be not send over.
* @deprecated BaseTelemetryNullLogger has been moved to the \@fluidframework/telemetry-utils package.
*/

@@ -23,2 +24,3 @@ export class BaseTelemetryNullLogger {

* It can be used in places where logger instance is required, but events should be not send over.
* @deprecated TelemetryNullLogger has been moved to the \@fluidframework/telemetry-utils package.
*/

@@ -25,0 +27,0 @@ export class TelemetryNullLogger {

@@ -8,3 +8,3 @@ /*!

export declare const pkgName = "@fluidframework/common-utils";
export declare const pkgVersion = "1.0.0";
export declare const pkgVersion = "1.1.0";
//# sourceMappingURL=packageVersion.d.ts.map

@@ -8,3 +8,3 @@ /*!

export const pkgName = "@fluidframework/common-utils";
export const pkgVersion = "1.0.0";
export const pkgVersion = "1.1.0";
//# sourceMappingURL=packageVersion.js.map

@@ -5,3 +5,3 @@ /*!

*/
export const performance = window.performance;
export const performance = globalThis.performance;
//# sourceMappingURL=performanceBrowser.js.map

@@ -5,4 +5,5 @@ /*!

*/
// eslint-disable-next-line import/no-nodejs-modules
import { performance as nodePerformance } from "perf_hooks";
export const performance = nodePerformance;
//# sourceMappingURL=performanceNode.js.map

@@ -26,3 +26,3 @@ /*!

else {
timeoutId = setTimeout(() => timeoutFn(), timeoutMs);
timeoutId = setTimeout(() => timeoutFn(), Math.max(timeoutMs, 0));
}

@@ -29,0 +29,0 @@ setTimeoutIdFn === null || setTimeoutIdFn === void 0 ? void 0 : setTimeoutIdFn(timeoutId);

{
"name": "@fluidframework/common-utils",
"version": "1.0.0",
"description": "Collection of utility functions for Fluid",
"homepage": "https://fluidframework.com",
"repository": {
"type": "git",
"url": "https://github.com/microsoft/FluidFramework.git",
"directory": "common/lib/common-utils"
},
"license": "MIT",
"author": "Microsoft and contributors",
"sideEffects": false,
"main": "dist/index.js",
"module": "lib/index.js",
"browser": {
"./dist/indexNode.js": "./dist/indexBrowser.js",
"./lib/indexNode.js": "./lib/indexBrowser.js"
},
"types": "dist/index.d.ts",
"scripts": {
"bench": "ts-node bench/src/index.ts",
"build": "npm run build:genver && concurrently npm:build:compile npm:lint && npm run build:docs",
"build:commonjs": "npm run tsc && npm run typetests:gen && npm run build:test",
"build:compile": "concurrently npm:build:commonjs npm:build:esnext",
"build:docs": "api-extractor run --local --typescript-compiler-folder ./node_modules/typescript && copyfiles -u 1 ./_api-extractor-temp/doc-models/* ../../../_api-extractor-temp/",
"build:esnext": "tsc --project ./tsconfig.esnext.json",
"build:full": "npm run build",
"build:full:compile": "npm run build:compile",
"build:genver": "gen-version",
"build:test": "concurrently npm:build:test:mocha npm:build:test:jest npm:build:test:types",
"build:test:jest": "tsc --project ./src/test/jest/tsconfig.json",
"build:test:mocha": "tsc --project ./src/test/mocha/tsconfig.json",
"build:test:types": "tsc --project ./src/test/types/tsconfig.json",
"bump-version": "npm version minor --no-push --no-git-tag-version && npm run build:gen:bump",
"ci:build": "npm run build:genver && npm run build:compile",
"ci:build:docs": "api-extractor run --typescript-compiler-folder ./node_modules/typescript && copyfiles -u 1 ./_api-extractor-temp/doc-models/* ../../../_api-extractor-temp/",
"ci:test": "npm run test:report",
"ci:test:coverage": "npm run test:coverage",
"clean": "rimraf _api-extractor-temp dist lib *.tsbuildinfo *.build.log",
"eslint": "eslint --format stylish src",
"eslint:fix": "eslint --format stylish src --fix --fix-type problem,suggestion,layout",
"format": "npm run prettier:fix",
"lint": "npm run prettier && npm run eslint",
"lint:fix": "npm run prettier:fix && npm run eslint:fix",
"prettier": "prettier --check . --ignore-path ../../../.prettierignore",
"prettier:fix": "prettier --write . --ignore-path ../../../.prettierignore",
"test": "npm run test:mocha && npm run test:jest",
"test:coverage": "npm run test:report",
"test:jest": "jest",
"test:jest:report": "npm run test:jest -- --ci --coverage --reporters=default --reporters=jest-junit",
"test:mocha": "mocha --unhandled-rejections=strict --recursive dist/test/mocha/**/*.spec.js --exit --project test/tsconfig.json",
"test:mocha:report": "npm run test:mocha -- -- --reporter xunit --reporter-option output=nyc/mocha-junit-report.xml",
"test:report": "nyc npm run test:mocha:report && npm run test:jest:report",
"tsc": "tsc",
"tsfmt": "tsfmt --verify",
"tsfmt:fix": "tsfmt --replace",
"typetests:gen": "fluid-type-validator -d .",
"typetests:prepare": "fluid-type-validator -d . -p"
},
"nyc": {
"all": true,
"cache-dir": "nyc/.cache",
"exclude": [
"src/test/**/*.ts",
"dist/test/**/*.js"
],
"exclude-after-remap": false,
"include": [
"src/**/*.ts",
"dist/**/*.js"
],
"report-dir": "nyc/report",
"reporter": [
"cobertura",
"html",
"text"
],
"temp-directory": "nyc/.nyc_output"
},
"dependencies": {
"@fluidframework/common-definitions": "^0.20.1",
"@types/events": "^3.0.0",
"base64-js": "^1.5.1",
"buffer": "^6.0.3",
"events": "^3.1.0",
"lodash": "^4.17.21",
"sha.js": "^2.4.11"
},
"devDependencies": {
"@fluidframework/build-common": "^0.24.0",
"@fluidframework/build-tools": "^0.3.1000",
"@fluidframework/common-utils-previous": "npm:@fluidframework/common-utils@^0.32.0",
"@fluidframework/eslint-config-fluid": "^0.28.2000",
"@microsoft/api-extractor": "^7.22.2",
"@rushstack/eslint-config": "^2.5.1",
"@types/base64-js": "^1.3.0",
"@types/benchmark": "^2.1.0",
"@types/jest": "22.2.3",
"@types/jest-environment-puppeteer": "2.2.0",
"@types/mocha": "^9.1.1",
"@types/puppeteer": "1.3.0",
"@types/sinon": "^7.0.13",
"benchmark": "^2.1.4",
"concurrently": "^6.2.0",
"copyfiles": "^2.1.0",
"eslint": "~8.6.0",
"eslint-config-prettier": "~8.5.0",
"jest": "^26.6.3",
"jest-junit": "^10.0.0",
"jest-puppeteer": "^4.4.0",
"mocha": "^10.0.0",
"nyc": "^15.0.0",
"prettier": "~2.6.2",
"puppeteer": "^2.1.0",
"rewire": "^5.0.0",
"rimraf": "^2.6.2",
"sinon": "^7.4.2",
"ts-jest": "^26.4.4",
"ts-node": "^7.0.1",
"typescript": "~4.5.5",
"typescript-formatter": "7.1.0"
},
"jest-junit": {
"outputDirectory": "nyc",
"outputName": "jest-junit-report.xml"
},
"typeValidation": {
"version": "0.33.1000",
"broken": {
"RemovedFunctionDeclaration_extractLogSafeErrorProperties": {
"forwardCompat": false,
"backCompat": false
},
"RemovedClassDeclaration_BatchManager": {
"forwardCompat": false,
"backCompat": false
}
}
}
"name": "@fluidframework/common-utils",
"version": "1.1.0",
"description": "Collection of utility functions for Fluid",
"homepage": "https://fluidframework.com",
"repository": {
"type": "git",
"url": "https://github.com/microsoft/FluidFramework.git",
"directory": "common/lib/common-utils"
},
"license": "MIT",
"author": "Microsoft and contributors",
"sideEffects": false,
"main": "dist/index.js",
"module": "lib/index.js",
"browser": {
"./dist/indexNode.js": "./dist/indexBrowser.js",
"./lib/indexNode.js": "./lib/indexBrowser.js"
},
"types": "dist/index.d.ts",
"scripts": {
"bench": "ts-node bench/src/index.ts",
"build": "npm run build:genver && concurrently npm:build:compile npm:lint && npm run build:docs",
"build:commonjs": "npm run tsc && npm run typetests:gen && npm run build:test",
"build:compile": "concurrently npm:build:commonjs npm:build:esnext",
"build:docs": "api-extractor run --local --typescript-compiler-folder ./node_modules/typescript && copyfiles -u 1 ./_api-extractor-temp/doc-models/* ../../../_api-extractor-temp/",
"build:esnext": "tsc --project ./tsconfig.esnext.json",
"build:full": "npm run build",
"build:full:compile": "npm run build:compile",
"build:genver": "gen-version",
"build:test": "concurrently npm:build:test:mocha npm:build:test:jest npm:build:test:types",
"build:test:jest": "tsc --project ./src/test/jest/tsconfig.json",
"build:test:mocha": "tsc --project ./src/test/mocha/tsconfig.json",
"build:test:types": "tsc --project ./src/test/types/tsconfig.json",
"bump-version": "npm version minor --no-push --no-git-tag-version && npm run build:gen:bump",
"ci:build": "npm run build:genver && npm run build:compile",
"ci:build:docs": "api-extractor run --typescript-compiler-folder ./node_modules/typescript && copyfiles -u 1 ./_api-extractor-temp/doc-models/* ../../../_api-extractor-temp/",
"ci:test": "npm run test:report",
"ci:test:coverage": "npm run test:coverage",
"clean": "rimraf _api-extractor-temp dist lib *.tsbuildinfo *.build.log",
"eslint": "eslint --format stylish src",
"eslint:fix": "eslint --format stylish src --fix --fix-type problem,suggestion,layout",
"format": "npm run prettier:fix",
"lint": "npm run prettier && npm run eslint",
"lint:fix": "npm run prettier:fix && npm run eslint:fix",
"prettier": "prettier --check . --ignore-path ../../../.prettierignore",
"prettier:fix": "prettier --write . --ignore-path ../../../.prettierignore",
"test": "npm run test:mocha && npm run test:jest",
"test:coverage": "npm run test:report",
"test:jest": "jest",
"test:jest:report": "npm run test:jest -- --ci --coverage --reporters=default --reporters=jest-junit",
"test:mocha": "mocha --unhandled-rejections=strict --recursive dist/test/mocha/**/*.spec.js --exit --project test/tsconfig.json",
"test:mocha:report": "npm run test:mocha -- -- --reporter xunit --reporter-option output=nyc/mocha-junit-report.xml",
"test:report": "nyc npm run test:mocha:report && npm run test:jest:report",
"tsc": "tsc",
"typetests:gen": "flub generate typetests --generate --dir .",
"typetests:prepare": "flub generate typetests --prepare --dir . --pin"
},
"nyc": {
"all": true,
"cache-dir": "nyc/.cache",
"exclude": [
"src/test/**/*.ts",
"dist/test/**/*.js"
],
"exclude-after-remap": false,
"include": [
"src/**/*.ts",
"dist/**/*.js"
],
"report-dir": "nyc/report",
"reporter": [
"cobertura",
"html",
"text"
],
"temp-directory": "nyc/.nyc_output"
},
"dependencies": {
"@fluidframework/common-definitions": "^0.20.1",
"@types/events": "^3.0.0",
"base64-js": "^1.5.1",
"buffer": "^6.0.3",
"events": "^3.1.0",
"lodash": "^4.17.21",
"sha.js": "^2.4.11"
},
"devDependencies": {
"@fluid-tools/build-cli": "^0.8.0",
"@fluidframework/build-common": "^1.1.0",
"@fluidframework/build-tools": "^0.8.0",
"@fluidframework/common-utils-previous": "npm:@fluidframework/common-utils@1.0.0",
"@fluidframework/eslint-config-fluid": "^2.0.0",
"@microsoft/api-extractor": "^7.22.2",
"@rushstack/eslint-config": "^2.5.1",
"@types/base64-js": "^1.3.0",
"@types/benchmark": "^2.1.0",
"@types/jest": "22.2.3",
"@types/jest-environment-puppeteer": "2.2.0",
"@types/mocha": "^9.1.1",
"@types/puppeteer": "1.3.0",
"@types/sinon": "^7.0.13",
"benchmark": "^2.1.4",
"concurrently": "^6.2.0",
"copyfiles": "^2.4.1",
"eslint": "~8.6.0",
"eslint-config-prettier": "~8.5.0",
"jest": "^26.6.3",
"jest-junit": "^10.0.0",
"jest-puppeteer": "^4.4.0",
"mocha": "^10.0.0",
"nyc": "^15.0.0",
"prettier": "~2.6.2",
"puppeteer": "^2.1.0",
"rewire": "^5.0.0",
"rimraf": "^2.6.2",
"sinon": "^7.4.2",
"ts-jest": "^26.4.4",
"ts-node": "^7.0.1",
"typescript": "~4.5.5"
},
"fluidBuild": {
"branchReleaseTypes": {
"main": "minor",
"release/**": "patch"
}
},
"jest-junit": {
"outputDirectory": "nyc",
"outputName": "jest-junit-report.xml"
},
"typeValidation": {
"version": "1.1.0",
"baselineRange": "~1.0.0",
"baselineVersion": "1.0.0",
"broken": {}
}
}

@@ -16,7 +16,7 @@ /*!

export function assert(condition: boolean, message: string | number): asserts condition {
if (!condition) {
throw new Error(
typeof message === "number" ? `0x${message.toString(16).padStart(3, "0")}` : message,
);
}
if (!condition) {
throw new Error(
typeof message === "number" ? `0x${message.toString(16).padStart(3, "0")}` : message,
);
}
}

@@ -13,3 +13,3 @@ /*!

export const fromBase64ToUtf8 = (input: string): string =>
IsoBuffer.from(input, "base64").toString("utf-8");
IsoBuffer.from(input, "base64").toString("utf-8");

@@ -21,3 +21,3 @@ /**

export const fromUtf8ToBase64 = (input: string): string =>
IsoBuffer.from(input, "utf8").toString("base64");
IsoBuffer.from(input, "utf8").toString("base64");

@@ -31,9 +31,9 @@ /**

export const toUtf8 = (input: string, encoding: string): string => {
switch (encoding) {
case "utf8":
case "utf-8":
return input;
default:
return IsoBuffer.from(input, encoding).toString();
}
switch (encoding) {
case "utf8":
case "utf-8":
return input;
default:
return IsoBuffer.from(input, encoding).toString();
}
};

@@ -7,3 +7,2 @@ /*!

import * as base64js from "base64-js";
import { assert } from "./assert";

@@ -20,15 +19,15 @@ /**

export function Uint8ArrayToString(arr: Uint8Array, encoding?: string): string {
switch (encoding) {
case "base64": {
return base64js.fromByteArray(arr);
}
case "utf8":
case "utf-8":
case undefined: {
return new TextDecoder().decode(arr);
}
default: {
throw new Error("invalid/unsupported encoding");
}
}
switch (encoding) {
case "base64": {
return base64js.fromByteArray(arr);
}
case "utf8":
case "utf-8":
case undefined: {
return new TextDecoder().decode(arr);
}
default: {
throw new Error("invalid/unsupported encoding");
}
}
}

@@ -43,3 +42,3 @@

export const stringToBuffer = (input: string, encoding: string): ArrayBufferLike =>
IsoBuffer.from(input, encoding).buffer;
IsoBuffer.from(input, encoding).buffer;

@@ -54,3 +53,3 @@ /**

export const bufferToString = (blob: ArrayBufferLike, encoding: string): string =>
IsoBuffer.from(blob).toString(encoding);
IsoBuffer.from(blob).toString(encoding);

@@ -70,12 +69,12 @@ /**

export function isArrayBuffer(obj: any): obj is ArrayBuffer {
const maybe = obj as (Partial<ArrayBuffer> & Partial<Uint8Array>) | undefined;
return (
obj instanceof ArrayBuffer ||
(typeof maybe === "object" &&
maybe !== null &&
typeof maybe.byteLength === "number" &&
typeof maybe.slice === "function" &&
maybe.byteOffset === undefined &&
maybe.buffer === undefined)
);
const maybe = obj as (Partial<ArrayBuffer> & Partial<Uint8Array>) | undefined;
return (
obj instanceof ArrayBuffer ||
(typeof maybe === "object" &&
maybe !== null &&
typeof maybe.byteLength === "number" &&
typeof maybe.slice === "function" &&
maybe.byteOffset === undefined &&
maybe.buffer === undefined)
);
}

@@ -87,106 +86,99 @@

export class IsoBuffer extends Uint8Array {
/**
* Convert the buffer to a string.
* Only supports encoding the whole string (unlike the Node Buffer equivalent)
* and only utf8 and base64 encodings.
*
* @param encoding - The encoding to use.
*/
public toString(encoding?: string): string {
return Uint8ArrayToString(this, encoding);
}
/**
* Convert the buffer to a string.
* Only supports encoding the whole string (unlike the Node Buffer equivalent)
* and only utf8 and base64 encodings.
*
* @param encoding - The encoding to use.
*/
public toString(encoding?: string): string {
return Uint8ArrayToString(this, encoding);
}
/**
* @param value - (string | ArrayBuffer)
* @param encodingOrOffset - (string | number)
* @param length - (number)
*/
static from(value, encodingOrOffset?, length?): IsoBuffer {
if (typeof value === "string") {
return IsoBuffer.fromString(value, encodingOrOffset as string | undefined);
// Capture any typed arrays, including Uint8Array (and thus - IsoBuffer!)
} else if (value !== null && typeof value === "object" && isArrayBuffer(value.buffer)) {
// Support currently for full array, no view ports! (though it can be added in future)
assert(value.byteOffset === 0, 0x000 /* "nonzero isobuffer byte offset" */);
assert(
value.byteLength === value.buffer.byteLength,
0x001 /* "unexpected isobuffer byte length" */,
);
return IsoBuffer.fromArrayBuffer(
value.buffer,
encodingOrOffset as number | undefined,
length,
);
} else if (isArrayBuffer(value)) {
return IsoBuffer.fromArrayBuffer(value, encodingOrOffset as number | undefined, length);
} else {
throw new TypeError();
}
}
/**
* @param value - (string | ArrayBuffer)
* @param encodingOrOffset - (string | number)
* @param length - (number)
*/
static from(value, encodingOrOffset?, length?): IsoBuffer {
if (typeof value === "string") {
return IsoBuffer.fromString(value, encodingOrOffset as string | undefined);
// Capture any typed arrays, including Uint8Array (and thus - IsoBuffer!)
} else if (value !== null && typeof value === "object" && isArrayBuffer(value.buffer)) {
// The version of the from function for the node buffer, which takes a buffer or typed array
// as first parameter, does not have any offset or length parameters. Those are just silently
// ignored and not taken into account
return IsoBuffer.fromArrayBuffer(value.buffer, value.byteOffset, value.byteLength);
} else if (isArrayBuffer(value)) {
return IsoBuffer.fromArrayBuffer(value, encodingOrOffset as number | undefined, length);
} else {
throw new TypeError();
}
}
static fromArrayBuffer(
arrayBuffer: ArrayBuffer,
byteOffset?: number,
byteLength?: number,
): IsoBuffer {
const offset = byteOffset ?? 0;
const validLength = byteLength ?? arrayBuffer.byteLength - offset;
if (
offset < 0 ||
offset > arrayBuffer.byteLength ||
validLength < 0 ||
validLength + offset > arrayBuffer.byteLength
) {
throw new RangeError();
}
static fromArrayBuffer(
arrayBuffer: ArrayBuffer,
byteOffset?: number,
byteLength?: number,
): IsoBuffer {
const offset = byteOffset ?? 0;
const validLength = byteLength ?? arrayBuffer.byteLength - offset;
if (
offset < 0 ||
offset > arrayBuffer.byteLength ||
validLength < 0 ||
validLength + offset > arrayBuffer.byteLength
) {
throw new RangeError();
}
return new IsoBuffer(arrayBuffer, offset, validLength);
}
return new IsoBuffer(arrayBuffer, offset, validLength);
}
static fromString(str: string, encoding?: string): IsoBuffer {
switch (encoding) {
case "base64": {
const sanitizedString = this.sanitizeBase64(str);
const encoded = base64js.toByteArray(sanitizedString);
return new IsoBuffer(encoded.buffer);
}
case "utf8":
case "utf-8":
case undefined: {
const encoded = new TextEncoder().encode(str);
return new IsoBuffer(encoded.buffer);
}
default: {
throw new Error("invalid/unsupported encoding");
}
}
}
static fromString(str: string, encoding?: string): IsoBuffer {
switch (encoding) {
case "base64": {
const sanitizedString = this.sanitizeBase64(str);
const encoded = base64js.toByteArray(sanitizedString);
return new IsoBuffer(encoded.buffer);
}
case "utf8":
case "utf-8":
case undefined: {
const encoded = new TextEncoder().encode(str);
return new IsoBuffer(encoded.buffer);
}
default: {
throw new Error("invalid/unsupported encoding");
}
}
}
static isBuffer(obj: any): boolean {
throw new Error("unimplemented");
}
static isBuffer(obj: any): boolean {
throw new Error("unimplemented");
}
/**
* Sanitize a base64 string to provide to base64-js library.
* {@link https://www.npmjs.com/package/base64-js} is not as tolerant of the same malformed base64 as Node'
* Buffer is.
*/
private static sanitizeBase64(str: string): string {
let sanitizedStr = str;
// Remove everything after padding - Node buffer ignores everything
// after any padding whereas base64-js does not
sanitizedStr = sanitizedStr.split("=")[0];
/**
* Sanitize a base64 string to provide to base64-js library.
* {@link https://www.npmjs.com/package/base64-js} is not as tolerant of the same malformed base64 as Node'
* Buffer is.
*/
private static sanitizeBase64(str: string): string {
let sanitizedStr = str;
// Remove everything after padding - Node buffer ignores everything
// after any padding whereas base64-js does not
sanitizedStr = sanitizedStr.split("=")[0];
// Remove invalid characters - Node buffer strips invalid characters
// whereas base64-js replaces them with "A"
sanitizedStr = sanitizedStr.replace(/[^\w+-/]/g, "");
// Remove invalid characters - Node buffer strips invalid characters
// whereas base64-js replaces them with "A"
sanitizedStr = sanitizedStr.replace(/[^\w+-/]/g, "");
// Check for missing padding - Node buffer tolerates missing padding
// whereas base64-js does not
if (sanitizedStr.length % 4 !== 0) {
const paddingArray = ["", "===", "==", "="];
sanitizedStr += paddingArray[sanitizedStr.length % 4];
}
return sanitizedStr;
}
// Check for missing padding - Node buffer tolerates missing padding
// whereas base64-js does not
if (sanitizedStr.length % 4 !== 0) {
const paddingArray = ["", "===", "==", "="];
sanitizedStr += paddingArray[sanitizedStr.length % 4];
}
return sanitizedStr;
}
}

@@ -12,10 +12,10 @@ /*!

export declare class Buffer extends Uint8Array {
toString(encoding?: string): string;
/**
* @param value - (string | ArrayBuffer).
* @param encodingOrOffset - (string | number).
* @param length - (number).
*/
static from(value, encodingOrOffset?, length?): IsoBuffer;
static isBuffer(obj: any): obj is Buffer;
toString(encoding?: string): string;
/**
* @param value - (string | ArrayBuffer).
* @param encodingOrOffset - (string | number).
* @param length - (number).
*/
static from(value, encodingOrOffset?, length?): IsoBuffer;
static isBuffer(obj: any): obj is Buffer;
}

@@ -34,4 +34,4 @@ export const IsoBuffer = Buffer;

export function Uint8ArrayToString(arr: Uint8Array, encoding?: string): string {
// Make this check because Buffer.from(arr) will always do a buffer copy
return Buffer.isBuffer(arr) ? arr.toString(encoding) : Buffer.from(arr).toString(encoding);
// Make this check because Buffer.from(arr) will always do a buffer copy
return Buffer.isBuffer(arr) ? arr.toString(encoding) : Buffer.from(arr).toString(encoding);
}

@@ -44,9 +44,9 @@

export function stringToBuffer(input: string, encoding: string): ArrayBufferLike {
const iso = IsoBuffer.from(input, encoding);
// In a Node environment, IsoBuffer may be a Node.js Buffer. Node.js will
// pool multiple small Buffer instances into a single ArrayBuffer, in which
// case we need to slice the appropriate span of bytes.
return iso.byteLength === iso.buffer.byteLength
? iso.buffer
: iso.buffer.slice(iso.byteOffset, iso.byteOffset + iso.byteLength);
const iso = IsoBuffer.from(input, encoding);
// In a Node environment, IsoBuffer may be a Node.js Buffer. Node.js will
// pool multiple small Buffer instances into a single ArrayBuffer, in which
// case we need to slice the appropriate span of bytes.
return iso.byteLength === iso.buffer.byteLength
? iso.buffer
: iso.buffer.slice(iso.byteOffset, iso.byteOffset + iso.byteLength);
}

@@ -62,2 +62,2 @@

export const bufferToString = (blob: ArrayBufferLike, encoding: string): string =>
IsoBuffer.from(blob).toString(encoding);
IsoBuffer.from(blob).toString(encoding);

@@ -11,6 +11,6 @@ /*!

export function Uint8ArrayToArrayBuffer(array: Uint8Array): ArrayBuffer {
if (array.byteOffset === 0 && array.byteLength === array.buffer.byteLength) {
return array.buffer;
}
return array.buffer.slice(array.byteOffset, array.byteOffset + array.byteLength);
if (array.byteOffset === 0 && array.byteLength === array.buffer.byteLength) {
return array.buffer;
}
return array.buffer.slice(array.byteOffset, array.byteOffset + array.byteLength);
}

@@ -11,2 +11,2 @@ /*!

export const delay = async (timeMs: number): Promise<void> =>
new Promise((resolve) => setTimeout(() => resolve(), timeMs));
new Promise((resolve) => setTimeout(() => resolve(), timeMs));

@@ -15,12 +15,12 @@ /*!

export function doIfNotDisposed<T>(
disposable: IDisposable,
f: (...args: any[]) => T,
disposable: IDisposable,
f: (...args: any[]) => T,
): (...args: any[]) => T {
return (...args: any[]): T => {
if (disposable.disposed) {
throw new Error("Already disposed");
} else {
return f(...args);
}
};
return (...args: any[]): T => {
if (disposable.disposed) {
throw new Error("Already disposed");
} else {
return f(...args);
}
};
}

@@ -16,104 +16,104 @@ /*!

export class EventForwarder<TEvent = IEvent>
extends TypedEventEmitter<TEvent>
implements IDisposable
extends TypedEventEmitter<TEvent>
implements IDisposable
{
protected static isEmitterEvent(event: string): boolean {
return (
event === EventForwarder.newListenerEvent ||
event === EventForwarder.removeListenerEvent
);
}
protected static isEmitterEvent(event: string): boolean {
return (
event === EventForwarder.newListenerEvent ||
event === EventForwarder.removeListenerEvent
);
}
private static readonly newListenerEvent = "newListener";
private static readonly removeListenerEvent = "removeListener";
private static readonly newListenerEvent = "newListener";
private static readonly removeListenerEvent = "removeListener";
/**
* {@inheritDoc @fluidframework/common-definitions#IDisposable.disposed}
*/
public get disposed(): boolean {
return this.isDisposed;
}
private isDisposed: boolean = false;
/**
* {@inheritDoc @fluidframework/common-definitions#IDisposable.disposed}
*/
public get disposed(): boolean {
return this.isDisposed;
}
private isDisposed: boolean = false;
private readonly forwardingEvents = new Map<
string,
Map<EventEmitter | IEventProvider<TEvent & IEvent>, () => void>
>();
private readonly forwardingEvents = new Map<
string,
Map<EventEmitter | IEventProvider<TEvent & IEvent>, () => void>
>();
constructor(source?: EventEmitter | IEventProvider<TEvent & IEvent>) {
super();
if (source !== undefined) {
// NewListener event is raised whenever someone starts listening to this events, so
// we keep track of events being listened to, and start forwarding from the source
// event emitter per event listened to on this
const removeListenerHandler = (event: string): void =>
this.unforwardEvent(source, event);
const newListenerHandler = (event: string): void => this.forwardEvent(source, event);
this.on(EventForwarder.removeListenerEvent, removeListenerHandler);
this.on(EventForwarder.newListenerEvent, newListenerHandler);
}
}
constructor(source?: EventEmitter | IEventProvider<TEvent & IEvent>) {
super();
if (source !== undefined) {
// NewListener event is raised whenever someone starts listening to this events, so
// we keep track of events being listened to, and start forwarding from the source
// event emitter per event listened to on this
const removeListenerHandler = (event: string): void =>
this.unforwardEvent(source, event);
const newListenerHandler = (event: string): void => this.forwardEvent(source, event);
this.on(EventForwarder.removeListenerEvent, removeListenerHandler);
this.on(EventForwarder.newListenerEvent, newListenerHandler);
}
}
/**
* {@inheritDoc @fluidframework/common-definitions#IDisposable.dispose}
*/
public dispose(): void {
this.isDisposed = true;
for (const listenerRemovers of this.forwardingEvents.values()) {
for (const listenerRemover of listenerRemovers.values()) {
try {
listenerRemover();
} catch {
// Should be fine because of removeAllListeners below
}
}
}
this.removeAllListeners();
this.forwardingEvents.clear();
}
/**
* {@inheritDoc @fluidframework/common-definitions#IDisposable.dispose}
*/
public dispose(): void {
this.isDisposed = true;
for (const listenerRemovers of this.forwardingEvents.values()) {
for (const listenerRemover of listenerRemovers.values()) {
try {
listenerRemover();
} catch {
// Should be fine because of removeAllListeners below
}
}
}
this.removeAllListeners();
this.forwardingEvents.clear();
}
protected forwardEvent(
source: EventEmitter | IEventProvider<TEvent & IEvent>,
...events: string[]
): void {
for (const event of events) {
if (
source !== undefined &&
event !== undefined &&
!EventForwarder.isEmitterEvent(event)
) {
let sources = this.forwardingEvents.get(event);
if (sources === undefined) {
sources = new Map();
this.forwardingEvents.set(event, sources);
}
if (!sources.has(source)) {
const listener = (...args: any[]): boolean => this.emit(event, ...args);
sources.set(source, () => source.off(event, listener));
source.on(event, listener);
}
}
}
}
protected forwardEvent(
source: EventEmitter | IEventProvider<TEvent & IEvent>,
...events: string[]
): void {
for (const event of events) {
if (
source !== undefined &&
event !== undefined &&
!EventForwarder.isEmitterEvent(event)
) {
let sources = this.forwardingEvents.get(event);
if (sources === undefined) {
sources = new Map();
this.forwardingEvents.set(event, sources);
}
if (!sources.has(source)) {
const listener = (...args: any[]): boolean => this.emit(event, ...args);
sources.set(source, () => source.off(event, listener));
source.on(event, listener);
}
}
}
}
protected unforwardEvent(
source: EventEmitter | IEventProvider<TEvent & IEvent>,
...events: string[]
): void {
for (const event of events) {
if (event !== undefined && !EventForwarder.isEmitterEvent(event)) {
const sources = this.forwardingEvents.get(event);
if (sources?.has(source) === true && this.listenerCount(event) === 0) {
const listenerRemover = sources.get(source);
if (listenerRemover !== undefined) {
listenerRemover();
}
sources.delete(source);
if (sources.size === 0) {
this.forwardingEvents.delete(event);
}
}
}
}
}
protected unforwardEvent(
source: EventEmitter | IEventProvider<TEvent & IEvent>,
...events: string[]
): void {
for (const event of events) {
if (event !== undefined && !EventForwarder.isEmitterEvent(event)) {
const sources = this.forwardingEvents.get(event);
if (sources?.has(source) === true && this.listenerCount(event) === 0) {
const listenerRemover = sources.get(source);
if (listenerRemover !== undefined) {
listenerRemover();
}
sources.delete(source);
if (sources.size === 0) {
this.forwardingEvents.delete(event);
}
}
}
}
}
}

@@ -10,21 +10,21 @@ /*!

async function digestBuffer(file: IsoBuffer, algorithm: "SHA-1" | "SHA-256"): Promise<Uint8Array> {
const hash = await crypto.subtle.digest(algorithm, file);
return new Uint8Array(hash);
const hash = await crypto.subtle.digest(algorithm, file);
return new Uint8Array(hash);
}
function encodeDigest(hashArray: Uint8Array, encoding: "hex" | "base64"): string {
// eslint-disable-next-line default-case
switch (encoding) {
case "hex": {
const hashHex = Array.prototype.map
.call(hashArray, (byte) => {
return byte.toString(16).padStart(2, "0") as string;
})
.join("");
return hashHex;
}
case "base64": {
return base64js.fromByteArray(hashArray);
}
}
// eslint-disable-next-line default-case
switch (encoding) {
case "hex": {
const hashHex = Array.prototype.map
.call(hashArray, (byte) => {
return byte.toString(16).padStart(2, "0") as string;
})
.join("");
return hashHex;
}
case "base64": {
return base64js.fromByteArray(hashArray);
}
}
}

@@ -44,21 +44,21 @@

export async function hashFile(
file: IsoBuffer,
algorithm: "SHA-1" | "SHA-256" = "SHA-1",
hashEncoding: "hex" | "base64" = "hex",
file: IsoBuffer,
algorithm: "SHA-1" | "SHA-256" = "SHA-1",
hashEncoding: "hex" | "base64" = "hex",
): Promise<string> {
// Handle insecure contexts (e.g. running with local services)
// by deferring to Node version, which uses a hash polyfill
// When packed, this chunk will show as "FluidFramework-HashFallback" separately
// from the main chunk and will be of non-trivial size. It will not be served
// under normal circumstances.
if (crypto.subtle === undefined) {
return import(
/* webpackChunkName: "FluidFramework-HashFallback" */
"./hashFileNode"
).then(async (m) => m.hashFile(file, algorithm, hashEncoding));
}
// Handle insecure contexts (e.g. running with local services)
// by deferring to Node version, which uses a hash polyfill
// When packed, this chunk will show as "FluidFramework-HashFallback" separately
// from the main chunk and will be of non-trivial size. It will not be served
// under normal circumstances.
if (crypto.subtle === undefined) {
return import(
/* webpackChunkName: "FluidFramework-HashFallback" */
"./hashFileNode"
).then(async (m) => m.hashFile(file, algorithm, hashEncoding));
}
// This is split up this way to facilitate testing (see the test for more info)
const hashArray = await digestBuffer(file, algorithm);
return encodeDigest(hashArray, hashEncoding);
// This is split up this way to facilitate testing (see the test for more info)
const hashArray = await digestBuffer(file, algorithm);
return encodeDigest(hashArray, hashEncoding);
}

@@ -74,8 +74,8 @@

export async function gitHashFile(file: IsoBuffer): Promise<string> {
const size = file.byteLength;
const filePrefix = `blob ${size.toString()}${String.fromCharCode(0)}`;
const hashBuffer = IsoBuffer.from(filePrefix + file.toString());
const size = file.byteLength;
const filePrefix = `blob ${size.toString()}${String.fromCharCode(0)}`;
const hashBuffer = IsoBuffer.from(filePrefix + file.toString());
// hashFile uses sha1; if that changes this will need to change too
return hashFile(hashBuffer);
// hashFile uses sha1; if that changes this will need to change too
return hashFile(hashBuffer);
}

@@ -24,19 +24,19 @@ /*!

export async function hashFile(
file: IsoBuffer,
algorithm: "SHA-1" | "SHA-256" = "SHA-1",
hashEncoding: "hex" | "base64" = "hex",
file: IsoBuffer,
algorithm: "SHA-1" | "SHA-256" = "SHA-1",
hashEncoding: "hex" | "base64" = "hex",
): Promise<string> {
let engine;
// eslint-disable-next-line default-case
switch (algorithm) {
case "SHA-1": {
engine = new sha1();
break;
}
case "SHA-256": {
engine = new sha256();
break;
}
}
return engine.update(file).digest(hashEncoding) as string;
let engine;
// eslint-disable-next-line default-case
switch (algorithm) {
case "SHA-1": {
engine = new sha1();
break;
}
case "SHA-256": {
engine = new sha256();
break;
}
}
return engine.update(file).digest(hashEncoding) as string;
}

@@ -52,6 +52,6 @@

export async function gitHashFile(file: IsoBuffer): Promise<string> {
const size = file.byteLength;
const filePrefix = `blob ${size.toString()}${String.fromCharCode(0)}`;
const engine = new sha1();
return engine.update(filePrefix).update(file).digest("hex") as string;
const size = file.byteLength;
const filePrefix = `blob ${size.toString()}${String.fromCharCode(0)}`;
const engine = new sha1();
return engine.update(filePrefix).update(file).digest("hex") as string;
}

@@ -10,13 +10,13 @@ /*!

export interface IComparer<T> {
/**
* The minimum value of type T.
*/
min: T;
/**
* The minimum value of type T.
*/
min: T;
/**
* Compare the two value
*
* @returns 0 if the value is equal, negative number if a is smaller then b, positive number otherwise
*/
compare(a: T, b: T): number;
/**
* Compare the two value
*
* @returns 0 if the value is equal, negative number if a is smaller then b, positive number otherwise
*/
compare(a: T, b: T): number;
}

@@ -28,12 +28,12 @@

export const NumberComparer: IComparer<number> = {
/**
* The compare function for numbers.
* @returns The difference of the two numbers.
*/
compare: (a, b): number => a - b,
/**
* The compare function for numbers.
* @returns The difference of the two numbers.
*/
compare: (a, b): number => a - b,
/**
* The minimum value of a JavaScript number, which is `Number.MIN_VALUE`.
*/
min: Number.MIN_VALUE,
/**
* The minimum value of a JavaScript number, which is `Number.MIN_VALUE`.
*/
min: Number.MIN_VALUE,
};

@@ -45,4 +45,4 @@

export interface IHeapNode<T> {
value: T;
position: number;
value: T;
position: number;
}

@@ -54,125 +54,125 @@

export class Heap<T> {
private L: IHeapNode<T>[];
private L: IHeapNode<T>[];
/**
* Creates an instance of `Heap` with comparer.
* @param comp - A comparer that specify how elements are ordered.
*/
constructor(public comp: IComparer<T>) {
this.L = [{ value: comp.min, position: 0 }];
}
/**
* Creates an instance of `Heap` with comparer.
* @param comp - A comparer that specify how elements are ordered.
*/
constructor(public comp: IComparer<T>) {
this.L = [{ value: comp.min, position: 0 }];
}
/**
* Return the smallest element in the heap as determined by the order of the comparer
*
* @returns Heap node containing the smallest element
*/
public peek(): IHeapNode<T> {
return this.L[1];
}
/**
* Return the smallest element in the heap as determined by the order of the comparer
*
* @returns Heap node containing the smallest element
*/
public peek(): IHeapNode<T> {
return this.L[1];
}
/**
* Get and remove the smallest element in the heap as determined by the order of the comparer
*
* @returns The smallest value in the heap
*/
public get(): T {
this.swap(1, this.count());
const x = this.L.pop();
this.fixdown(1);
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
return x!.value;
}
/**
* Get and remove the smallest element in the heap as determined by the order of the comparer
*
* @returns The smallest value in the heap
*/
public get(): T {
this.swap(1, this.count());
const x = this.L.pop();
this.fixdown(1);
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
return x!.value;
}
/**
* Add a value to the heap
*
* @param x - value to add
* @returns The heap node that contains the value
*/
public add(x: T): IHeapNode<T> {
const node = { value: x, position: this.L.length };
this.L.push(node);
this.fixup(this.count());
/**
* Add a value to the heap
*
* @param x - value to add
* @returns The heap node that contains the value
*/
public add(x: T): IHeapNode<T> {
const node = { value: x, position: this.L.length };
this.L.push(node);
this.fixup(this.count());
return node;
}
return node;
}
/**
* Allows for the Heap to be updated after a node's value changes.
*/
public update(node: IHeapNode<T>): void {
const k = node.position;
if (this.isGreaterThanParent(k)) {
this.fixup(k);
} else {
this.fixdown(k);
}
}
/**
* Allows for the Heap to be updated after a node's value changes.
*/
public update(node: IHeapNode<T>): void {
const k = node.position;
if (this.isGreaterThanParent(k)) {
this.fixup(k);
} else {
this.fixdown(k);
}
}
/**
* Removes the given node from the heap.
*
* @param node - The node to remove from the heap.
*/
public remove(node: IHeapNode<T>): void {
// Move the node we want to remove to the end of the array
const position = node.position;
this.swap(node.position, this.L.length - 1);
this.L.splice(this.L.length - 1);
/**
* Removes the given node from the heap.
*
* @param node - The node to remove from the heap.
*/
public remove(node: IHeapNode<T>): void {
// Move the node we want to remove to the end of the array
const position = node.position;
this.swap(node.position, this.L.length - 1);
this.L.splice(this.L.length - 1);
// Update the swapped node assuming we didn't remove the end of the list
if (position !== this.L.length) {
this.update(this.L[position]);
}
}
// Update the swapped node assuming we didn't remove the end of the list
if (position !== this.L.length) {
this.update(this.L[position]);
}
}
/**
* Get the number of elements in the Heap.
*
* @returns The number of elements in the Heap.
*/
public count(): number {
return this.L.length - 1;
}
/**
* Get the number of elements in the Heap.
*
* @returns The number of elements in the Heap.
*/
public count(): number {
return this.L.length - 1;
}
private fixup(pos: number): void {
let k = pos;
while (this.isGreaterThanParent(k)) {
// eslint-disable-next-line no-bitwise
const parent = k >> 1;
this.swap(k, parent);
k = parent;
}
}
private fixup(pos: number): void {
let k = pos;
while (this.isGreaterThanParent(k)) {
// eslint-disable-next-line no-bitwise
const parent = k >> 1;
this.swap(k, parent);
k = parent;
}
}
private isGreaterThanParent(k: number): boolean {
// eslint-disable-next-line no-bitwise
return k > 1 && this.comp.compare(this.L[k >> 1].value, this.L[k].value) > 0;
}
private isGreaterThanParent(k: number): boolean {
// eslint-disable-next-line no-bitwise
return k > 1 && this.comp.compare(this.L[k >> 1].value, this.L[k].value) > 0;
}
private fixdown(pos: number): void {
let k = pos;
// eslint-disable-next-line no-bitwise
while (k << 1 <= this.count()) {
// eslint-disable-next-line no-bitwise
let j = k << 1;
if (j < this.count() && this.comp.compare(this.L[j].value, this.L[j + 1].value) > 0) {
j++;
}
if (this.comp.compare(this.L[k].value, this.L[j].value) <= 0) {
break;
}
this.swap(k, j);
k = j;
}
}
private fixdown(pos: number): void {
let k = pos;
// eslint-disable-next-line no-bitwise
while (k << 1 <= this.count()) {
// eslint-disable-next-line no-bitwise
let j = k << 1;
if (j < this.count() && this.comp.compare(this.L[j].value, this.L[j + 1].value) > 0) {
j++;
}
if (this.comp.compare(this.L[k].value, this.L[j].value) <= 0) {
break;
}
this.swap(k, j);
k = j;
}
}
private swap(k: number, j: number): void {
const tmp = this.L[k];
this.L[k] = this.L[j];
this.L[k].position = k;
this.L[j] = tmp;
this.L[j].position = j;
}
private swap(k: number, j: number): void {
const tmp = this.L[k];
this.L[k] = this.L[j];
this.L[k].position = k;
this.L[j] = tmp;
this.L[j].position = j;
}
}

@@ -7,3 +7,3 @@ /*!

/**
* This package contains common utility functions and classes used by the Fluid Framework.
* This library contains common utility functions and classes used by the Fluid Framework.
*

@@ -13,21 +13,37 @@ * @packageDocumentation

export * from "./assert";
export * from "./indexNode";
export * from "./base64Encoding";
export * from "./disposal";
export * from "./eventForwarder";
export * from "./heap";
export * from "./logger";
export * from "./promiseCache";
export * from "./promises";
export * from "./rangeTracker";
export * from "./rateLimiter";
export * from "./safeParser";
export * from "./timer";
export * from "./trace";
export * from "./typedEventEmitter";
export * from "./unreachable";
export * from "./lazy";
export * from "./performanceIsomorphic";
export * from "./delay";
export * from "./bufferShared";
export { assert } from "./assert";
export { fromBase64ToUtf8, fromUtf8ToBase64, toUtf8 } from "./base64Encoding";
export { Uint8ArrayToArrayBuffer } from "./bufferShared";
export { delay } from "./delay";
export { doIfNotDisposed } from "./disposal";
export { EventForwarder } from "./eventForwarder";
export { Heap, IComparer, IHeapNode, NumberComparer } from "./heap";
export {
Buffer,
bufferToString,
gitHashFile,
hashFile,
IsoBuffer,
performance,
stringToBuffer,
Uint8ArrayToString,
} from "./indexNode";
export { Lazy } from "./lazy";
export { BaseTelemetryNullLogger, TelemetryNullLogger } from "./logger";
export { IsomorphicPerformance } from "./performanceIsomorphic";
export { PromiseCache, PromiseCacheExpiry, PromiseCacheOptions } from "./promiseCache";
export { Deferred, LazyPromise } from "./promises";
export { IRange, IRangeTrackerSnapshot, RangeTracker } from "./rangeTracker";
export { RateLimiter } from "./rateLimiter";
export { safelyParseJSON } from "./safeParser";
export {
IPromiseTimer,
IPromiseTimerResult,
ITimer,
PromiseTimer,
setLongTimeout,
Timer,
} from "./timer";
export { ITraceEvent, Trace } from "./trace";
export { EventEmitterEventType, TypedEventEmitter, TypedEventTransform } from "./typedEventEmitter";
export { unreachableCase } from "./unreachable";

@@ -6,4 +6,10 @@ /*!

export * from "./bufferBrowser";
export * from "./hashFileBrowser";
export * from "./performanceBrowser";
export {
bufferToString,
isArrayBuffer,
IsoBuffer,
stringToBuffer,
Uint8ArrayToString,
} from "./bufferBrowser";
export { gitHashFile, hashFile } from "./hashFileBrowser";
export { performance } from "./performanceBrowser";

@@ -6,4 +6,10 @@ /*!

export * from "./bufferNode";
export * from "./hashFileNode";
export * from "./performanceNode";
export {
Buffer,
bufferToString,
IsoBuffer,
stringToBuffer,
Uint8ArrayToString,
} from "./bufferNode";
export { gitHashFile, hashFile } from "./hashFileNode";
export { performance } from "./performanceNode";

@@ -10,28 +10,28 @@ /*!

export class Lazy<T> {
private _value: T | undefined;
private _evaluated: boolean = false;
/**
* Instantiates an instance of Lazy<T>.
* @param valueGenerator - The function that will generate the value when value is accessed the first time.
*/
constructor(private readonly valueGenerator: () => T) {}
private _value: T | undefined;
private _evaluated: boolean = false;
/**
* Instantiates an instance of Lazy<T>.
* @param valueGenerator - The function that will generate the value when value is accessed the first time.
*/
constructor(private readonly valueGenerator: () => T) {}
/**
* Return true if the value as been generated, otherwise false.
*/
public get evaluated(): boolean {
return this._evaluated;
}
/**
* Return true if the value as been generated, otherwise false.
*/
public get evaluated(): boolean {
return this._evaluated;
}
/**
* Get the value. If this is the first call the value will be generated.
*/
public get value(): T {
if (!this._evaluated) {
this._evaluated = true;
this._value = this.valueGenerator();
}
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
return this._value!;
}
/**
* Get the value. If this is the first call the value will be generated.
*/
public get value(): T {
if (!this._evaluated) {
this._evaluated = true;
this._value = this.valueGenerator();
}
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
return this._value!;
}
}

@@ -7,8 +7,8 @@ /*!

import {
ITelemetryBaseEvent,
ITelemetryBaseLogger,
ITelemetryErrorEvent,
ITelemetryGenericEvent,
ITelemetryLogger,
ITelemetryPerformanceEvent,
ITelemetryBaseEvent,
ITelemetryBaseLogger,
ITelemetryErrorEvent,
ITelemetryGenericEvent,
ITelemetryLogger,
ITelemetryPerformanceEvent,
} from "@fluidframework/common-definitions";

@@ -19,12 +19,13 @@

* It can be used in places where logger instance is required, but events should be not send over.
* @deprecated BaseTelemetryNullLogger has been moved to the \@fluidframework/telemetry-utils package.
*/
export class BaseTelemetryNullLogger implements ITelemetryBaseLogger {
/**
* Send an event with the logger
*
* @param event - the event to send
*/
public send(event: ITelemetryBaseEvent): void {
return;
}
/**
* Send an event with the logger
*
* @param event - the event to send
*/
public send(event: ITelemetryBaseEvent): void {
return;
}
}

@@ -35,8 +36,9 @@

* It can be used in places where logger instance is required, but events should be not send over.
* @deprecated TelemetryNullLogger has been moved to the \@fluidframework/telemetry-utils package.
*/
export class TelemetryNullLogger implements ITelemetryLogger {
public send(event: ITelemetryBaseEvent): void {}
public sendTelemetryEvent(event: ITelemetryGenericEvent, error?: any): void {}
public sendErrorEvent(event: ITelemetryErrorEvent, error?: any): void {}
public sendPerformanceEvent(event: ITelemetryPerformanceEvent, error?: any): void {}
public send(event: ITelemetryBaseEvent): void {}
public sendTelemetryEvent(event: ITelemetryGenericEvent, error?: any): void {}
public sendErrorEvent(event: ITelemetryErrorEvent, error?: any): void {}
public sendPerformanceEvent(event: ITelemetryPerformanceEvent, error?: any): void {}
}

@@ -9,2 +9,2 @@ /*!

export const pkgName = "@fluidframework/common-utils";
export const pkgVersion = "1.0.0";
export const pkgVersion = "1.1.0";

@@ -8,2 +8,2 @@ /*!

export const performance: IsomorphicPerformance = window.performance;
export const performance: IsomorphicPerformance = globalThis.performance;

@@ -11,2 +11,2 @@ /*!

export type IsomorphicPerformance = Partial<Performance> &
Pick<Performance, "clearMarks" | "mark" | "measure" | "now">;
Pick<Performance, "clearMarks" | "mark" | "measure" | "now">;

@@ -6,2 +6,3 @@ /*!

// eslint-disable-next-line import/no-nodejs-modules
import { performance as nodePerformance } from "perf_hooks";

@@ -8,0 +9,0 @@ import { IsomorphicPerformance } from "./performanceIsomorphic";

@@ -13,9 +13,9 @@ /*!

export type PromiseCacheExpiry =
| {
policy: "indefinite";
}
| {
policy: "absolute" | "sliding";
durationMs: number;
};
| {
policy: "indefinite";
}
| {
policy: "absolute" | "sliding";
durationMs: number;
};

@@ -26,6 +26,6 @@ /**

export interface PromiseCacheOptions {
/** Common expiration policy for all items added to this cache */
expiry?: PromiseCacheExpiry;
/** If the stored Promise is rejected with a particular error, should the given key be removed? */
removeOnError?: (e: any) => boolean;
/** Common expiration policy for all items added to this cache */
expiry?: PromiseCacheExpiry;
/** If the stored Promise is rejected with a particular error, should the given key be removed? */
removeOnError?: (e: any) => boolean;
}

@@ -38,45 +38,45 @@

class GarbageCollector<TKey> {
private readonly gcTimeouts = new Map<TKey, ReturnType<typeof setTimeout>>();
private readonly gcTimeouts = new Map<TKey, ReturnType<typeof setTimeout>>();
constructor(
private readonly expiry: PromiseCacheExpiry,
private readonly cleanup: (key: TKey) => void,
) {}
constructor(
private readonly expiry: PromiseCacheExpiry,
private readonly cleanup: (key: TKey) => void,
) {}
/**
* Schedule GC for the given key, as applicable
*/
public schedule(key: TKey): void {
if (this.expiry.policy !== "indefinite") {
this.gcTimeouts.set(
key,
setTimeout(() => {
this.cleanup(key);
this.cancel(key);
}, this.expiry.durationMs),
);
}
}
/**
* Schedule GC for the given key, as applicable
*/
public schedule(key: TKey): void {
if (this.expiry.policy !== "indefinite") {
this.gcTimeouts.set(
key,
setTimeout(() => {
this.cleanup(key);
this.cancel(key);
}, this.expiry.durationMs),
);
}
}
/**
* Cancel any pending GC for the given key
*/
public cancel(key: TKey): void {
const timeout = this.gcTimeouts.get(key);
if (timeout !== undefined) {
clearTimeout(timeout);
this.gcTimeouts.delete(key);
}
}
/**
* Cancel any pending GC for the given key
*/
public cancel(key: TKey): void {
const timeout = this.gcTimeouts.get(key);
if (timeout !== undefined) {
clearTimeout(timeout);
this.gcTimeouts.delete(key);
}
}
/**
* Update any pending GC for the given key, as applicable
*/
public update(key: TKey): void {
// Cancel/reschedule new GC if the policy is sliding
if (this.expiry.policy === "sliding") {
this.cancel(key);
this.schedule(key);
}
}
/**
* Update any pending GC for the given key, as applicable
*/
public update(key: TKey): void {
// Cancel/reschedule new GC if the policy is sliding
if (this.expiry.policy === "sliding") {
this.cancel(key);
this.schedule(key);
}
}
}

@@ -89,112 +89,112 @@

export class PromiseCache<TKey, TResult> {
private readonly cache = new Map<TKey, Promise<TResult>>();
private readonly gc: GarbageCollector<TKey>;
private readonly cache = new Map<TKey, Promise<TResult>>();
private readonly gc: GarbageCollector<TKey>;
private readonly removeOnError: (error: any) => boolean;
private readonly removeOnError: (error: any) => boolean;
/**
* Create the PromiseCache with the given options, with the following defaults:
*
* expiry: indefinite, removeOnError: true for all errors
*/
constructor({
expiry = { policy: "indefinite" },
removeOnError = (): boolean => true,
}: PromiseCacheOptions = {}) {
this.removeOnError = removeOnError;
this.gc = new GarbageCollector<TKey>(expiry, (key) => this.remove(key));
}
/**
* Create the PromiseCache with the given options, with the following defaults:
*
* expiry: indefinite, removeOnError: true for all errors
*/
constructor({
expiry = { policy: "indefinite" },
removeOnError = (): boolean => true,
}: PromiseCacheOptions = {}) {
this.removeOnError = removeOnError;
this.gc = new GarbageCollector<TKey>(expiry, (key) => this.remove(key));
}
/**
* Check if there's anything cached at the given key
*/
public has(key: TKey): boolean {
return this.cache.has(key);
}
/**
* Check if there's anything cached at the given key
*/
public has(key: TKey): boolean {
return this.cache.has(key);
}
/**
* Get the Promise for the given key, or undefined if it's not found.
* Extend expiry if applicable.
*/
public get(key: TKey): Promise<TResult> | undefined {
if (this.has(key)) {
this.gc.update(key);
}
return this.cache.get(key);
}
/**
* Get the Promise for the given key, or undefined if it's not found.
* Extend expiry if applicable.
*/
public get(key: TKey): Promise<TResult> | undefined {
if (this.has(key)) {
this.gc.update(key);
}
return this.cache.get(key);
}
/**
* Remove the Promise for the given key, returning true if it was found and removed
*/
public remove(key: TKey): boolean {
this.gc.cancel(key);
return this.cache.delete(key);
}
/**
* Remove the Promise for the given key, returning true if it was found and removed
*/
public remove(key: TKey): boolean {
this.gc.cancel(key);
return this.cache.delete(key);
}
/**
* Try to add the result of the given asyncFn, without overwriting an existing cache entry at that key.
* Returns a Promise for the added or existing async work being done at that key.
* @param key - key name where to store the async work
* @param asyncFn - the async work to do and store, if not already in progress under the given key
*/
public async addOrGet(key: TKey, asyncFn: () => Promise<TResult>): Promise<TResult> {
// NOTE: Do not await the Promise returned by asyncFn!
// Let the caller do so once we return or after a subsequent call to get
let promise = this.get(key);
if (promise === undefined) {
// Wrap in an async lambda in case asyncFn disabled @typescript-eslint/promise-function-async
const safeAsyncFn = async (): Promise<TResult> => asyncFn();
/**
* Try to add the result of the given asyncFn, without overwriting an existing cache entry at that key.
* Returns a Promise for the added or existing async work being done at that key.
* @param key - key name where to store the async work
* @param asyncFn - the async work to do and store, if not already in progress under the given key
*/
public async addOrGet(key: TKey, asyncFn: () => Promise<TResult>): Promise<TResult> {
// NOTE: Do not await the Promise returned by asyncFn!
// Let the caller do so once we return or after a subsequent call to get
let promise = this.get(key);
if (promise === undefined) {
// Wrap in an async lambda in case asyncFn disabled @typescript-eslint/promise-function-async
const safeAsyncFn = async (): Promise<TResult> => asyncFn();
// Start the async work and put the Promise in the cache
promise = safeAsyncFn();
this.cache.set(key, promise);
// Start the async work and put the Promise in the cache
promise = safeAsyncFn();
this.cache.set(key, promise);
// If asyncFn throws, we may remove the Promise from the cache
promise.catch((error) => {
if (this.removeOnError(error)) {
this.remove(key);
}
});
// If asyncFn throws, we may remove the Promise from the cache
promise.catch((error) => {
if (this.removeOnError(error)) {
this.remove(key);
}
});
this.gc.schedule(key);
}
this.gc.schedule(key);
}
return promise;
}
return promise;
}
/**
* Try to add the result of the given asyncFn, without overwriting an existing cache entry at that key.
* Returns false if the cache already contained an entry at that key, and true otherwise.
* @param key - key name where to store the async work
* @param asyncFn - the async work to do and store, if not already in progress under the given key
*/
public add(key: TKey, asyncFn: () => Promise<TResult>): boolean {
const alreadyPresent = this.has(key);
/**
* Try to add the result of the given asyncFn, without overwriting an existing cache entry at that key.
* Returns false if the cache already contained an entry at that key, and true otherwise.
* @param key - key name where to store the async work
* @param asyncFn - the async work to do and store, if not already in progress under the given key
*/
public add(key: TKey, asyncFn: () => Promise<TResult>): boolean {
const alreadyPresent = this.has(key);
// We are blindly adding the Promise to the cache here, which introduces a Promise in this scope.
// Swallow Promise rejections here, since whoever gets this out of the cache to use it will await/catch.
this.addOrGet(key, asyncFn).catch(() => {});
// We are blindly adding the Promise to the cache here, which introduces a Promise in this scope.
// Swallow Promise rejections here, since whoever gets this out of the cache to use it will await/catch.
this.addOrGet(key, asyncFn).catch(() => {});
return !alreadyPresent;
}
return !alreadyPresent;
}
/**
* Try to add the given value, without overwriting an existing cache entry at that key.
* Returns a Promise for the added or existing async work being done at that key.
* @param key - key name where to store the async work
* @param value - value to store
*/
public async addValueOrGet(key: TKey, value: TResult): Promise<TResult> {
return this.addOrGet(key, async () => value);
}
/**
* Try to add the given value, without overwriting an existing cache entry at that key.
* Returns a Promise for the added or existing async work being done at that key.
* @param key - key name where to store the async work
* @param value - value to store
*/
public async addValueOrGet(key: TKey, value: TResult): Promise<TResult> {
return this.addOrGet(key, async () => value);
}
/**
* Try to add the given value, without overwriting an existing cache entry at that key.
* Returns false if the cache already contained an entry at that key, and true otherwise.
* @param key - key name where to store the value
* @param value - value to store
*/
public addValue(key: TKey, value: TResult): boolean {
return this.add(key, async () => value);
}
/**
* Try to add the given value, without overwriting an existing cache entry at that key.
* Returns false if the cache already contained an entry at that key, and true otherwise.
* @param key - key name where to store the value
* @param value - value to store
*/
public addValue(key: TKey, value: TResult): boolean {
return this.add(key, async () => value);
}
}

@@ -10,52 +10,52 @@ /*!

export class Deferred<T> {
private readonly p: Promise<T>;
private res: ((value: T | PromiseLike<T>) => void) | undefined;
private rej: ((reason?: any) => void) | undefined;
private completed: boolean = false;
private readonly p: Promise<T>;
private res: ((value: T | PromiseLike<T>) => void) | undefined;
private rej: ((reason?: any) => void) | undefined;
private completed: boolean = false;
constructor() {
this.p = new Promise<T>((resolve, reject) => {
this.res = resolve;
this.rej = reject;
});
}
/**
* Returns whether the underlying promise has been completed
*/
public get isCompleted(): boolean {
return this.completed;
}
constructor() {
this.p = new Promise<T>((resolve, reject) => {
this.res = resolve;
this.rej = reject;
});
}
/**
* Returns whether the underlying promise has been completed
*/
public get isCompleted(): boolean {
return this.completed;
}
/**
* Retrieves the underlying promise for the deferred
*
* @returns the underlying promise
*/
public get promise(): Promise<T> {
return this.p;
}
/**
* Retrieves the underlying promise for the deferred
*
* @returns the underlying promise
*/
public get promise(): Promise<T> {
return this.p;
}
/**
* Resolves the promise
*
* @param value - the value to resolve the promise with
*/
public resolve(value: T | PromiseLike<T>): void {
if (this.res !== undefined) {
this.completed = true;
this.res(value);
}
}
/**
* Resolves the promise
*
* @param value - the value to resolve the promise with
*/
public resolve(value: T | PromiseLike<T>): void {
if (this.res !== undefined) {
this.completed = true;
this.res(value);
}
}
/**
* Rejects the promise
*
* @param value - the value to reject the promise with
*/
public reject(error: any): void {
if (this.rej !== undefined) {
this.completed = true;
this.rej(error);
}
}
/**
* Rejects the promise
*
* @param value - the value to reject the promise with
*/
public reject(error: any): void {
if (this.rej !== undefined) {
this.completed = true;
this.rej(error);
}
}
}

@@ -70,40 +70,40 @@

export class LazyPromise<T> implements Promise<T> {
public get [Symbol.toStringTag](): string {
return this.getPromise()[Symbol.toStringTag];
}
public get [Symbol.toStringTag](): string {
return this.getPromise()[Symbol.toStringTag];
}
private result: Promise<T> | undefined;
private result: Promise<T> | undefined;
constructor(private readonly execute: () => Promise<T>) {}
constructor(private readonly execute: () => Promise<T>) {}
public async then<TResult1 = T, TResult2 = never>(
// eslint-disable-next-line @rushstack/no-new-null
onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | null | undefined,
// eslint-disable-next-line @rushstack/no-new-null
onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null | undefined,
): Promise<TResult1 | TResult2> {
// eslint-disable-next-line prefer-rest-params
return this.getPromise().then<TResult1, TResult2>(...arguments);
}
public async then<TResult1 = T, TResult2 = never>(
// eslint-disable-next-line @rushstack/no-new-null
onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | null | undefined,
// eslint-disable-next-line @rushstack/no-new-null
onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null | undefined,
): Promise<TResult1 | TResult2> {
// eslint-disable-next-line prefer-rest-params
return this.getPromise().then<TResult1, TResult2>(...arguments);
}
public async catch<TResult = never>(
// eslint-disable-next-line @rushstack/no-new-null
onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | null | undefined,
): Promise<T | TResult> {
// eslint-disable-next-line prefer-rest-params
return this.getPromise().catch<TResult>(...arguments);
}
public async catch<TResult = never>(
// eslint-disable-next-line @rushstack/no-new-null
onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | null | undefined,
): Promise<T | TResult> {
// eslint-disable-next-line prefer-rest-params
return this.getPromise().catch<TResult>(...arguments);
}
// eslint-disable-next-line @rushstack/no-new-null
public async finally(onfinally?: (() => void) | null | undefined): Promise<T> {
// eslint-disable-next-line prefer-rest-params
return this.getPromise().finally(...arguments);
}
// eslint-disable-next-line @rushstack/no-new-null
public async finally(onfinally?: (() => void) | null | undefined): Promise<T> {
// eslint-disable-next-line prefer-rest-params
return this.getPromise().finally(...arguments);
}
private async getPromise(): Promise<T> {
if (this.result === undefined) {
this.result = this.execute();
}
return this.result;
}
private async getPromise(): Promise<T> {
if (this.result === undefined) {
this.result = this.execute();
}
return this.result;
}
}

@@ -14,5 +14,5 @@ /*!

export interface IRange {
primary: number;
secondary: number | undefined;
length: number;
primary: number;
secondary: number | undefined;
length: number;
}

@@ -24,5 +24,5 @@

export interface IRangeTrackerSnapshot {
ranges: IRange[];
lastPrimary: number;
lastSecondary: number | undefined;
ranges: IRange[];
lastPrimary: number;
lastSecondary: number | undefined;
}

@@ -38,182 +38,182 @@

export class RangeTracker {
private ranges: IRange[];
private lastPrimary: number;
private lastSecondary: number | undefined;
private ranges: IRange[];
private lastPrimary: number;
private lastSecondary: number | undefined;
get base(): number {
return this.ranges[0].primary;
}
get base(): number {
return this.ranges[0].primary;
}
/**
* Getter for the last primary that was added
*
* @returns last primary that was added
*/
get primaryHead(): number {
return this.lastPrimary;
}
/**
* Getter for the last primary that was added
*
* @returns last primary that was added
*/
get primaryHead(): number {
return this.lastPrimary;
}
/**
* Getter for the last secondary that was added
*
* @returns last secondary that was added
*/
get secondaryHead(): number | undefined {
return this.lastSecondary;
}
/**
* Getter for the last secondary that was added
*
* @returns last secondary that was added
*/
get secondaryHead(): number | undefined {
return this.lastSecondary;
}
constructor(primary: IRangeTrackerSnapshot);
constructor(primary: number, secondary: number);
constructor(primary: IRangeTrackerSnapshot | number, secondary?: number) {
if (typeof primary === "number") {
this.ranges = [{ length: 0, primary, secondary }];
this.lastPrimary = primary;
this.lastSecondary = secondary;
} else {
this.ranges = cloneDeep(primary.ranges);
this.lastPrimary = primary.lastPrimary;
this.lastSecondary = primary.lastSecondary;
}
}
constructor(primary: IRangeTrackerSnapshot);
constructor(primary: number, secondary: number);
constructor(primary: IRangeTrackerSnapshot | number, secondary?: number) {
if (typeof primary === "number") {
this.ranges = [{ length: 0, primary, secondary }];
this.lastPrimary = primary;
this.lastSecondary = secondary;
} else {
this.ranges = cloneDeep(primary.ranges);
this.lastPrimary = primary.lastPrimary;
this.lastSecondary = primary.lastSecondary;
}
}
/**
* Returns a serialized form of the RangeTracker
*/
public serialize(): IRangeTrackerSnapshot {
return {
lastPrimary: this.lastPrimary,
lastSecondary: this.lastSecondary,
ranges: cloneDeep(this.ranges),
};
}
/**
* Returns a serialized form of the RangeTracker
*/
public serialize(): IRangeTrackerSnapshot {
return {
lastPrimary: this.lastPrimary,
lastSecondary: this.lastSecondary,
ranges: cloneDeep(this.ranges),
};
}
/**
* Add a primary, secondary pair to the range
*
* @param primary - the primary number in the range
* @param secondary - the secondary number in the range
*/
public add(primary: number, secondary: number): void {
// Both values must continuously be increasing - we won't always track the last value we saw so we do so
// below to check invariants
assert(primary >= this.lastPrimary, 0x003 /* "Primary to add to range < last primary!" */);
if (this.lastSecondary !== undefined) {
assert(
secondary >= this.lastSecondary,
0x004 /* "Secondary to add to range < last secondary!" */,
);
}
this.lastPrimary = primary;
this.lastSecondary = secondary;
/**
* Add a primary, secondary pair to the range
*
* @param primary - the primary number in the range
* @param secondary - the secondary number in the range
*/
public add(primary: number, secondary: number): void {
// Both values must continuously be increasing - we won't always track the last value we saw so we do so
// below to check invariants
assert(primary >= this.lastPrimary, 0x003 /* "Primary to add to range < last primary!" */);
if (this.lastSecondary !== undefined) {
assert(
secondary >= this.lastSecondary,
0x004 /* "Secondary to add to range < last secondary!" */,
);
}
this.lastPrimary = primary;
this.lastSecondary = secondary;
// Get quicker references to the head of the range
const head = this.ranges[this.ranges.length - 1];
const primaryHead = head.primary + head.length;
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const secondaryHead = head.secondary! + head.length;
// Get quicker references to the head of the range
const head = this.ranges[this.ranges.length - 1];
const primaryHead = head.primary + head.length;
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const secondaryHead = head.secondary! + head.length;
// Same secondary indicates this is not a true inflection point - we can ignore it
if (secondary === secondaryHead) {
return;
}
// Same secondary indicates this is not a true inflection point - we can ignore it
if (secondary === secondaryHead) {
return;
}
// New secondary - need to update the ranges
if (primary === primaryHead) {
// Technically this code path has us supporting N:N ranges. But we simply overwrite duplicate values to
// preserve 1:N since you can only lookup from the primary to a secondary
if (head.length === 0) {
// No range represented - we can simply update secondary with the overwritten value
head.secondary = secondary;
} else {
// The values in the range before this one are valid - but we need to create a new one for this update
head.length--;
this.ranges.push({ length: 0, primary, secondary });
}
} else {
if (primaryHead + 1 === primary && secondaryHead + 1 === secondary) {
// Extend the length if both increase by the same amount
head.length++;
} else {
// Insert a new node
this.ranges.push({ length: 0, primary, secondary });
}
}
}
// New secondary - need to update the ranges
if (primary === primaryHead) {
// Technically this code path has us supporting N:N ranges. But we simply overwrite duplicate values to
// preserve 1:N since you can only lookup from the primary to a secondary
if (head.length === 0) {
// No range represented - we can simply update secondary with the overwritten value
head.secondary = secondary;
} else {
// The values in the range before this one are valid - but we need to create a new one for this update
head.length--;
this.ranges.push({ length: 0, primary, secondary });
}
} else {
if (primaryHead + 1 === primary && secondaryHead + 1 === secondary) {
// Extend the length if both increase by the same amount
head.length++;
} else {
// Insert a new node
this.ranges.push({ length: 0, primary, secondary });
}
}
}
/**
* Get the closest range to the primary
*
* @param primary - the primary value to look for
* @returns the closest range to the primary
*/
public get(primary: number): number {
assert(
primary >= this.ranges[0].primary,
0x005 /* "Target primary to retrieve < first range's primary!" */,
);
/**
* Get the closest range to the primary
*
* @param primary - the primary value to look for
* @returns the closest range to the primary
*/
public get(primary: number): number {
assert(
primary >= this.ranges[0].primary,
0x005 /* "Target primary to retrieve < first range's primary!" */,
);
// Find the first range where the starting position is greater than the primary. Our target range is
// the one before it.
let index = 1;
for (; index < this.ranges.length; index++) {
if (primary < this.ranges[index].primary) {
break;
}
}
assert(
primary >= this.ranges[index - 1].primary,
0x006 /* "Target primary to retrieve < last range's primary!" */,
);
// Find the first range where the starting position is greater than the primary. Our target range is
// the one before it.
let index = 1;
for (; index < this.ranges.length; index++) {
if (primary < this.ranges[index].primary) {
break;
}
}
assert(
primary >= this.ranges[index - 1].primary,
0x006 /* "Target primary to retrieve < last range's primary!" */,
);
// If the difference is within the stored range use it - otherwise add in the length - 1 as the highest
// stored secondary value to use.
const closestRange = this.ranges[index - 1];
return (
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
Math.min(primary - closestRange.primary, closestRange.length) + closestRange.secondary!
);
}
// If the difference is within the stored range use it - otherwise add in the length - 1 as the highest
// stored secondary value to use.
const closestRange = this.ranges[index - 1];
return (
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
Math.min(primary - closestRange.primary, closestRange.length) + closestRange.secondary!
);
}
/**
* Update the range of primary
*
* @param primary - the primary value to update
*/
public updateBase(primary: number): void {
assert(
primary >= this.ranges[0].primary,
0x007 /* "Target primary to update < first range's primary!" */,
);
/**
* Update the range of primary
*
* @param primary - the primary value to update
*/
public updateBase(primary: number): void {
assert(
primary >= this.ranges[0].primary,
0x007 /* "Target primary to update < first range's primary!" */,
);
// Walk the ranges looking for the first one that is greater than the primary. Primary is then within the
// previous index by definition (since it's less than the current index's primary but greather than the
// previous index's primary) and we know primary must be greater than the base.
let index = 1;
for (; index < this.ranges.length; index++) {
if (primary < this.ranges[index].primary) {
break;
}
}
assert(
primary >= this.ranges[index - 1].primary,
0x008 /* "Target primary to update < last range's primary!" */,
);
// Walk the ranges looking for the first one that is greater than the primary. Primary is then within the
// previous index by definition (since it's less than the current index's primary but greather than the
// previous index's primary) and we know primary must be greater than the base.
let index = 1;
for (; index < this.ranges.length; index++) {
if (primary < this.ranges[index].primary) {
break;
}
}
assert(
primary >= this.ranges[index - 1].primary,
0x008 /* "Target primary to update < last range's primary!" */,
);
// Update the last range values
const range = this.ranges[index - 1];
const delta = primary - range.primary;
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
range.secondary = range.secondary! + Math.min(delta, range.length);
range.length = Math.max(range.length - delta, 0);
range.primary = primary;
// Update the last range values
const range = this.ranges[index - 1];
const delta = primary - range.primary;
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
range.secondary = range.secondary! + Math.min(delta, range.length);
range.length = Math.max(range.length - delta, 0);
range.primary = primary;
// And remove unnecessary ranges
this.ranges = index - 1 > 0 ? this.ranges.slice(index - 1) : this.ranges;
// And remove unnecessary ranges
this.ranges = index - 1 > 0 ? this.ranges.slice(index - 1) : this.ranges;
// Assert that the lowest value is now the input to this method
assert(
primary === this.ranges[0].primary,
0x009 /* "After update, target primary is not first range's primary!" */,
);
}
// Assert that the lowest value is now the input to this method
assert(
primary === this.ranges[0].primary,
0x009 /* "After update, target primary is not first range's primary!" */,
);
}
}

@@ -10,39 +10,39 @@ /*!

export class RateLimiter {
private readonly requestMap = new Map<string, number>();
private readonly requestMap = new Map<string, number>();
/**
* Creates a rate limiter that keep track of the request it has made
*
* @param windowMSec - time in millisecond, use to filter out messages
* for a clientId if the last request falls within this time window
*/
constructor(private readonly windowMSec: number) {}
/**
* Creates a rate limiter that keep track of the request it has made
*
* @param windowMSec - time in millisecond, use to filter out messages
* for a clientId if the last request falls within this time window
*/
constructor(private readonly windowMSec: number) {}
/**
* Filter out the messages that had already been requested within the time window
*
* @param clientId - the clientId who want to send the message
* @param messages - the message we want to send
* @returns the message we approved to send that hasn't been sent recently
*/
public filter(clientId: string, messages: string[]): string[] {
const approvedList: string[] = [];
const currentTime = Date.now();
/**
* Filter out the messages that had already been requested within the time window
*
* @param clientId - the clientId who want to send the message
* @param messages - the message we want to send
* @returns the message we approved to send that hasn't been sent recently
*/
public filter(clientId: string, messages: string[]): string[] {
const approvedList: string[] = [];
const currentTime = Date.now();
for (const message of messages) {
const key = `${clientId}/${message}`;
if (!this.requestMap.has(key)) {
this.requestMap.set(key, currentTime);
approvedList.push(message);
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
} else if (this.requestMap.get(key)! + this.windowMSec > currentTime) {
continue;
} else {
this.requestMap.set(key, currentTime);
approvedList.push(message);
}
}
for (const message of messages) {
const key = `${clientId}/${message}`;
if (!this.requestMap.has(key)) {
this.requestMap.set(key, currentTime);
approvedList.push(message);
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
} else if (this.requestMap.get(key)! + this.windowMSec > currentTime) {
continue;
} else {
this.requestMap.set(key, currentTime);
approvedList.push(message);
}
}
return approvedList;
}
return approvedList;
}
}

@@ -16,10 +16,10 @@ /*!

export function safelyParseJSON(json: string): any | undefined {
let parsed;
try {
parsed = JSON.parse(json);
} catch (error) {
return undefined;
}
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return parsed;
let parsed;
try {
parsed = JSON.parse(json);
} catch (error) {
return undefined;
}
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return parsed;
}

@@ -10,50 +10,50 @@ /*!

export interface ITimer {
/**
* True if timer is currently running
*/
readonly hasTimer: boolean;
/**
* True if timer is currently running
*/
readonly hasTimer: boolean;
/**
* Starts the timer
*/
start(): void;
/**
* Starts the timer
*/
start(): void;
/**
* Cancels the timer if already running
*/
clear(): void;
/**
* Cancels the timer if already running
*/
clear(): void;
}
interface ITimeout {
/**
* Tick that timeout was started.
*/
startTick: number;
/**
* Tick that timeout was started.
*/
startTick: number;
/**
* Timeout duration in ms.
*/
duration: number;
/**
* Timeout duration in ms.
*/
duration: number;
/**
* Handler to execute when timeout ends.
*/
handler: () => void;
/**
* Handler to execute when timeout ends.
*/
handler: () => void;
}
interface IRunningTimerState extends ITimeout {
/**
* JavaScript Timeout object.
*/
timeout: ReturnType<typeof setTimeout>;
/**
* JavaScript Timeout object.
*/
timeout: ReturnType<typeof setTimeout>;
/**
* Intended duration in ms.
*/
intendedDuration: number;
/**
* Intended duration in ms.
*/
intendedDuration: number;
/**
* Intended restart timeout.
*/
restart?: ITimeout;
/**
* Intended restart timeout.
*/
restart?: ITimeout;
}

@@ -74,20 +74,20 @@

export function setLongTimeout(
timeoutFn: () => void,
timeoutMs: number,
setTimeoutIdFn?: (timeoutId: ReturnType<typeof setTimeout>) => void,
timeoutFn: () => void,
timeoutMs: number,
setTimeoutIdFn?: (timeoutId: ReturnType<typeof setTimeout>) => void,
): ReturnType<typeof setTimeout> {
// The setTimeout max is 24.8 days before looping occurs.
let timeoutId: ReturnType<typeof setTimeout>;
if (timeoutMs > maxSetTimeoutMs) {
const newTimeoutMs = timeoutMs - maxSetTimeoutMs;
timeoutId = setTimeout(
() => setLongTimeout(timeoutFn, newTimeoutMs, setTimeoutIdFn),
maxSetTimeoutMs,
);
} else {
timeoutId = setTimeout(() => timeoutFn(), timeoutMs);
}
// The setTimeout max is 24.8 days before looping occurs.
let timeoutId: ReturnType<typeof setTimeout>;
if (timeoutMs > maxSetTimeoutMs) {
const newTimeoutMs = timeoutMs - maxSetTimeoutMs;
timeoutId = setTimeout(
() => setLongTimeout(timeoutFn, newTimeoutMs, setTimeoutIdFn),
maxSetTimeoutMs,
);
} else {
timeoutId = setTimeout(() => timeoutFn(), Math.max(timeoutMs, 0));
}
setTimeoutIdFn?.(timeoutId);
return timeoutId;
setTimeoutIdFn?.(timeoutId);
return timeoutId;
}

@@ -102,122 +102,122 @@

export class Timer implements ITimer {
/**
* Returns true if the timer is running.
*/
public get hasTimer(): boolean {
return !!this.runningState;
}
/**
* Returns true if the timer is running.
*/
public get hasTimer(): boolean {
return !!this.runningState;
}
private runningState: IRunningTimerState | undefined;
private runningState: IRunningTimerState | undefined;
constructor(
private readonly defaultTimeout: number,
private readonly defaultHandler: () => void,
private readonly getCurrentTick: () => number = (): number => Date.now(),
) {}
constructor(
private readonly defaultTimeout: number,
private readonly defaultHandler: () => void,
private readonly getCurrentTick: () => number = (): number => Date.now(),
) {}
/**
* Calls setTimeout and tracks the resulting timeout.
* @param ms - overrides default timeout in ms
* @param handler - overrides default handler
*/
public start(
ms: number = this.defaultTimeout,
handler: () => void = this.defaultHandler,
): void {
this.startCore(ms, handler, ms);
}
/**
* Calls setTimeout and tracks the resulting timeout.
* @param ms - overrides default timeout in ms
* @param handler - overrides default handler
*/
public start(
ms: number = this.defaultTimeout,
handler: () => void = this.defaultHandler,
): void {
this.startCore(ms, handler, ms);
}
/**
* Calls clearTimeout on the underlying timeout if running.
*/
public clear(): void {
if (!this.runningState) {
return;
}
clearTimeout(this.runningState.timeout);
this.runningState = undefined;
}
/**
* Calls clearTimeout on the underlying timeout if running.
*/
public clear(): void {
if (!this.runningState) {
return;
}
clearTimeout(this.runningState.timeout);
this.runningState = undefined;
}
/**
* Restarts the timer with the new handler and duration.
* If a new handler is passed, the original handler may
* never execute.
* This is a potentially more efficient way to clear and start
* a new timer.
* @param ms - overrides previous or default timeout in ms
* @param handler - overrides previous or default handler
*/
public restart(ms?: number, handler?: () => void): void {
if (!this.runningState) {
// If restart is called first, it behaves as a call to start
this.start(ms, handler);
} else {
const duration = ms ?? this.runningState.intendedDuration;
const handlerToUse =
handler ?? this.runningState.restart?.handler ?? this.runningState.handler;
const remainingTime = this.calculateRemainingTime(this.runningState);
/**
* Restarts the timer with the new handler and duration.
* If a new handler is passed, the original handler may
* never execute.
* This is a potentially more efficient way to clear and start
* a new timer.
* @param ms - overrides previous or default timeout in ms
* @param handler - overrides previous or default handler
*/
public restart(ms?: number, handler?: () => void): void {
if (!this.runningState) {
// If restart is called first, it behaves as a call to start
this.start(ms, handler);
} else {
const duration = ms ?? this.runningState.intendedDuration;
const handlerToUse =
handler ?? this.runningState.restart?.handler ?? this.runningState.handler;
const remainingTime = this.calculateRemainingTime(this.runningState);
if (duration < remainingTime) {
// If remaining time exceeds restart duration, do a hard restart.
// The existing timeout time is too long.
this.start(duration, handlerToUse);
} else if (duration === remainingTime) {
// The existing timeout time is perfect, just update handler and data.
this.runningState.handler = handlerToUse;
this.runningState.restart = undefined;
this.runningState.intendedDuration = duration;
} else {
// If restart duration exceeds remaining time, set restart info.
// Existing timeout will start a new timeout for remaining time.
this.runningState.restart = {
startTick: this.getCurrentTick(),
duration,
handler: handlerToUse,
};
}
}
}
if (duration < remainingTime) {
// If remaining time exceeds restart duration, do a hard restart.
// The existing timeout time is too long.
this.start(duration, handlerToUse);
} else if (duration === remainingTime) {
// The existing timeout time is perfect, just update handler and data.
this.runningState.handler = handlerToUse;
this.runningState.restart = undefined;
this.runningState.intendedDuration = duration;
} else {
// If restart duration exceeds remaining time, set restart info.
// Existing timeout will start a new timeout for remaining time.
this.runningState.restart = {
startTick: this.getCurrentTick(),
duration,
handler: handlerToUse,
};
}
}
}
private startCore(duration: number, handler: () => void, intendedDuration: number): void {
this.clear();
this.runningState = {
startTick: this.getCurrentTick(),
duration,
intendedDuration,
handler,
timeout: setLongTimeout(
() => this.handler(),
duration,
(timer: number) => {
if (this.runningState !== undefined) {
this.runningState.timeout = timer;
}
},
),
};
}
private startCore(duration: number, handler: () => void, intendedDuration: number): void {
this.clear();
this.runningState = {
startTick: this.getCurrentTick(),
duration,
intendedDuration,
handler,
timeout: setLongTimeout(
() => this.handler(),
duration,
(timer: number) => {
if (this.runningState !== undefined) {
this.runningState.timeout = timer;
}
},
),
};
}
private handler(): void {
assert(!!this.runningState, 0x00a /* "Running timer missing handler" */);
const restart = this.runningState.restart;
if (restart !== undefined) {
// Restart with remaining time
const remainingTime = this.calculateRemainingTime(restart);
this.startCore(remainingTime, () => restart.handler(), restart.duration);
} else {
// Run clear first, in case the handler decides to start again
const handler = this.runningState.handler;
this.clear();
handler();
}
}
private handler(): void {
assert(!!this.runningState, 0x00a /* "Running timer missing handler" */);
const restart = this.runningState.restart;
if (restart !== undefined) {
// Restart with remaining time
const remainingTime = this.calculateRemainingTime(restart);
this.startCore(remainingTime, () => restart.handler(), restart.duration);
} else {
// Run clear first, in case the handler decides to start again
const handler = this.runningState.handler;
this.clear();
handler();
}
}
private calculateRemainingTime(runningTimeout: ITimeout): number {
const elapsedTime = this.getCurrentTick() - runningTimeout.startTick;
return runningTimeout.duration - elapsedTime;
}
private calculateRemainingTime(runningTimeout: ITimeout): number {
const elapsedTime = this.getCurrentTick() - runningTimeout.startTick;
return runningTimeout.duration - elapsedTime;
}
}
export interface IPromiseTimerResult {
timerResult: "timeout" | "cancel";
timerResult: "timeout" | "cancel";
}

@@ -230,7 +230,7 @@

export interface IPromiseTimer extends ITimer {
/**
* Starts the timer and returns a promise that
* resolves when the timer times out or is canceled.
*/
start(): Promise<IPromiseTimerResult>;
/**
* Starts the timer and returns a promise that
* resolves when the timer times out or is canceled.
*/
start(): Promise<IPromiseTimerResult>;
}

@@ -245,40 +245,40 @@

export class PromiseTimer implements IPromiseTimer {
private deferred?: Deferred<IPromiseTimerResult>;
private readonly timer: Timer;
private deferred?: Deferred<IPromiseTimerResult>;
private readonly timer: Timer;
/**
* {@inheritDoc Timer.hasTimer}
*/
public get hasTimer(): boolean {
return this.timer.hasTimer;
}
/**
* {@inheritDoc Timer.hasTimer}
*/
public get hasTimer(): boolean {
return this.timer.hasTimer;
}
constructor(defaultTimeout: number, defaultHandler: () => void) {
this.timer = new Timer(defaultTimeout, () => this.wrapHandler(defaultHandler));
}
constructor(defaultTimeout: number, defaultHandler: () => void) {
this.timer = new Timer(defaultTimeout, () => this.wrapHandler(defaultHandler));
}
/**
* {@inheritDoc IPromiseTimer.start}
*/
public async start(ms?: number, handler?: () => void): Promise<IPromiseTimerResult> {
this.clear();
this.deferred = new Deferred<IPromiseTimerResult>();
this.timer.start(ms, handler ? (): void => this.wrapHandler(handler) : undefined);
return this.deferred.promise;
}
/**
* {@inheritDoc IPromiseTimer.start}
*/
public async start(ms?: number, handler?: () => void): Promise<IPromiseTimerResult> {
this.clear();
this.deferred = new Deferred<IPromiseTimerResult>();
this.timer.start(ms, handler ? (): void => this.wrapHandler(handler) : undefined);
return this.deferred.promise;
}
public clear(): void {
this.timer.clear();
if (this.deferred) {
this.deferred.resolve({ timerResult: "cancel" });
this.deferred = undefined;
}
}
public clear(): void {
this.timer.clear();
if (this.deferred) {
this.deferred.resolve({ timerResult: "cancel" });
this.deferred = undefined;
}
}
protected wrapHandler(handler: () => void): void {
handler();
assert(!!this.deferred, 0x00b /* "Handler executed without deferred" */);
this.deferred.resolve({ timerResult: "timeout" });
this.deferred = undefined;
}
protected wrapHandler(handler: () => void): void {
handler();
assert(!!this.deferred, 0x00b /* "Handler executed without deferred" */);
this.deferred.resolve({ timerResult: "timeout" });
this.deferred = undefined;
}
}

@@ -13,22 +13,22 @@ /*!

export class Trace {
public static start(): Trace {
const startTick = performance.now();
return new Trace(startTick);
}
public static start(): Trace {
const startTick = performance.now();
return new Trace(startTick);
}
protected lastTick: number;
protected constructor(public readonly startTick: number) {
this.lastTick = startTick;
}
protected lastTick: number;
protected constructor(public readonly startTick: number) {
this.lastTick = startTick;
}
public trace(): ITraceEvent {
const tick = performance.now();
const event = {
totalTimeElapsed: tick - this.startTick,
duration: tick - this.lastTick,
tick,
};
this.lastTick = tick;
return event;
}
public trace(): ITraceEvent {
const tick = performance.now();
const event = {
totalTimeElapsed: tick - this.startTick,
duration: tick - this.lastTick,
tick,
};
this.lastTick = tick;
return event;
}
}

@@ -40,17 +40,17 @@

export interface ITraceEvent {
/**
* Total time elapsed since the start of the Trace.
* Measured in milliseconds as a floating point with a decimal
*/
readonly totalTimeElapsed: number;
/**
* Time elapsed since the last trace event.
* Measured in milliseconds as a floating point with a decimal
*/
readonly duration: number;
/**
* This number represents a relative time which should
* be consistent for all trace ticks.
*/
readonly tick: number;
/**
* Total time elapsed since the start of the Trace.
* Measured in milliseconds as a floating point with a decimal
*/
readonly totalTimeElapsed: number;
/**
* Time elapsed since the last trace event.
* Measured in milliseconds as a floating point with a decimal
*/
readonly duration: number;
/**
* This number represents a relative time which should
* be consistent for all trace ticks.
*/
readonly tick: number;
}

@@ -8,6 +8,6 @@ /*!

import {
IEvent,
TransformedEvent,
IEventTransformer,
IEventProvider,
IEvent,
TransformedEvent,
IEventTransformer,
IEventProvider,
} from "@fluidframework/common-definitions";

@@ -22,19 +22,19 @@

export type EventEmitterEventType = EventEmitter extends { on(event: infer E, listener: any) }
? E
: never;
? E
: never;
export type TypedEventTransform<TThis, TEvent> =
// Event emitter supports some special events for the emitter itself to use
// this exposes those events for the TypedEventEmitter.
// Since we know what the shape of these events are, we can describe them directly via a TransformedEvent
// which easier than trying to extend TEvent directly
TransformedEvent<
TThis,
"newListener" | "removeListener",
Parameters<(event: string, listener: (...args: any[]) => void) => void>
> &
// Expose all the events provides by TEvent
IEventTransformer<TThis, TEvent & IEvent> &
// Add the default overload so this is covertable to EventEmitter regardless of environment
TransformedEvent<TThis, EventEmitterEventType, any[]>;
// Event emitter supports some special events for the emitter itself to use
// this exposes those events for the TypedEventEmitter.
// Since we know what the shape of these events are, we can describe them directly via a TransformedEvent
// which easier than trying to extend TEvent directly
TransformedEvent<
TThis,
"newListener" | "removeListener",
Parameters<(event: string, listener: (...args: any[]) => void) => void>
> &
// Expose all the events provides by TEvent
IEventTransformer<TThis, TEvent & IEvent> &
// Add the default overload so this is covertable to EventEmitter regardless of environment
TransformedEvent<TThis, EventEmitterEventType, any[]>;

@@ -45,28 +45,28 @@ /**

export class TypedEventEmitter<TEvent>
extends EventEmitter
implements IEventProvider<TEvent & IEvent>
extends EventEmitter
implements IEventProvider<TEvent & IEvent>
{
constructor() {
super();
this.addListener = super.addListener.bind(this) as TypedEventTransform<this, TEvent>;
this.on = super.on.bind(this) as TypedEventTransform<this, TEvent>;
this.once = super.once.bind(this) as TypedEventTransform<this, TEvent>;
this.prependListener = super.prependListener.bind(this) as TypedEventTransform<
this,
TEvent
>;
this.prependOnceListener = super.prependOnceListener.bind(this) as TypedEventTransform<
this,
TEvent
>;
this.removeListener = super.removeListener.bind(this) as TypedEventTransform<this, TEvent>;
this.off = super.off.bind(this) as TypedEventTransform<this, TEvent>;
}
readonly addListener: TypedEventTransform<this, TEvent>;
readonly on: TypedEventTransform<this, TEvent>;
readonly once: TypedEventTransform<this, TEvent>;
readonly prependListener: TypedEventTransform<this, TEvent>;
readonly prependOnceListener: TypedEventTransform<this, TEvent>;
readonly removeListener: TypedEventTransform<this, TEvent>;
readonly off: TypedEventTransform<this, TEvent>;
constructor() {
super();
this.addListener = super.addListener.bind(this) as TypedEventTransform<this, TEvent>;
this.on = super.on.bind(this) as TypedEventTransform<this, TEvent>;
this.once = super.once.bind(this) as TypedEventTransform<this, TEvent>;
this.prependListener = super.prependListener.bind(this) as TypedEventTransform<
this,
TEvent
>;
this.prependOnceListener = super.prependOnceListener.bind(this) as TypedEventTransform<
this,
TEvent
>;
this.removeListener = super.removeListener.bind(this) as TypedEventTransform<this, TEvent>;
this.off = super.off.bind(this) as TypedEventTransform<this, TEvent>;
}
readonly addListener: TypedEventTransform<this, TEvent>;
readonly on: TypedEventTransform<this, TEvent>;
readonly once: TypedEventTransform<this, TEvent>;
readonly prependListener: TypedEventTransform<this, TEvent>;
readonly prependOnceListener: TypedEventTransform<this, TEvent>;
readonly removeListener: TypedEventTransform<this, TEvent>;
readonly off: TypedEventTransform<this, TEvent>;
}

@@ -12,3 +12,3 @@ /*!

export function unreachableCase(_: never, message = "Unreachable Case"): never {
throw new Error(message);
throw new Error(message);
}
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "./lib",
"module": "esnext",
},
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "./lib",
"module": "esnext",
},
}
{
"extends": "@fluidframework/build-common/ts-common-config.json",
"compilerOptions": {
"composite": true,
"rootDir": "./src",
"outDir": "./dist",
"baseUrl": ".",
"paths": {
"perf_hooks": ["types/perf_hooks.d.ts"],
},
},
"include": ["src/**/*"],
"exclude": ["src/test/**/*"],
"extends": "@fluidframework/build-common/ts-common-config.json",
"compilerOptions": {
"composite": true,
"rootDir": "./src",
"outDir": "./dist",
"baseUrl": ".",
"paths": {
"perf_hooks": ["types/perf_hooks.d.ts"],
},
},
"include": ["src/**/*"],
"exclude": ["src/test/**/*"],
}

@@ -9,3 +9,3 @@ /*!

declare module "perf_hooks" {
export const performance: import("../src/performanceIsomorphic").IsomorphicPerformance;
export const performance: import("../src/performanceIsomorphic").IsomorphicPerformance;
}

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc