@fluidframework/matrix 1.4.0-121020 → 2.0.0-dev-rc.1.0.0.224419
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.js +21 -23
- package/.mocharc.js +12 -0
- package/CHANGELOG.md +168 -0
- package/README.md +81 -21
- package/api-extractor-lint.json +4 -0
- package/api-extractor.json +2 -2
- package/api-report/matrix.api.md +130 -0
- package/dist/{handlecache.js → handlecache.cjs} +8 -10
- package/dist/handlecache.cjs.map +1 -0
- package/dist/handlecache.d.ts +1 -1
- package/dist/handlecache.d.ts.map +1 -1
- package/dist/{handletable.js → handletable.cjs} +19 -7
- package/dist/handletable.cjs.map +1 -0
- package/dist/handletable.d.ts +8 -1
- package/dist/handletable.d.ts.map +1 -1
- package/dist/{index.js → index.cjs} +3 -3
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/matrix-alpha.d.ts +213 -0
- package/dist/matrix-beta.d.ts +36 -0
- package/dist/matrix-public.d.ts +36 -0
- package/dist/matrix-untrimmed.d.ts +213 -0
- package/dist/matrix.cjs +628 -0
- package/dist/matrix.cjs.map +1 -0
- package/dist/matrix.d.ts +72 -10
- package/dist/matrix.d.ts.map +1 -1
- package/dist/{ops.js → ops.cjs} +3 -2
- package/dist/ops.cjs.map +1 -0
- package/dist/ops.d.ts +6 -2
- package/dist/ops.d.ts.map +1 -1
- package/dist/{packageVersion.js → packageVersion.cjs} +2 -2
- package/dist/packageVersion.cjs.map +1 -0
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.d.ts.map +1 -1
- package/dist/{permutationvector.js → permutationvector.cjs} +75 -85
- package/dist/permutationvector.cjs.map +1 -0
- package/dist/permutationvector.d.ts +10 -18
- package/dist/permutationvector.d.ts.map +1 -1
- package/dist/{range.js → range.cjs} +1 -1
- package/dist/range.cjs.map +1 -0
- package/dist/range.d.ts.map +1 -1
- package/dist/{runtime.js → runtime.cjs} +7 -3
- package/dist/runtime.cjs.map +1 -0
- package/dist/runtime.d.ts +4 -0
- package/dist/runtime.d.ts.map +1 -1
- package/dist/{serialization.js → serialization.cjs} +5 -5
- package/dist/serialization.cjs.map +1 -0
- package/dist/serialization.d.ts +2 -2
- package/dist/serialization.d.ts.map +1 -1
- package/dist/{sparsearray2d.js → sparsearray2d.cjs} +10 -13
- package/dist/sparsearray2d.cjs.map +1 -0
- package/dist/sparsearray2d.d.ts +5 -5
- package/dist/sparsearray2d.d.ts.map +1 -1
- package/dist/tsdoc-metadata.json +11 -0
- package/dist/{types.js → types.cjs} +1 -1
- package/dist/types.cjs.map +1 -0
- package/dist/types.d.ts +9 -3
- package/dist/types.d.ts.map +1 -1
- package/dist/undoprovider.cjs +149 -0
- package/dist/undoprovider.cjs.map +1 -0
- package/dist/undoprovider.d.ts +6 -8
- package/dist/undoprovider.d.ts.map +1 -1
- package/lib/{handlecache.d.ts → handlecache.d.mts} +3 -3
- package/lib/handlecache.d.mts.map +1 -0
- package/lib/{handlecache.js → handlecache.mjs} +6 -9
- package/lib/handlecache.mjs.map +1 -0
- package/lib/{handletable.d.ts → handletable.d.mts} +8 -1
- package/lib/handletable.d.mts.map +1 -0
- package/lib/{handletable.js → handletable.mjs} +19 -7
- package/lib/handletable.mjs.map +1 -0
- package/lib/index.d.mts +8 -0
- package/lib/index.d.mts.map +1 -0
- package/lib/index.mjs +7 -0
- package/lib/index.mjs.map +1 -0
- package/lib/matrix-alpha.d.mts +213 -0
- package/lib/matrix-beta.d.mts +36 -0
- package/lib/matrix-public.d.mts +36 -0
- package/lib/matrix-untrimmed.d.mts +213 -0
- package/lib/{matrix.d.ts → matrix.d.mts} +74 -12
- package/lib/matrix.d.mts.map +1 -0
- package/lib/{matrix.js → matrix.mjs} +256 -126
- package/lib/matrix.mjs.map +1 -0
- package/lib/{ops.d.ts → ops.d.mts} +6 -2
- package/lib/ops.d.mts.map +1 -0
- package/lib/{ops.js → ops.mjs} +2 -1
- package/lib/ops.mjs.map +1 -0
- package/lib/{packageVersion.d.ts → packageVersion.d.mts} +1 -1
- package/lib/{packageVersion.d.ts.map → packageVersion.d.mts.map} +1 -1
- package/lib/{packageVersion.js → packageVersion.mjs} +2 -2
- package/lib/packageVersion.mjs.map +1 -0
- package/lib/{permutationvector.d.ts → permutationvector.d.mts} +13 -21
- package/lib/permutationvector.d.mts.map +1 -0
- package/lib/{permutationvector.js → permutationvector.mjs} +73 -82
- package/lib/permutationvector.mjs.map +1 -0
- package/lib/range.d.mts.map +1 -0
- package/lib/{range.js → range.mjs} +1 -1
- package/lib/range.mjs.map +1 -0
- package/lib/{runtime.d.ts → runtime.d.mts} +4 -0
- package/lib/runtime.d.mts.map +1 -0
- package/lib/{runtime.js → runtime.mjs} +7 -3
- package/lib/runtime.mjs.map +1 -0
- package/lib/{serialization.d.ts → serialization.d.mts} +2 -2
- package/lib/serialization.d.mts.map +1 -0
- package/lib/{serialization.js → serialization.mjs} +3 -3
- package/lib/serialization.mjs.map +1 -0
- package/lib/{sparsearray2d.d.ts → sparsearray2d.d.mts} +5 -5
- package/lib/sparsearray2d.d.mts.map +1 -0
- package/lib/{sparsearray2d.js → sparsearray2d.mjs} +10 -13
- package/lib/sparsearray2d.mjs.map +1 -0
- package/lib/{types.d.ts → types.d.mts} +9 -3
- package/lib/types.d.mts.map +1 -0
- package/lib/{types.js → types.mjs} +1 -1
- package/lib/types.mjs.map +1 -0
- package/lib/undoprovider.d.mts +28 -0
- package/lib/undoprovider.d.mts.map +1 -0
- package/lib/undoprovider.mjs +144 -0
- package/lib/undoprovider.mjs.map +1 -0
- package/matrix.test-files.tar +0 -0
- package/package.json +110 -70
- package/{bench/src/read/sparsearray2d.ts → prettier.config.cjs} +3 -4
- package/src/handlecache.ts +116 -114
- package/src/handletable.ts +95 -71
- package/src/index.ts +1 -1
- package/src/matrix.ts +987 -689
- package/src/ops.ts +16 -11
- package/src/packageVersion.ts +1 -1
- package/src/permutationvector.ts +418 -383
- package/src/range.ts +8 -8
- package/src/runtime.ts +39 -35
- package/src/serialization.ts +16 -12
- package/src/sparsearray2d.ts +193 -192
- package/src/types.ts +9 -3
- package/src/undoprovider.ts +177 -145
- package/tsc-multi.test.json +4 -0
- package/tsconfig.json +11 -12
- package/bench/bsp-set-optimizations.md +0 -84
- package/bench/graphviz.svg +0 -73
- package/bench/src/imports.ts +0 -8
- package/bench/src/index.ts +0 -30
- package/bench/src/read/map.ts +0 -25
- package/bench/src/read/matrix/contiguous.ts +0 -15
- package/bench/src/read/matrix/fragmented.ts +0 -12
- package/bench/src/read/nativearray.ts +0 -25
- package/bench/src/read/test.ts +0 -32
- package/bench/src/read/tiled.ts +0 -233
- package/bench/src/util.ts +0 -52
- package/bench/tsconfig.json +0 -15
- package/dist/bspSet.d.ts +0 -125
- package/dist/bspSet.d.ts.map +0 -1
- package/dist/bspSet.js +0 -425
- package/dist/bspSet.js.map +0 -1
- package/dist/handlecache.js.map +0 -1
- package/dist/handletable.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/matrix.js +0 -498
- package/dist/matrix.js.map +0 -1
- package/dist/ops.js.map +0 -1
- package/dist/packageVersion.js.map +0 -1
- package/dist/permutationvector.js.map +0 -1
- package/dist/productSet.d.ts +0 -61
- package/dist/productSet.d.ts.map +0 -1
- package/dist/productSet.js +0 -676
- package/dist/productSet.js.map +0 -1
- package/dist/range.js.map +0 -1
- package/dist/runtime.js.map +0 -1
- package/dist/serialization.js.map +0 -1
- package/dist/sparsearray2d.js.map +0 -1
- package/dist/split.d.ts +0 -41
- package/dist/split.d.ts.map +0 -1
- package/dist/split.js +0 -125
- package/dist/split.js.map +0 -1
- package/dist/types.js.map +0 -1
- package/dist/undoprovider.js +0 -129
- package/dist/undoprovider.js.map +0 -1
- package/lib/bspSet.d.ts +0 -125
- package/lib/bspSet.d.ts.map +0 -1
- package/lib/bspSet.js +0 -402
- package/lib/bspSet.js.map +0 -1
- package/lib/handlecache.d.ts.map +0 -1
- package/lib/handlecache.js.map +0 -1
- package/lib/handletable.d.ts.map +0 -1
- package/lib/handletable.js.map +0 -1
- package/lib/index.d.ts +0 -8
- package/lib/index.d.ts.map +0 -1
- package/lib/index.js +0 -7
- package/lib/index.js.map +0 -1
- package/lib/matrix.d.ts.map +0 -1
- package/lib/matrix.js.map +0 -1
- package/lib/ops.d.ts.map +0 -1
- package/lib/ops.js.map +0 -1
- package/lib/packageVersion.js.map +0 -1
- package/lib/permutationvector.d.ts.map +0 -1
- package/lib/permutationvector.js.map +0 -1
- package/lib/productSet.d.ts +0 -61
- package/lib/productSet.d.ts.map +0 -1
- package/lib/productSet.js +0 -662
- package/lib/productSet.js.map +0 -1
- package/lib/range.d.ts.map +0 -1
- package/lib/range.js.map +0 -1
- package/lib/runtime.d.ts.map +0 -1
- package/lib/runtime.js.map +0 -1
- package/lib/serialization.d.ts.map +0 -1
- package/lib/serialization.js.map +0 -1
- package/lib/sparsearray2d.d.ts.map +0 -1
- package/lib/sparsearray2d.js.map +0 -1
- package/lib/split.d.ts +0 -41
- package/lib/split.d.ts.map +0 -1
- package/lib/split.js +0 -114
- package/lib/split.js.map +0 -1
- package/lib/types.d.ts.map +0 -1
- package/lib/types.js.map +0 -1
- package/lib/undoprovider.d.ts +0 -30
- package/lib/undoprovider.d.ts.map +0 -1
- package/lib/undoprovider.js +0 -124
- package/lib/undoprovider.js.map +0 -1
- package/src/bspSet.ts +0 -649
- package/src/productSet.ts +0 -974
- package/src/split.ts +0 -150
- package/tsconfig.esnext.json +0 -7
- /package/lib/{range.d.ts → range.d.mts} +0 -0
package/.eslintrc.js
CHANGED
|
@@ -4,28 +4,26 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
module.exports = {
|
|
7
|
-
|
|
8
|
-
parserOptions: {
|
|
9
|
-
project: ["./tsconfig.json", "./src/test/tsconfig.json"],
|
|
10
|
-
},
|
|
11
|
-
rules: {
|
|
12
|
-
"@typescript-eslint/no-shadow": "off",
|
|
13
|
-
"space-before-function-paren": "off", // Off because it conflicts with typescript-formatter
|
|
7
|
+
extends: [require.resolve("@fluidframework/eslint-config-fluid/minimal"), "prettier"],
|
|
14
8
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
9
|
+
parserOptions: {
|
|
10
|
+
project: ["./tsconfig.json", "./src/test/tsconfig.json"],
|
|
11
|
+
},
|
|
12
|
+
rules: {
|
|
13
|
+
"@typescript-eslint/no-shadow": "off",
|
|
14
|
+
"space-before-function-paren": "off", // Off because it conflicts with typescript-formatter
|
|
15
|
+
|
|
16
|
+
// This library is used in the browser, so we don't want dependencies on most node libraries.
|
|
17
|
+
"import/no-nodejs-modules": ["error", { allow: ["events"] }],
|
|
18
|
+
},
|
|
19
|
+
overrides: [
|
|
20
|
+
{
|
|
21
|
+
// Rules only for test files
|
|
22
|
+
files: ["*.spec.ts", "src/test/**"],
|
|
23
|
+
rules: {
|
|
24
|
+
// Test files are run in node only so additional node libraries can be used.
|
|
25
|
+
"import/no-nodejs-modules": ["error", { allow: ["assert", "events"] }],
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
],
|
|
31
29
|
};
|
package/.mocharc.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
|
+
* Licensed under the MIT License.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
"use strict";
|
|
7
|
+
|
|
8
|
+
const getFluidTestMochaConfig = require("@fluidframework/mocha-test-setup/mocharc-common");
|
|
9
|
+
|
|
10
|
+
const packageDir = __dirname;
|
|
11
|
+
const config = getFluidTestMochaConfig(packageDir);
|
|
12
|
+
module.exports = config;
|
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
# @fluidframework/matrix
|
|
2
|
+
|
|
3
|
+
## 2.0.0-internal.8.0.0
|
|
4
|
+
|
|
5
|
+
### Major Changes
|
|
6
|
+
|
|
7
|
+
- sequence: Some function return types are now void instead of any [9a451d4946](https://github.com/microsoft/FluidFramework/commits/9a451d4946b5c51a52e4d1ab5bf51e7b285b0d74)
|
|
8
|
+
|
|
9
|
+
The return types of some functions have changed from `any` to `void` because the projects are now being compiled with
|
|
10
|
+
the `noImplicitAny` TypeScript compilation option. This does not represent a logic change and only serves to make the
|
|
11
|
+
typing of these functions more accurate.
|
|
12
|
+
|
|
13
|
+
- datastore-definitions: Jsonable and Serializable now require a generic parameter [9a451d4946](https://github.com/microsoft/FluidFramework/commits/9a451d4946b5c51a52e4d1ab5bf51e7b285b0d74)
|
|
14
|
+
|
|
15
|
+
The `Jsonable` and `Serializable` types from @fluidframework/datastore-definitions now require a generic parameter and
|
|
16
|
+
if that type is `any` or `unknown`will return a new result `JsonableTypeWith<>` that more accurately represents the
|
|
17
|
+
limitation of serialization.
|
|
18
|
+
|
|
19
|
+
Additional modifications:
|
|
20
|
+
|
|
21
|
+
- `Jsonable`'s `TReplacement` parameter default has also been changed from `void` to `never`, which now disallows
|
|
22
|
+
`void`.
|
|
23
|
+
- Unrecognized primitive types like `symbol` are now filtered to `never` instead of `{}`.
|
|
24
|
+
- Recursive types with arrays (`[]`) are now supported.
|
|
25
|
+
|
|
26
|
+
`Serializable` is commonly used for DDS values and now requires more precision when using them. For example SharedMatrix
|
|
27
|
+
(unqualified) has an `any` default that meant values were `Serializable<any>` (i.e. `any`), but now `Serializable<any>`
|
|
28
|
+
is `JsonableTypeWith<IFluidHandle>` which may be problematic for reading or writing. Preferred correction is to specify
|
|
29
|
+
the value type but casting through `any` may provide a quick fix.
|
|
30
|
+
|
|
31
|
+
## 2.0.0-internal.7.4.0
|
|
32
|
+
|
|
33
|
+
Dependency updates only.
|
|
34
|
+
|
|
35
|
+
## 2.0.0-internal.7.3.0
|
|
36
|
+
|
|
37
|
+
Dependency updates only.
|
|
38
|
+
|
|
39
|
+
## 2.0.0-internal.7.2.0
|
|
40
|
+
|
|
41
|
+
Dependency updates only.
|
|
42
|
+
|
|
43
|
+
## 2.0.0-internal.7.1.0
|
|
44
|
+
|
|
45
|
+
Dependency updates only.
|
|
46
|
+
|
|
47
|
+
## 2.0.0-internal.7.0.0
|
|
48
|
+
|
|
49
|
+
### Major Changes
|
|
50
|
+
|
|
51
|
+
- Dependencies on @fluidframework/protocol-definitions package updated to 3.0.0 [871b3493dd](https://github.com/microsoft/FluidFramework/commits/871b3493dd0d7ea3a89be64998ceb6cb9021a04e)
|
|
52
|
+
|
|
53
|
+
This included the following changes from the protocol-definitions release:
|
|
54
|
+
|
|
55
|
+
- Updating signal interfaces for some planned improvements. The intention is split the interface between signals
|
|
56
|
+
submitted by clients to the server and the resulting signals sent from the server to clients.
|
|
57
|
+
- A new optional type member is available on the ISignalMessage interface and a new ISentSignalMessage interface has
|
|
58
|
+
been added, which will be the typing for signals sent from the client to the server. Both extend a new
|
|
59
|
+
ISignalMessageBase interface that contains common members.
|
|
60
|
+
- The @fluidframework/common-definitions package dependency has been updated to version 1.0.0.
|
|
61
|
+
|
|
62
|
+
- Server upgrade: dependencies on Fluid server packages updated to 2.0.1 [871b3493dd](https://github.com/microsoft/FluidFramework/commits/871b3493dd0d7ea3a89be64998ceb6cb9021a04e)
|
|
63
|
+
|
|
64
|
+
Dependencies on the following Fluid server package have been updated to version 2.0.1:
|
|
65
|
+
|
|
66
|
+
- @fluidframework/gitresources: 2.0.1
|
|
67
|
+
- @fluidframework/server-kafka-orderer: 2.0.1
|
|
68
|
+
- @fluidframework/server-lambdas: 2.0.1
|
|
69
|
+
- @fluidframework/server-lambdas-driver: 2.0.1
|
|
70
|
+
- @fluidframework/server-local-server: 2.0.1
|
|
71
|
+
- @fluidframework/server-memory-orderer: 2.0.1
|
|
72
|
+
- @fluidframework/protocol-base: 2.0.1
|
|
73
|
+
- @fluidframework/server-routerlicious: 2.0.1
|
|
74
|
+
- @fluidframework/server-routerlicious-base: 2.0.1
|
|
75
|
+
- @fluidframework/server-services: 2.0.1
|
|
76
|
+
- @fluidframework/server-services-client: 2.0.1
|
|
77
|
+
- @fluidframework/server-services-core: 2.0.1
|
|
78
|
+
- @fluidframework/server-services-ordering-kafkanode: 2.0.1
|
|
79
|
+
- @fluidframework/server-services-ordering-rdkafka: 2.0.1
|
|
80
|
+
- @fluidframework/server-services-ordering-zookeeper: 2.0.1
|
|
81
|
+
- @fluidframework/server-services-shared: 2.0.1
|
|
82
|
+
- @fluidframework/server-services-telemetry: 2.0.1
|
|
83
|
+
- @fluidframework/server-services-utils: 2.0.1
|
|
84
|
+
- @fluidframework/server-test-utils: 2.0.1
|
|
85
|
+
- tinylicious: 2.0.1
|
|
86
|
+
|
|
87
|
+
- Minimum TypeScript version now 5.1.6 [871b3493dd](https://github.com/microsoft/FluidFramework/commits/871b3493dd0d7ea3a89be64998ceb6cb9021a04e)
|
|
88
|
+
|
|
89
|
+
The minimum supported TypeScript version for Fluid 2.0 clients is now 5.1.6.
|
|
90
|
+
|
|
91
|
+
## 2.0.0-internal.6.4.0
|
|
92
|
+
|
|
93
|
+
Dependency updates only.
|
|
94
|
+
|
|
95
|
+
## 2.0.0-internal.6.3.0
|
|
96
|
+
|
|
97
|
+
Dependency updates only.
|
|
98
|
+
|
|
99
|
+
## 2.0.0-internal.6.2.0
|
|
100
|
+
|
|
101
|
+
### Minor Changes
|
|
102
|
+
|
|
103
|
+
- Remove use of @fluidframework/common-definitions ([#16638](https://github.com/microsoft/FluidFramework/issues/16638)) [a8c81509c9](https://github.com/microsoft/FluidFramework/commits/a8c81509c9bf09cfb2092ebcf7265205f9eb6dbf)
|
|
104
|
+
|
|
105
|
+
The **@fluidframework/common-definitions** package is being deprecated, so the following interfaces and types are now
|
|
106
|
+
imported from the **@fluidframework/core-interfaces** package:
|
|
107
|
+
|
|
108
|
+
- interface IDisposable
|
|
109
|
+
- interface IErrorEvent
|
|
110
|
+
- interface IErrorEvent
|
|
111
|
+
- interface IEvent
|
|
112
|
+
- interface IEventProvider
|
|
113
|
+
- interface ILoggingError
|
|
114
|
+
- interface ITaggedTelemetryPropertyType
|
|
115
|
+
- interface ITelemetryBaseEvent
|
|
116
|
+
- interface ITelemetryBaseLogger
|
|
117
|
+
- interface ITelemetryErrorEvent
|
|
118
|
+
- interface ITelemetryGenericEvent
|
|
119
|
+
- interface ITelemetryLogger
|
|
120
|
+
- interface ITelemetryPerformanceEvent
|
|
121
|
+
- interface ITelemetryProperties
|
|
122
|
+
- type ExtendEventProvider
|
|
123
|
+
- type IEventThisPlaceHolder
|
|
124
|
+
- type IEventTransformer
|
|
125
|
+
- type ReplaceIEventThisPlaceHolder
|
|
126
|
+
- type ReplaceIEventThisPlaceHolder
|
|
127
|
+
- type TelemetryEventCategory
|
|
128
|
+
- type TelemetryEventPropertyType
|
|
129
|
+
|
|
130
|
+
## 2.0.0-internal.6.1.0
|
|
131
|
+
|
|
132
|
+
Dependency updates only.
|
|
133
|
+
|
|
134
|
+
## 2.0.0-internal.6.0.0
|
|
135
|
+
|
|
136
|
+
### Major Changes
|
|
137
|
+
|
|
138
|
+
- Upgraded typescript transpilation target to ES2020 [8abce8cdb4](https://github.com/microsoft/FluidFramework/commits/8abce8cdb4e2832fb6405fb44e393bef03d5648a)
|
|
139
|
+
|
|
140
|
+
Upgraded typescript transpilation target to ES2020. This is done in order to decrease the bundle sizes of Fluid Framework packages. This has provided size improvements across the board for ex. Loader, Driver, Runtime etc. Reduced bundle sizes helps to load lesser code in apps and hence also helps to improve the perf.If any app wants to target any older versions of browsers with which this target version is not compatible, then they can use packages like babel to transpile to a older target.
|
|
141
|
+
|
|
142
|
+
## 2.0.0-internal.5.4.0
|
|
143
|
+
|
|
144
|
+
Dependency updates only.
|
|
145
|
+
|
|
146
|
+
## 2.0.0-internal.5.3.0
|
|
147
|
+
|
|
148
|
+
Dependency updates only.
|
|
149
|
+
|
|
150
|
+
## 2.0.0-internal.5.2.0
|
|
151
|
+
|
|
152
|
+
Dependency updates only.
|
|
153
|
+
|
|
154
|
+
## 2.0.0-internal.5.1.0
|
|
155
|
+
|
|
156
|
+
Dependency updates only.
|
|
157
|
+
|
|
158
|
+
## 2.0.0-internal.5.0.0
|
|
159
|
+
|
|
160
|
+
Dependency updates only.
|
|
161
|
+
|
|
162
|
+
## 2.0.0-internal.4.4.0
|
|
163
|
+
|
|
164
|
+
Dependency updates only.
|
|
165
|
+
|
|
166
|
+
## 2.0.0-internal.4.1.0
|
|
167
|
+
|
|
168
|
+
Dependency updates only.
|
package/README.md
CHANGED
|
@@ -1,14 +1,35 @@
|
|
|
1
1
|
# @fluidframework/matrix
|
|
2
2
|
|
|
3
|
-
SharedMatrix is a rectangular 2D array of values.
|
|
3
|
+
SharedMatrix is a rectangular 2D array of values. Matrix values are a superset of JSON serializable types that includes embedded IFluidHandle references to Fluid object.
|
|
4
|
+
|
|
5
|
+
<!-- AUTO-GENERATED-CONTENT:START (README_DEPENDENCY_GUIDELINES_SECTION:includeHeading=TRUE) -->
|
|
6
|
+
|
|
7
|
+
<!-- prettier-ignore-start -->
|
|
8
|
+
<!-- NOTE: This section is automatically generated using @fluid-tools/markdown-magic. Do not update these generated contents directly. -->
|
|
9
|
+
|
|
10
|
+
## Using Fluid Framework libraries
|
|
11
|
+
|
|
12
|
+
When taking a dependency on a Fluid Framework library, we recommend using a `^` (caret) version range, such as `^1.3.4`.
|
|
13
|
+
While Fluid Framework libraries may use different ranges with interdependencies between other Fluid Framework libraries,
|
|
14
|
+
library consumers should always prefer `^`.
|
|
15
|
+
|
|
16
|
+
Note that when depending on a library version of the form `2.0.0-internal.x.y.z`, called the Fluid internal version scheme,
|
|
17
|
+
you must use a `>= <` dependency range (such as `>=2.0.0-internal.x.y.z <2.0.0-internal.w.0.0` where `w` is `x+1`).
|
|
18
|
+
Standard `^` and `~` ranges will not work as expected.
|
|
19
|
+
See the [@fluid-tools/version-tools](https://github.com/microsoft/FluidFramework/blob/main/build-tools/packages/version-tools/README.md)
|
|
20
|
+
package for more information including tools to convert between version schemes.
|
|
21
|
+
|
|
22
|
+
<!-- prettier-ignore-end -->
|
|
23
|
+
|
|
24
|
+
<!-- AUTO-GENERATED-CONTENT:END -->
|
|
4
25
|
|
|
5
26
|
## Operations
|
|
6
27
|
|
|
7
28
|
The SharedMatrix currently supports the following operations:
|
|
8
29
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
30
|
+
- `insertCols(col, numCols)` / `removeCols(col, numCols)`
|
|
31
|
+
- `insertRows(row, numRows)` / `removeRows(row, numRows)`
|
|
32
|
+
- `setCells(row, col, numCols, values)` (values is a 1D array in row-major order)
|
|
12
33
|
|
|
13
34
|
Insertion / removal operations are reconciled using Fluid sequence semantics, while setCells() uses Fluid map semantics.
|
|
14
35
|
|
|
@@ -16,8 +37,8 @@ Insertion / removal operations are reconciled using Fluid sequence semantics, wh
|
|
|
16
37
|
|
|
17
38
|
The SharedMatrix data structure is comprised of:
|
|
18
39
|
|
|
19
|
-
|
|
20
|
-
|
|
40
|
+
- Two 'PermutationVectors', which are used to process row/col insertion and removal ops
|
|
41
|
+
- A sparse quadtree-like "physical store" for holding the cell values
|
|
21
42
|
|
|
22
43
|
### Permutation Vectors
|
|
23
44
|
|
|
@@ -57,7 +78,7 @@ physical row -> 1 | 8 .
|
|
|
57
78
|
```
|
|
58
79
|
|
|
59
80
|
The next row/column to be inserted is assigned the next available physical address, regardless of
|
|
60
|
-
where the row/col was logically inserted.
|
|
81
|
+
where the row/col was logically inserted. Deleted rows/cols are recycled after clearing the physical store.
|
|
61
82
|
|
|
62
83
|
This indirection between logical row/col and storage row/col provides three functions:
|
|
63
84
|
|
|
@@ -66,12 +87,12 @@ This indirection between logical row/col and storage row/col provides three func
|
|
|
66
87
|
updated).
|
|
67
88
|
3. It enables us to "time-travel" to previous matrix versions when reconciling ops from remote clients.
|
|
68
89
|
|
|
69
|
-
To support reconciliation, we use a MergeTree for each PermutationVector.
|
|
90
|
+
To support reconciliation, we use a MergeTree for each PermutationVector. MergeTree is a B-Tree of order 7 that
|
|
70
91
|
temporarily maintains some extra metadata to reconcile ops while they are within the current collab window.
|
|
71
92
|
|
|
72
93
|
### Physical Storage
|
|
73
94
|
|
|
74
|
-
Cell data is stored in a quadtree-like data structure that is a recursive subdivision of 16x16 tiles.
|
|
95
|
+
Cell data is stored in a quadtree-like data structure that is a recursive subdivision of 16x16 tiles. The
|
|
75
96
|
implementation leverages [Morton coding](https://en.wikipedia.org/wiki/Z-order_curve) to implement this as a cascade of
|
|
76
97
|
fast 1D array accesses.
|
|
77
98
|
|
|
@@ -81,20 +102,59 @@ const keyLo = r0c0ToMorton2x16((row << 16) >>> 16, (col << 16) >>> 16);
|
|
|
81
102
|
|
|
82
103
|
const level0 = this.root[keyHi];
|
|
83
104
|
if (level0 !== undefined) {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
105
|
+
const level1 = level0[byte0(keyLo)];
|
|
106
|
+
if (level1 !== undefined) {
|
|
107
|
+
const level2 = level1[byte1(keyLo)];
|
|
108
|
+
if (level2 !== undefined) {
|
|
109
|
+
const level3 = level2[byte2(keyLo)];
|
|
110
|
+
if (level3 !== undefined) {
|
|
111
|
+
return level3[byte3(keyLo)];
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
94
115
|
}
|
|
95
|
-
return undefined;
|
|
116
|
+
return undefined; // Empty region
|
|
96
117
|
```
|
|
97
118
|
|
|
98
119
|
A benefit of storing the cell data in [Z-order](https://en.wikipedia.org/wiki/Z-order_curve) is that both row-major and
|
|
99
|
-
col-major traversal benefit from prefetching and cache coherence.
|
|
120
|
+
col-major traversal benefit from prefetching and cache coherence. Reading/writing to the physical storage along either
|
|
100
121
|
axis is typically within an order of magnitude compared to sequentially accessing a cache hot native JavaScript array.
|
|
122
|
+
|
|
123
|
+
### Switching From Last Write Win(LWW) to First Write Win(FWW) mode
|
|
124
|
+
|
|
125
|
+
Shared Matrix allows to make to make one way switch from LWW to FWW. This is introduced in order to handle conflict
|
|
126
|
+
when multiple clients at once initialize a cell. Using FWW, will help clients to receive a `conflict` event in case
|
|
127
|
+
their change was rejected. They can resolve conflict with the new information that they received in the event.
|
|
128
|
+
This event is only emitted when the SetCell Resolution Policy is First Write Win(FWW). This is emitted when two clients
|
|
129
|
+
race and send changes without observing each other changes, the changes that gets sequenced last would be rejected, and
|
|
130
|
+
only client who's changes rejected would be notified via this event, with expectation that it will merge its changes
|
|
131
|
+
back by accounting new information (state from winner of the race).
|
|
132
|
+
|
|
133
|
+
Some cases which documents how the Set op changes are applied or rejected during LWW -> FWW switch as some clients will
|
|
134
|
+
be in FWW mode and some will in LWW mode. When app calls `switchSetCellPolicy` the policy is changed to FWW mode
|
|
135
|
+
immediately and then later communicated to other clients via next SetOp which is made on the matrix.
|
|
136
|
+
|
|
137
|
+
**Case 1:** When all clients have switched to FWW mode, then any race between 2 Set Op, will result in a `conflict` event
|
|
138
|
+
at the loser client until it receives its own latest Set op. For example, client has sent op for cell C1. It receives remote
|
|
139
|
+
ops R1 and R2 for cell C1. It will first raise `conflict` event when it receives R1 and then another `conflict` event when
|
|
140
|
+
it receives R2. This will keep happening until it receives its own op, so that its changes are not lost due to conflict.
|
|
141
|
+
|
|
142
|
+
**Case 2:** Client switches policy to FWW locally. No SetOp is made yet. This client has no pending changes yet. On receiving
|
|
143
|
+
remote Set ops, this client will apply them all.
|
|
144
|
+
|
|
145
|
+
**Case 3:** Client switches policy to FWW locally. This client has pending changes for cell C1. On
|
|
146
|
+
receiving remote LWW Set op for C1, this client will reject it as its own op will finally be applied. So the first FWW
|
|
147
|
+
SetOp is still treated as LWW op in a way. Now lets say it has received a remote FWW op for C1 instead of a LWW op, then
|
|
148
|
+
the remote op would have been applied causing client's policy to shift to FWW with that op. It will also raise a conflict
|
|
149
|
+
event locally as its Op for cell c1 will be rejected by other clients as it is a loser op.
|
|
150
|
+
|
|
151
|
+
**Case 4:** In FWW mode, when there is no conflict, clients will still be able to overwrite cells. We track the sequence
|
|
152
|
+
number for each cell when it was last edited and also track the clientId which made that change. If the receive a Op for
|
|
153
|
+
cell C1, and its ref Sequence number is >= to sequence number at which it was last edited, then the cell would be
|
|
154
|
+
overwritten. Otherwise, if the same client made the changes, then the op will still be applied as the client knew about
|
|
155
|
+
the previous edit.
|
|
156
|
+
|
|
157
|
+
**Case 5: Reconnection:** When a client makes an op in LWW mode in disconnected state for cell C1, then when it comes online
|
|
158
|
+
later on, and catches up it sees a FWW op for C1, it will raise a `conflict` event for C1 and will not send it own op.
|
|
159
|
+
It can receive many ops for C1 during catchup and will raise `conflict` event for each of those in case they are winner
|
|
160
|
+
ops for C1.
|
package/api-extractor.json
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
"$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json",
|
|
3
|
+
"extends": "../../../common/build/build-common/api-extractor-base.json"
|
|
4
4
|
}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
## API Report File for "@fluidframework/matrix"
|
|
2
|
+
|
|
3
|
+
> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
|
|
4
|
+
|
|
5
|
+
```ts
|
|
6
|
+
|
|
7
|
+
import { IChannel } from '@fluidframework/datastore-definitions';
|
|
8
|
+
import { IChannelAttributes } from '@fluidframework/datastore-definitions';
|
|
9
|
+
import { IChannelFactory } from '@fluidframework/datastore-definitions';
|
|
10
|
+
import { IChannelServices } from '@fluidframework/datastore-definitions';
|
|
11
|
+
import { IChannelStorageService } from '@fluidframework/datastore-definitions';
|
|
12
|
+
import { IEventThisPlaceHolder } from '@fluidframework/core-interfaces';
|
|
13
|
+
import { IFluidDataStoreRuntime } from '@fluidframework/datastore-definitions';
|
|
14
|
+
import { IFluidSerializer } from '@fluidframework/shared-object-base';
|
|
15
|
+
import { IJSONSegment } from '@fluidframework/merge-tree';
|
|
16
|
+
import { IMatrixConsumer } from '@tiny-calc/nano';
|
|
17
|
+
import { IMatrixProducer } from '@tiny-calc/nano';
|
|
18
|
+
import { IMatrixReader } from '@tiny-calc/nano';
|
|
19
|
+
import { IMatrixWriter } from '@tiny-calc/nano';
|
|
20
|
+
import { ISequencedDocumentMessage } from '@fluidframework/protocol-definitions';
|
|
21
|
+
import { ISharedObjectEvents } from '@fluidframework/shared-object-base';
|
|
22
|
+
import { ISummaryTreeWithStats } from '@fluidframework/runtime-definitions';
|
|
23
|
+
import { Serializable } from '@fluidframework/datastore-definitions';
|
|
24
|
+
import { SharedObject } from '@fluidframework/shared-object-base';
|
|
25
|
+
|
|
26
|
+
// @alpha (undocumented)
|
|
27
|
+
export interface IRevertible {
|
|
28
|
+
// (undocumented)
|
|
29
|
+
discard(): void;
|
|
30
|
+
// (undocumented)
|
|
31
|
+
revert(): void;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// @alpha
|
|
35
|
+
export interface ISharedMatrixEvents<T> extends ISharedObjectEvents {
|
|
36
|
+
(event: "conflict", listener: (row: number, col: number, currentValue: MatrixItem<T>, conflictingValue: MatrixItem<T>, target: IEventThisPlaceHolder) => void): void;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// @alpha (undocumented)
|
|
40
|
+
export interface IUndoConsumer {
|
|
41
|
+
// (undocumented)
|
|
42
|
+
pushToCurrentOperation(revertible: IRevertible): void;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// @alpha
|
|
46
|
+
export type MatrixItem<T> = Serializable<Exclude<T, null>> | undefined;
|
|
47
|
+
|
|
48
|
+
// @alpha
|
|
49
|
+
export class SharedMatrix<T = any> extends SharedObject<ISharedMatrixEvents<T>> implements IMatrixProducer<MatrixItem<T>>, IMatrixReader<MatrixItem<T>>, IMatrixWriter<MatrixItem<T>> {
|
|
50
|
+
constructor(runtime: IFluidDataStoreRuntime, id: string, attributes: IChannelAttributes, _isSetCellConflictResolutionPolicyFWW?: boolean);
|
|
51
|
+
// (undocumented)
|
|
52
|
+
protected applyStashedOp(content: any): unknown;
|
|
53
|
+
// (undocumented)
|
|
54
|
+
closeMatrix(consumer: IMatrixConsumer<MatrixItem<T>>): void;
|
|
55
|
+
// (undocumented)
|
|
56
|
+
get colCount(): number;
|
|
57
|
+
// (undocumented)
|
|
58
|
+
static create<T>(runtime: IFluidDataStoreRuntime, id?: string): SharedMatrix<T>;
|
|
59
|
+
// (undocumented)
|
|
60
|
+
protected didAttach(): void;
|
|
61
|
+
// (undocumented)
|
|
62
|
+
getCell(row: number, col: number): MatrixItem<T>;
|
|
63
|
+
// (undocumented)
|
|
64
|
+
static getFactory(): SharedMatrixFactory;
|
|
65
|
+
// (undocumented)
|
|
66
|
+
id: string;
|
|
67
|
+
// (undocumented)
|
|
68
|
+
insertCols(colStart: number, count: number): void;
|
|
69
|
+
// (undocumented)
|
|
70
|
+
insertRows(rowStart: number, count: number): void;
|
|
71
|
+
// (undocumented)
|
|
72
|
+
isSetCellConflictResolutionPolicyFWW(): boolean;
|
|
73
|
+
// (undocumented)
|
|
74
|
+
protected loadCore(storage: IChannelStorageService): Promise<void>;
|
|
75
|
+
// (undocumented)
|
|
76
|
+
get matrixProducer(): IMatrixProducer<MatrixItem<T>>;
|
|
77
|
+
// (undocumented)
|
|
78
|
+
protected onConnect(): void;
|
|
79
|
+
// (undocumented)
|
|
80
|
+
protected onDisconnect(): void;
|
|
81
|
+
// (undocumented)
|
|
82
|
+
openMatrix(consumer: IMatrixConsumer<MatrixItem<T>>): IMatrixReader<MatrixItem<T>>;
|
|
83
|
+
openUndo(consumer: IUndoConsumer): void;
|
|
84
|
+
// (undocumented)
|
|
85
|
+
protected processCore(rawMessage: ISequencedDocumentMessage, local: boolean, localOpMetadata: unknown): void;
|
|
86
|
+
protected processGCDataCore(serializer: IFluidSerializer): void;
|
|
87
|
+
// (undocumented)
|
|
88
|
+
removeCols(colStart: number, count: number): void;
|
|
89
|
+
// (undocumented)
|
|
90
|
+
removeRows(rowStart: number, count: number): void;
|
|
91
|
+
// (undocumented)
|
|
92
|
+
protected reSubmitCore(content: any, localOpMetadata: unknown): void;
|
|
93
|
+
// (undocumented)
|
|
94
|
+
get rowCount(): number;
|
|
95
|
+
// (undocumented)
|
|
96
|
+
setCell(row: number, col: number, value: MatrixItem<T>): void;
|
|
97
|
+
// (undocumented)
|
|
98
|
+
setCells(rowStart: number, colStart: number, colCount: number, values: readonly MatrixItem<T>[]): void;
|
|
99
|
+
// (undocumented)
|
|
100
|
+
protected submitLocalMessage(message: any, localOpMetadata?: any): void;
|
|
101
|
+
// (undocumented)
|
|
102
|
+
protected summarizeCore(serializer: IFluidSerializer): ISummaryTreeWithStats;
|
|
103
|
+
switchSetCellPolicy(): void;
|
|
104
|
+
// (undocumented)
|
|
105
|
+
toString(): string;
|
|
106
|
+
// (undocumented)
|
|
107
|
+
_undoRemoveCols(colStart: number, spec: IJSONSegment): void;
|
|
108
|
+
// (undocumented)
|
|
109
|
+
_undoRemoveRows(rowStart: number, spec: IJSONSegment): void;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// @alpha
|
|
113
|
+
export class SharedMatrixFactory implements IChannelFactory {
|
|
114
|
+
// (undocumented)
|
|
115
|
+
static readonly Attributes: IChannelAttributes;
|
|
116
|
+
// (undocumented)
|
|
117
|
+
get attributes(): IChannelAttributes;
|
|
118
|
+
// (undocumented)
|
|
119
|
+
create(document: IFluidDataStoreRuntime, id: string): IChannel;
|
|
120
|
+
// (undocumented)
|
|
121
|
+
load(runtime: IFluidDataStoreRuntime, id: string, services: IChannelServices, attributes: IChannelAttributes): Promise<IChannel>;
|
|
122
|
+
// (undocumented)
|
|
123
|
+
static Type: string;
|
|
124
|
+
// (undocumented)
|
|
125
|
+
get type(): string;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// (No @packageDocumentation comment for this package)
|
|
129
|
+
|
|
130
|
+
```
|
|
@@ -6,14 +6,14 @@
|
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
7
|
exports.HandleCache = void 0;
|
|
8
8
|
/* eslint-disable no-bitwise */
|
|
9
|
-
const
|
|
10
|
-
const handletable_1 = require("./handletable");
|
|
11
|
-
const range_1 = require("./range");
|
|
9
|
+
const core_utils_1 = require("@fluidframework/core-utils");
|
|
10
|
+
const handletable_1 = require("./handletable.cjs");
|
|
11
|
+
const range_1 = require("./range.cjs");
|
|
12
12
|
/**
|
|
13
13
|
* Used by PermutationVector to cache position -\> handle lookups.
|
|
14
14
|
*
|
|
15
15
|
* Perf: Possibly, this should eventually be inlined into PermutationVector itself, but
|
|
16
|
-
*
|
|
16
|
+
* so far there's no measurable perf penalty for being a separate object (node 12 x64)
|
|
17
17
|
*/
|
|
18
18
|
class HandleCache {
|
|
19
19
|
constructor(vector) {
|
|
@@ -43,16 +43,14 @@ class HandleCache {
|
|
|
43
43
|
// Perf: A cache hit implies that 'position' was in bounds. Therefore, we can defer
|
|
44
44
|
// checking that 'position' is in bounds until 'cacheMiss(..)'. This yields an
|
|
45
45
|
// ~40% speedup when the position is in the cache (node v12 x64).
|
|
46
|
-
return index < this.handles.length
|
|
47
|
-
? this.handles[index]
|
|
48
|
-
: this.cacheMiss(position);
|
|
46
|
+
return index < this.handles.length ? this.handles[index] : this.cacheMiss(position);
|
|
49
47
|
}
|
|
50
48
|
/** Update the cache when a handle has been allocated for a given position. */
|
|
51
49
|
addHandle(position, handle) {
|
|
52
|
-
(0,
|
|
50
|
+
(0, core_utils_1.assert)((0, handletable_1.isHandleValid)(handle), 0x017 /* "Trying to add invalid handle!" */);
|
|
53
51
|
const index = this.getIndex(position);
|
|
54
52
|
if (index < this.handles.length) {
|
|
55
|
-
(0,
|
|
53
|
+
(0, core_utils_1.assert)(!(0, handletable_1.isHandleValid)(this.handles[index]), 0x018 /* "Trying to insert handle into position with already valid handle!" */);
|
|
56
54
|
this.handles[index] = handle;
|
|
57
55
|
}
|
|
58
56
|
}
|
|
@@ -110,4 +108,4 @@ class HandleCache {
|
|
|
110
108
|
}
|
|
111
109
|
}
|
|
112
110
|
exports.HandleCache = HandleCache;
|
|
113
|
-
//# sourceMappingURL=handlecache.
|
|
111
|
+
//# sourceMappingURL=handlecache.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handlecache.cjs","sourceRoot":"","sources":["../src/handlecache.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\n/* eslint-disable no-bitwise */\n\nimport { assert } from \"@fluidframework/core-utils\";\nimport { IVectorConsumer } from \"@tiny-calc/nano\";\nimport { Handle, isHandleValid } from \"./handletable\";\nimport { PermutationVector, PermutationSegment } from \"./permutationvector\";\nimport { ensureRange } from \"./range\";\n\n/**\n * Used by PermutationVector to cache position -\\> handle lookups.\n *\n * Perf: Possibly, this should eventually be inlined into PermutationVector itself, but\n * so far there's no measurable perf penalty for being a separate object (node 12 x64)\n */\nexport class HandleCache implements IVectorConsumer<Handle> {\n\tprivate handles: Handle[] = [];\n\tprivate start = 0;\n\n\tconstructor(public readonly vector: PermutationVector) {}\n\n\t/**\n\t * Returns the index of the given position in the 'handles' array as a Uint32.\n\t * (If the position is not in the array, returns an integer greater than 'handles.length').\n\t */\n\tprivate getIndex(position: number) {\n\t\treturn (position - this.start) >>> 0;\n\t}\n\n\t/**\n\t * Returns the handle currently assigned to the given 'position' (if any). Check\n\t * the result with 'isValidHandle(..)' to see if a handle has been allocated for\n\t * the given position.\n\t *\n\t * Throws a 'RangeError' if the provided 'position' is out-of-bounds wrt. the\n\t * PermutationVector's length.\n\t */\n\tpublic getHandle(position: number) {\n\t\tconst index = this.getIndex(position);\n\n\t\t// Perf: To encourage inlining, handling of the 'cacheMiss(..)' case has been extracted\n\t\t// to a separate method.\n\n\t\t// Perf: A cache hit implies that 'position' was in bounds. Therefore, we can defer\n\t\t// checking that 'position' is in bounds until 'cacheMiss(..)'. This yields an\n\t\t// ~40% speedup when the position is in the cache (node v12 x64).\n\n\t\treturn index < this.handles.length ? this.handles[index] : this.cacheMiss(position);\n\t}\n\n\t/** Update the cache when a handle has been allocated for a given position. */\n\tpublic addHandle(position: number, handle: Handle) {\n\t\tassert(isHandleValid(handle), 0x017 /* \"Trying to add invalid handle!\" */);\n\n\t\tconst index = this.getIndex(position);\n\t\tif (index < this.handles.length) {\n\t\t\tassert(\n\t\t\t\t!isHandleValid(this.handles[index]),\n\t\t\t\t0x018 /* \"Trying to insert handle into position with already valid handle!\" */,\n\t\t\t);\n\t\t\tthis.handles[index] = handle;\n\t\t}\n\t}\n\n\t/** Used by 'CacheMiss()' to retrieve handles for a range of positions. */\n\tprivate getHandles(start: number, end: number) {\n\t\t// TODO: This can be accelerated substantially using 'walkSegments()'. The only catch\n\t\t// is that\n\n\t\tconst handles: Handle[] = [];\n\t\tconst { vector } = this;\n\n\t\tfor (let pos = start; pos < end; pos++) {\n\t\t\tconst { segment, offset } = vector.getContainingSegment(pos);\n\t\t\tconst asPerm = segment as PermutationSegment;\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\t\thandles.push(asPerm.start + offset!);\n\t\t}\n\n\t\treturn handles;\n\t}\n\n\tprivate cacheMiss(position: number) {\n\t\t// Coercing 'position' to an Uint32 allows us to handle a negative 'position' value\n\t\t// with the same logic that handles 'position' >= length.\n\t\tconst _position = position >>> 0;\n\n\t\t// TODO: To bound memory usage, there should be a limit on the maximum size of\n\t\t// handle[].\n\n\t\t// TODO: To reduce MergeTree lookups, this code should opportunistically grow\n\t\t// the cache to the next MergeTree segment boundary (within the limits of\n\t\t// the handle cache).\n\n\t\tif (_position < this.start) {\n\t\t\tthis.handles = this.getHandles(_position, this.start).concat(this.handles);\n\t\t\tthis.start = _position;\n\t\t\treturn this.handles[0];\n\t\t} else {\n\t\t\tensureRange(_position, this.vector.getLength());\n\n\t\t\tthis.handles = this.handles.concat(\n\t\t\t\tthis.getHandles(this.start + this.handles.length, _position + 1),\n\t\t\t);\n\t\t\treturn this.handles[this.handles.length - 1];\n\t\t}\n\t}\n\n\t// #region IVectorConsumer\n\n\titemsChanged(start: number, removedCount: number, insertedCount: number): void {\n\t\t// If positions were inserted/removed, our current policy is to trim the array\n\t\t// at the beginning of the invalidate range and lazily repopulate the handles\n\t\t// on demand.\n\t\t//\n\t\t// Some alternatives to consider that preserve the previously cached handles\n\t\t// that are still valid:\n\t\t//\n\t\t// * Eagerly populate the 'handles[]' with the newly insert values (currently guaranteed\n\t\t// to be Handle.unallocated, so we don't even need to look them up.)\n\t\t//\n\t\t// * Use a sentinel value or other mechanism to allow \"holes\" in the cache.\n\n\t\tconst index = this.getIndex(start);\n\t\tif (index < this.handles.length) {\n\t\t\tthis.handles.length = index;\n\t\t}\n\t}\n\n\t// #endregion IVectorConsumer\n}\n"]}
|
package/dist/handlecache.d.ts
CHANGED
|
@@ -9,7 +9,7 @@ import { PermutationVector } from "./permutationvector";
|
|
|
9
9
|
* Used by PermutationVector to cache position -\> handle lookups.
|
|
10
10
|
*
|
|
11
11
|
* Perf: Possibly, this should eventually be inlined into PermutationVector itself, but
|
|
12
|
-
*
|
|
12
|
+
* so far there's no measurable perf penalty for being a separate object (node 12 x64)
|
|
13
13
|
*/
|
|
14
14
|
export declare class HandleCache implements IVectorConsumer<Handle> {
|
|
15
15
|
readonly vector: PermutationVector;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handlecache.d.ts","sourceRoot":"","sources":["../src/handlecache.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,MAAM,EAAiB,MAAM,eAAe,CAAC;AACtD,OAAO,EAAE,iBAAiB,EAAsB,MAAM,qBAAqB,CAAC;AAG5E;;;;;GAKG;AACH,qBAAa,WAAY,YAAW,eAAe,CAAC,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"handlecache.d.ts","sourceRoot":"","sources":["../src/handlecache.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,MAAM,EAAiB,MAAM,eAAe,CAAC;AACtD,OAAO,EAAE,iBAAiB,EAAsB,MAAM,qBAAqB,CAAC;AAG5E;;;;;GAKG;AACH,qBAAa,WAAY,YAAW,eAAe,CAAC,MAAM,CAAC;aAI9B,MAAM,EAAE,iBAAiB;IAHrD,OAAO,CAAC,OAAO,CAAgB;IAC/B,OAAO,CAAC,KAAK,CAAK;gBAEU,MAAM,EAAE,iBAAiB;IAErD;;;OAGG;IACH,OAAO,CAAC,QAAQ;IAIhB;;;;;;;OAOG;IACI,SAAS,CAAC,QAAQ,EAAE,MAAM;IAajC,8EAA8E;IACvE,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;IAajD,0EAA0E;IAC1E,OAAO,CAAC,UAAU;IAiBlB,OAAO,CAAC,SAAS;IA4BjB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,IAAI;CAoB9E"}
|