@audiotool/nexus 0.0.8 → 0.0.10
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/dist/api.js +2 -2
- package/dist/{audiotool-api-BeiEe46q.js → audiotool-api-D9u-oGp3.js} +191 -184
- package/dist/document/backend/create-wasm-document-state.d.ts +11 -0
- package/dist/document/backend/document-service/connection/index.d.ts +37 -0
- package/dist/document/backend/document-service/connection/ping-notifier.d.ts +20 -0
- package/dist/document/backend/document-service/connection/transaction-receiver.d.ts +26 -0
- package/dist/document/backend/document-service/connection/transaction-receiver.test.d.ts +1 -0
- package/dist/document/backend/document-service/connection/transaction-sender.d.ts +17 -0
- package/dist/document/backend/document-service/connection/transaction-sender.test.d.ts +1 -0
- package/dist/document/backend/document-service/consolidator.d.ts +2 -1
- package/dist/document/backend/document-service/gateway.d.ts +18 -32
- package/dist/document/backend/gateway.d.ts +22 -2
- package/dist/document/backend/validator.d.ts +2 -0
- package/dist/document/document.d.ts +24 -15
- package/dist/document/event-manager.d.ts +5 -0
- package/dist/document/mock/mock-document-state.d.ts +1 -0
- package/dist/document.js +1 -1
- package/dist/{get-schema-location-details-BSMUliFD.js → get-schema-location-details-CI3Fi5PK.js} +1 -1
- package/dist/{observable-notifier-value-pw47I_2-.js → hash-map-CMrPM1s6.js} +87 -88
- package/dist/index.js +1117 -1045
- package/dist/lang-K-8hAzE4.js +40 -0
- package/dist/login-status.d.ts +1 -2
- package/dist/synced-document.d.ts +19 -1
- package/dist/utils/combine-notifiers.d.ts +1 -1
- package/dist/utils/grpc/retrying-client.d.ts +2 -0
- package/dist/utils/lang.d.ts +17 -8
- package/dist/utils.js +3 -3
- package/package.json +2 -1
- package/dist/document/backend/document-service/wrapper/buffered-sender.d.ts +0 -29
- package/dist/document/backend/document-service/wrapper/create-ping-loop.d.ts +0 -8
- package/dist/document/backend/document-service/wrapper/create-receive-next-transaction-fn.d.ts +0 -15
- package/dist/document/backend/document-service/wrapper/wrapper.d.ts +0 -41
- package/dist/document/init-collab-gateway.d.ts +0 -6
- package/dist/lang-KJQpoj7q.js +0 -13
- /package/dist/{document/backend/document-service/wrapper/buffered-sender.test.d.ts → audiotool-client.test.d.ts} +0 -0
- /package/dist/document/backend/document-service/{wrapper/wrapper.test.d.ts → connection/ping-notifier.test.d.ts} +0 -0
|
@@ -12,6 +12,8 @@ export type WasmDocumentState = {
|
|
|
12
12
|
* * an error string if the transaction is invalid
|
|
13
13
|
*/
|
|
14
14
|
applyTransaction: (transaction: Transaction) => Transaction | string;
|
|
15
|
+
/** Causes {@link applyTransaction} to throw. Used to clean up memory in the wasm. */
|
|
16
|
+
terminate(): void;
|
|
15
17
|
};
|
|
16
18
|
/** Type of object returned by the wasm module if an error happens. */
|
|
17
19
|
type WasmError = {
|
|
@@ -42,4 +44,13 @@ declare global {
|
|
|
42
44
|
} | undefined;
|
|
43
45
|
var createDocumentState: (() => WasmState) | undefined;
|
|
44
46
|
}
|
|
47
|
+
/**
|
|
48
|
+
* @internal
|
|
49
|
+
*
|
|
50
|
+
* For debugging - tracks how many documents are currently open in wasm but not yet closed.
|
|
51
|
+
*
|
|
52
|
+
* This can be used to assert that all documents have been terminated when a nexus document is terminated.
|
|
53
|
+
* This is important because the wasm memory won't be freed on its own if it's not referenced.
|
|
54
|
+
*/
|
|
55
|
+
export declare let DEBUG_totalOpenWasmDocuments: number;
|
|
45
56
|
export {};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { DocumentService } from '../../../../gen/audiotool/document/v1/document_service_connect';
|
|
2
|
+
import { Transaction } from '../../../../gen/audiotool/document/v1/document_service_pb';
|
|
3
|
+
import { RetryingClient } from '../../../../utils/grpc/retrying-client';
|
|
4
|
+
import { ObservableValue } from '../../../../utils/observable-notifier-value';
|
|
5
|
+
|
|
6
|
+
/** This object represents a connection to the document service. It's built from a document service client.
|
|
7
|
+
*
|
|
8
|
+
* While it isn't terminated, it will continuously ping the backend to check if the connection is still alive,
|
|
9
|
+
* and update the ping value.
|
|
10
|
+
*
|
|
11
|
+
* The parameter {@link connectionOk} turns to false if something goes wrong in a recoverable way.
|
|
12
|
+
* If something goes wrong in an unrecoverable way, the service connection will throw an error in a detached promise.
|
|
13
|
+
*
|
|
14
|
+
*/
|
|
15
|
+
export type DocumentServiceConnection = {
|
|
16
|
+
/** The stream of incoming transactions. The document is "loaded" when the first transaction is received.*/
|
|
17
|
+
receiveNextTransaction: AsyncIterable<Transaction, void, void>;
|
|
18
|
+
/** Send the next transaction to the backend, returns a string if the backend rejects it. */
|
|
19
|
+
sendNextTransaction: (t: Transaction) => Promise<string | undefined>;
|
|
20
|
+
/** The current ping to the backend. */
|
|
21
|
+
pingMs: ObservableValue<number>;
|
|
22
|
+
/**
|
|
23
|
+
* Turns to false if any of the three calls (send, receive, ping) fail in a recoverable way.
|
|
24
|
+
*/
|
|
25
|
+
connectionOk: ObservableValue<boolean>;
|
|
26
|
+
/** Terminate the connection. Has the following effect:
|
|
27
|
+
* * `receiveNextTransaction` is terminated
|
|
28
|
+
* * `sendNextTransaction` will throw an error
|
|
29
|
+
*
|
|
30
|
+
* Resolves once the last transaction has been sent.
|
|
31
|
+
*/
|
|
32
|
+
terminate: () => Promise<void>;
|
|
33
|
+
};
|
|
34
|
+
export declare const createDocumentServiceConnection: (documentService: RetryingClient<typeof DocumentService>, projectName: string, opts?: {
|
|
35
|
+
backoffMs?: number;
|
|
36
|
+
pingIntervalMs?: number;
|
|
37
|
+
}) => DocumentServiceConnection;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { DocumentService } from '../../../../gen/audiotool/document/v1/document_service_connect';
|
|
2
|
+
import { RetryingClient } from '../../../../utils/grpc/retrying-client';
|
|
3
|
+
import { Observable } from '../../../../utils/observable-notifier';
|
|
4
|
+
import { ObservableValue } from '../../../../utils/observable-notifier-value';
|
|
5
|
+
|
|
6
|
+
/** A ping notifier continuously pings the backend to check if the connection is still alive. */
|
|
7
|
+
export type PingNotifier = {
|
|
8
|
+
/** emits a true/false value every time a successful/failed ping is received. */
|
|
9
|
+
pingCallResults: Observable<boolean>;
|
|
10
|
+
/** true while ping call is not retrying */
|
|
11
|
+
connectionOk: ObservableValue<boolean>;
|
|
12
|
+
/** current ping to server, in milliseconds. Currently doesn't update if no ping response is received */
|
|
13
|
+
pingMs: ObservableValue<number>;
|
|
14
|
+
/** Immediately terminates the ping loop. */
|
|
15
|
+
terminate: () => void;
|
|
16
|
+
};
|
|
17
|
+
export declare const createPingNotifier: (documentService: Pick<RetryingClient<typeof DocumentService>, "ping">, projectName: string, opts?: {
|
|
18
|
+
pingIntervalMs?: number;
|
|
19
|
+
clientId?: string;
|
|
20
|
+
}) => PingNotifier;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { DocumentService } from '../../../../gen/audiotool/document/v1/document_service_connect';
|
|
2
|
+
import { Transaction } from '../../../../gen/audiotool/document/v1/document_service_pb';
|
|
3
|
+
import { RetryingClient } from '../../../../utils/grpc/retrying-client';
|
|
4
|
+
import { ObservableValue } from '../../../../utils/observable-notifier-value';
|
|
5
|
+
|
|
6
|
+
export type TransactionReceiver = {
|
|
7
|
+
/** Get the next transaction sent from the backend. On disconnect, just blocks until
|
|
8
|
+
* reconnection. Throws only if unrecoverable. The very first transaction will "load" the current document
|
|
9
|
+
* state, which might be empty if the document is new.
|
|
10
|
+
*/
|
|
11
|
+
nextTransactionIterator: AsyncIterable<Transaction, void, void>;
|
|
12
|
+
/**
|
|
13
|
+
* Stops internal logic, terminates the iterator. No effect on connectionOk.
|
|
14
|
+
*/
|
|
15
|
+
terminate(): void;
|
|
16
|
+
/** Trigger a recovery of the connection. This should be called if an issue is detected in the logic
|
|
17
|
+
* outside of the iterator (e.g. if the ping call fails), because the connection used internally
|
|
18
|
+
* in this object cannot reliably detect disconnects.
|
|
19
|
+
*/
|
|
20
|
+
reconnect(): void;
|
|
21
|
+
/** Turns to false while we're trying to reconnect. */
|
|
22
|
+
connectionOk: ObservableValue<boolean>;
|
|
23
|
+
};
|
|
24
|
+
export declare const createTransactionReceiver: (documentService: Pick<RetryingClient<typeof DocumentService>, "attach">, projectName: string, opts?: {
|
|
25
|
+
backoffMs?: number;
|
|
26
|
+
}) => TransactionReceiver;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { DocumentService } from '../../../../gen/audiotool/document/v1/document_service_connect';
|
|
2
|
+
import { Transaction } from '../../../../gen/audiotool/document/v1/document_service_pb';
|
|
3
|
+
import { RetryingClient } from '../../../../utils/grpc/retrying-client';
|
|
4
|
+
import { ObservableValue } from '../../../../utils/observable-notifier-value';
|
|
5
|
+
|
|
6
|
+
export type TransactionSender = {
|
|
7
|
+
sendNextTransaction: (t: Transaction) => Promise<string | undefined>;
|
|
8
|
+
/** Turns to false if sending is temporarily interrupted. */
|
|
9
|
+
connectionOk: ObservableValue<boolean>;
|
|
10
|
+
/** Terminate this sender. This will cause all sendNextTransaction calls
|
|
11
|
+
* to throw. The promise will resolve once the last transaction has been
|
|
12
|
+
* confirmed as received by the backend, and the sendNextTransaction
|
|
13
|
+
* methods of all pending transactions have been resolved.
|
|
14
|
+
*/
|
|
15
|
+
terminate: () => Promise<void>;
|
|
16
|
+
};
|
|
17
|
+
export declare const createTransactionSender: (documentService: Pick<RetryingClient<typeof DocumentService>, "applyTransactions">, projectName: string) => TransactionSender;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Transaction } from '../../../gen/audiotool/document/v1/document_service_pb';
|
|
2
2
|
import { WasmDocumentState } from '../create-wasm-document-state';
|
|
3
|
+
import { ReadonlyTransaction } from '../gateway';
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* This class can be used to "consolidate" two transaction histories in such a way that
|
|
@@ -28,5 +29,5 @@ export declare class NexusStateConsolidator {
|
|
|
28
29
|
/** new rejected transactions received from the document service. Must be a subset of `newOutgoing`. */
|
|
29
30
|
newReceivedRejected: Set<string>,
|
|
30
31
|
/** new locally created transactions */
|
|
31
|
-
newCreated: Transaction[]):
|
|
32
|
+
newCreated: Transaction[]): ReadonlyTransaction[];
|
|
32
33
|
}
|
|
@@ -1,36 +1,22 @@
|
|
|
1
|
-
import { Transaction } from '../../../gen/audiotool/document/v1/document_service_pb';
|
|
2
|
-
import { ObservableValue } from '../../../utils/observable-notifier-value';
|
|
3
1
|
import { NexusGateway } from '../gateway';
|
|
2
|
+
import { DocumentService } from '../../../gen/audiotool/document/v1/document_service_connect';
|
|
3
|
+
import { RetryingClient } from '../../../utils/grpc/retrying-client';
|
|
4
4
|
import { WasmDocumentState } from '../create-wasm-document-state';
|
|
5
|
-
import { DocumentServiceWrapper } from './wrapper/wrapper';
|
|
6
5
|
|
|
7
|
-
/**
|
|
8
|
-
* * reject transaction
|
|
9
|
-
* * reorder transactions
|
|
10
|
-
* * interleave transactions with transactions of other clients
|
|
6
|
+
/** Collab gateway returns a gateway that syncs with a document service.
|
|
11
7
|
*/
|
|
12
|
-
export declare
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
logOutgoingTransactions?: boolean;
|
|
28
|
-
logIncomingTransactions?: boolean;
|
|
29
|
-
logConsolidatedTransactions?: boolean;
|
|
30
|
-
logRejectedTransactions?: boolean;
|
|
31
|
-
});
|
|
32
|
-
/** Send a transaction to the document service. */
|
|
33
|
-
send(t: Transaction): void;
|
|
34
|
-
/** Receive new transactions from the backend, already consolidated with the local change history.*/
|
|
35
|
-
synchronize(): Transaction[];
|
|
36
|
-
}
|
|
8
|
+
export declare const createCollabGateway: (documentService: RetryingClient<typeof DocumentService>, state: WasmDocumentState, projectName: string, opts?: {
|
|
9
|
+
logOutgoingTransactions?: boolean;
|
|
10
|
+
logIncomingTransactions?: boolean;
|
|
11
|
+
logConsolidatedTransactions?: boolean;
|
|
12
|
+
logRejectedTransactions?: boolean;
|
|
13
|
+
}) => NexusGateway;
|
|
14
|
+
/** Statistics for debugging - global singleton for easy of access.
|
|
15
|
+
* Won't be correct if multiple gateways are created.
|
|
16
|
+
*/
|
|
17
|
+
export declare const debugStatistics: {
|
|
18
|
+
numReceivedCtr: number;
|
|
19
|
+
numConfirmedCtr: number;
|
|
20
|
+
numQueuedCtr: number;
|
|
21
|
+
numRejectedCtr: number;
|
|
22
|
+
};
|
|
@@ -1,6 +1,17 @@
|
|
|
1
|
-
import { Transaction } from '../../gen/audiotool/document/v1/document_service_pb';
|
|
1
|
+
import { Modification, Transaction } from '../../gen/audiotool/document/v1/document_service_pb';
|
|
2
2
|
import { ObservableValue } from '../../utils/observable-notifier-value';
|
|
3
3
|
|
|
4
|
+
/** A read only variant of a transaction that is returned by {@link NexusGateway.synchronize}.
|
|
5
|
+
*
|
|
6
|
+
* It's important that the gateway doesn't have to clone every transaction for performance reasons,
|
|
7
|
+
* but the returned transactions must also never be modified by the caller. This type
|
|
8
|
+
* allows us to enforce this.
|
|
9
|
+
*/
|
|
10
|
+
export type ReadonlyTransaction = {
|
|
11
|
+
readonly id: string;
|
|
12
|
+
readonly commitIndex: number;
|
|
13
|
+
readonly modifications: readonly Modification[];
|
|
14
|
+
};
|
|
4
15
|
/**
|
|
5
16
|
* This is the interface the {@link NexusDocument} uses to sync itself with
|
|
6
17
|
* a state from some "backend". This could be a server, local storage,
|
|
@@ -15,6 +26,8 @@ export interface NexusGateway {
|
|
|
15
26
|
*/
|
|
16
27
|
send(t: Transaction): void;
|
|
17
28
|
/** Fetch new transactions that should be immediately applied to the document to sync with upstream.
|
|
29
|
+
*
|
|
30
|
+
* The returned transactions MUST NOT be modified by the caller.
|
|
18
31
|
*
|
|
19
32
|
* This function must only be called after all local transactions created since the last call
|
|
20
33
|
* to {@link synchronize} have been sent with {@link send}.
|
|
@@ -29,9 +42,16 @@ export interface NexusGateway {
|
|
|
29
42
|
* one transaction. If the document state is empty, that transaction can be empty. The studio
|
|
30
43
|
* will show the loading spinner until the first transaction is received.
|
|
31
44
|
*/
|
|
32
|
-
synchronize():
|
|
45
|
+
synchronize(): ReadonlyTransaction[];
|
|
33
46
|
/** This becomes true when the gateway is blocked in some way from syncing with upstream state.
|
|
34
47
|
* The document should be locked in this case to prevent data loss.
|
|
35
48
|
*/
|
|
36
49
|
blocked: ObservableValue<boolean>;
|
|
50
|
+
/** Terminate the gateway. This will have the following effect:
|
|
51
|
+
* * `send` will throw
|
|
52
|
+
* * `synchronize` will return an empty array
|
|
53
|
+
*
|
|
54
|
+
* The promise will resolve once the last sent transaction has been confirmed as received by the backend.
|
|
55
|
+
*/
|
|
56
|
+
terminate(): Promise<void>;
|
|
37
57
|
}
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import { Modification, Transaction } from '../gen/audiotool/document/v1/document_service_pb';
|
|
2
|
-
import { EntityTypes } from '../gen/audiotool/document/v1/utils/types';
|
|
3
1
|
import { Notifier } from '../utils/observable-notifier';
|
|
4
|
-
import { NexusGateway } from './backend/gateway';
|
|
2
|
+
import { NexusGateway, ReadonlyTransaction } from './backend/gateway';
|
|
5
3
|
import { NexusValidator } from './backend/validator';
|
|
4
|
+
import { Modification, Transaction } from '../gen/audiotool/document/v1/document_service_pb';
|
|
6
5
|
import { EntityTypeKey } from './entity-utils';
|
|
7
6
|
import { NexusEventManager } from './event-manager';
|
|
8
7
|
import { EntityQuery } from './query/entity';
|
|
@@ -100,16 +99,6 @@ export declare class NexusDocument {
|
|
|
100
99
|
*/
|
|
101
100
|
actionId?: symbol;
|
|
102
101
|
}>;
|
|
103
|
-
/** Public field to query the entities in the document.
|
|
104
|
-
*
|
|
105
|
-
* @deprecated Don't use this field, as it can cause race conditions on the nexus document.
|
|
106
|
-
*
|
|
107
|
-
* Instead, use
|
|
108
|
-
* * for building a transaction: {@link TransactionBuilder.entities}
|
|
109
|
-
* * for other purposes, being aware of caveats: {@link NexusDocument.queryEntitiesWithoutLock}
|
|
110
|
-
*
|
|
111
|
-
*/
|
|
112
|
-
readonly entities: EntityQuery<keyof EntityTypes>;
|
|
113
102
|
/**
|
|
114
103
|
* This flag is set to true if {@link takeTransactions} is called. Before that, no transactions
|
|
115
104
|
* from the backend are processed, and no transactions are allowed to be created from the frontend.
|
|
@@ -139,7 +128,9 @@ export declare class NexusDocument {
|
|
|
139
128
|
* Note that every transaction by default is undoable, unless the flag in {@link TransactionOptions} is set to false.
|
|
140
129
|
* @returns: {@link TransactionBuilder}
|
|
141
130
|
*/
|
|
142
|
-
createTransaction(opts?: TransactionOptions
|
|
131
|
+
createTransaction(opts?: TransactionOptions,
|
|
132
|
+
/** @internal allows skipping of taking the transaction lock */
|
|
133
|
+
_takeTransactionLock?: boolean): Promise<TransactionBuilder>;
|
|
143
134
|
/**
|
|
144
135
|
* A helper method for small transactions.
|
|
145
136
|
*
|
|
@@ -169,15 +160,33 @@ export declare class NexusDocument {
|
|
|
169
160
|
takeTransactions(props?: {
|
|
170
161
|
validator?: NexusValidator;
|
|
171
162
|
gateway?: NexusGateway;
|
|
163
|
+
/** if a project template should be loaded on startup, pass a promise that resolves to the transaction */
|
|
164
|
+
templateTransaction?: Promise<Transaction>;
|
|
172
165
|
}): Promise<void>;
|
|
173
166
|
/** Apply a transaction that doesn't originate from this document. Yields to the browser
|
|
174
167
|
* scheduler every few modifications applied to make sure we don't block the main thread
|
|
175
168
|
* for too long for big transactions. Throws if the transaction lock isn't taken.
|
|
169
|
+
*
|
|
176
170
|
*/
|
|
177
|
-
|
|
171
|
+
_applyIncomingTransactions(ts: ReadonlyTransaction[],
|
|
172
|
+
/** @internal */
|
|
173
|
+
opts?: {
|
|
174
|
+
/** This can be false if the transaction lock is already held already when calling from the outside.
|
|
175
|
+
* The method will throw if takeTransactionLock is false and the lock is not held.
|
|
176
|
+
*/
|
|
177
|
+
_takeTransactionLock?: boolean;
|
|
178
|
+
}): Promise<void>;
|
|
178
179
|
/** For debugging purposes */
|
|
179
180
|
getStats(): {
|
|
180
181
|
entities: number;
|
|
181
182
|
references: number;
|
|
182
183
|
};
|
|
184
|
+
/** Stop the document from syncing. This will have the following effect:
|
|
185
|
+
* First, all pending `modify` and `createTransaction` calls will finish.
|
|
186
|
+
* The modifications they create will be synced with the backend, and the document is locked down.
|
|
187
|
+
*
|
|
188
|
+
* After this, calling `modify` or `createTransaction` will throw an error. The only property that
|
|
189
|
+
* can still be accessed is `queryEntities`. The document can be thrown away safely after this.
|
|
190
|
+
*/
|
|
191
|
+
terminate(): Promise<void>;
|
|
183
192
|
}
|
|
@@ -175,6 +175,11 @@ export declare class NexusEventManager {
|
|
|
175
175
|
from: NexusLocation) => void): Terminable;
|
|
176
176
|
/** @internal */
|
|
177
177
|
_dispatchStopPointingTo(to: NexusLocation, from: NexusLocation): void;
|
|
178
|
+
/**
|
|
179
|
+
* @internal
|
|
180
|
+
*
|
|
181
|
+
* Removes all event listeners.*/
|
|
182
|
+
_clear(): void;
|
|
178
183
|
/**
|
|
179
184
|
* @internal
|
|
180
185
|
* Some stats for debugging. Static for easy access. This method can get quite slow, 6.5ms measured
|
package/dist/document.js
CHANGED
|
@@ -3,16 +3,86 @@ var v = (i) => {
|
|
|
3
3
|
};
|
|
4
4
|
var M = (i, e, s) => e.has(i) || v("Cannot " + s);
|
|
5
5
|
var t = (i, e, s) => (M(i, e, "read from private field"), s ? s.call(i) : e.get(i)), h = (i, e, s) => e.has(i) ? v("Cannot add the same private member more than once") : e instanceof WeakSet ? e.add(i) : e.set(i, s), o = (i, e, s, r) => (M(i, e, "write to private field"), r ? r.call(i, s) : e.set(i, s), s);
|
|
6
|
-
var l
|
|
6
|
+
var l;
|
|
7
|
+
class A {
|
|
8
|
+
constructor() {
|
|
9
|
+
h(this, l, /* @__PURE__ */ new Set());
|
|
10
|
+
}
|
|
11
|
+
// A set allows us to remove while iterating
|
|
12
|
+
subscribe(e) {
|
|
13
|
+
return t(this, l).add(e), { terminate: () => t(this, l).delete(e) };
|
|
14
|
+
}
|
|
15
|
+
notify(e) {
|
|
16
|
+
t(this, l).forEach((s) => s(e));
|
|
17
|
+
}
|
|
18
|
+
terminate() {
|
|
19
|
+
t(this, l).clear();
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
l = new WeakMap();
|
|
23
|
+
var f, c, g;
|
|
7
24
|
class E {
|
|
25
|
+
constructor(e) {
|
|
26
|
+
h(this, f, new A());
|
|
27
|
+
h(this, c);
|
|
28
|
+
h(this, g, V(t(this, f)));
|
|
29
|
+
o(this, c, e);
|
|
30
|
+
}
|
|
31
|
+
getValue() {
|
|
32
|
+
return t(this, g).call(this), t(this, c);
|
|
33
|
+
}
|
|
34
|
+
setValue(e) {
|
|
35
|
+
t(this, c) !== e && (o(this, c, e), t(this, f).notify(e));
|
|
36
|
+
}
|
|
37
|
+
subscribe(e, s = !1) {
|
|
38
|
+
return s && e(t(this, c)), t(this, f).subscribe(e);
|
|
39
|
+
}
|
|
40
|
+
terminate() {
|
|
41
|
+
t(this, f).terminate();
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
f = new WeakMap(), c = new WeakMap(), g = new WeakMap();
|
|
45
|
+
var u, y, n;
|
|
46
|
+
class N {
|
|
47
|
+
constructor(e) {
|
|
48
|
+
h(this, u, new A());
|
|
49
|
+
h(this, y, V(t(this, u)));
|
|
50
|
+
h(this, n);
|
|
51
|
+
o(this, n, e ?? /* @__PURE__ */ new Map());
|
|
52
|
+
}
|
|
53
|
+
/** Subscribe to updates of the set */
|
|
54
|
+
subscribe(e, s = !1) {
|
|
55
|
+
return s && e(t(this, n)), t(this, u).subscribe(() => e(t(this, n)));
|
|
56
|
+
}
|
|
57
|
+
/** Get the underlying map. Readonly because changing it won't trigger updates. */
|
|
58
|
+
getValue() {
|
|
59
|
+
return t(this, y).call(this), t(this, n);
|
|
60
|
+
}
|
|
61
|
+
set(e, s) {
|
|
62
|
+
return t(this, n).set(e, s), t(this, u).notify(), this;
|
|
63
|
+
}
|
|
64
|
+
delete(e) {
|
|
65
|
+
const s = t(this, n).delete(e);
|
|
66
|
+
return s && t(this, u).notify(), s;
|
|
67
|
+
}
|
|
68
|
+
clear() {
|
|
69
|
+
const e = t(this, n).size > 0;
|
|
70
|
+
t(this, n).clear(), e && t(this, u).notify();
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
u = new WeakMap(), y = new WeakMap(), n = new WeakMap();
|
|
74
|
+
const V = (i) => () => {
|
|
75
|
+
};
|
|
76
|
+
var d, m, b;
|
|
77
|
+
class T {
|
|
8
78
|
/** if `warnAfterMs` is set, the lock will emit a warning if a call to `lock.acquire()
|
|
9
79
|
* tok more than `warnAfterMs` milliseconds.
|
|
10
80
|
*/
|
|
11
81
|
constructor(e) {
|
|
12
|
-
h(this,
|
|
82
|
+
h(this, d, !1);
|
|
13
83
|
h(this, m, []);
|
|
14
|
-
h(this,
|
|
15
|
-
o(this,
|
|
84
|
+
h(this, b);
|
|
85
|
+
o(this, b, (e == null ? void 0 : e.warnAfterMs) ?? void 0);
|
|
16
86
|
}
|
|
17
87
|
/**
|
|
18
88
|
* Wait until no other async thread holds a lock, then returns a lock.
|
|
@@ -36,17 +106,17 @@ class E {
|
|
|
36
106
|
async acquire() {
|
|
37
107
|
let e = () => {
|
|
38
108
|
};
|
|
39
|
-
t(this,
|
|
40
|
-
t(this,
|
|
41
|
-
`Waited for lock.acquire() for more than ${t(this,
|
|
42
|
-
)), t(this,
|
|
109
|
+
t(this, b) !== void 0 && (e = k(
|
|
110
|
+
t(this, b),
|
|
111
|
+
`Waited for lock.acquire() for more than ${t(this, b)} ms, deadlock?`
|
|
112
|
+
)), t(this, d) && await new Promise((r) => t(this, m).push(r)), e(), o(this, d, !0);
|
|
43
113
|
let s = !1;
|
|
44
114
|
return {
|
|
45
115
|
release: () => {
|
|
46
116
|
var r;
|
|
47
117
|
if (s)
|
|
48
118
|
throw new Error("Lock already released");
|
|
49
|
-
s = !0, t(this, m).length > 0 ? (r = t(this, m).shift()) == null || r() : o(this,
|
|
119
|
+
s = !0, t(this, m).length > 0 ? (r = t(this, m).shift()) == null || r() : o(this, d, !1);
|
|
50
120
|
}
|
|
51
121
|
};
|
|
52
122
|
}
|
|
@@ -88,36 +158,18 @@ class E {
|
|
|
88
158
|
* without `await`ing the `lock.acquire()`.
|
|
89
159
|
*/
|
|
90
160
|
get locked() {
|
|
91
|
-
return t(this,
|
|
161
|
+
return t(this, d);
|
|
92
162
|
}
|
|
93
163
|
}
|
|
94
|
-
|
|
164
|
+
d = new WeakMap(), m = new WeakMap(), b = new WeakMap();
|
|
95
165
|
const k = (i, e) => {
|
|
96
166
|
const s = setTimeout(() => {
|
|
97
167
|
console.warn(e), console.trace("Waited here:");
|
|
98
168
|
}, i);
|
|
99
169
|
return () => clearTimeout(s);
|
|
100
|
-
};
|
|
101
|
-
var d;
|
|
102
|
-
class A {
|
|
103
|
-
constructor() {
|
|
104
|
-
h(this, d, /* @__PURE__ */ new Set());
|
|
105
|
-
}
|
|
106
|
-
// A set allows us to remove while iterating
|
|
107
|
-
subscribe(e) {
|
|
108
|
-
return t(this, d).add(e), { terminate: () => t(this, d).delete(e) };
|
|
109
|
-
}
|
|
110
|
-
notify(e) {
|
|
111
|
-
t(this, d).forEach((s) => s(e));
|
|
112
|
-
}
|
|
113
|
-
terminate() {
|
|
114
|
-
t(this, d).clear();
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
d = new WeakMap();
|
|
118
|
-
const w = Symbol();
|
|
170
|
+
}, w = Symbol();
|
|
119
171
|
var a;
|
|
120
|
-
class
|
|
172
|
+
class _ {
|
|
121
173
|
constructor() {
|
|
122
174
|
/** Maps the hash of a key to both key and value */
|
|
123
175
|
h(this, a, /* @__PURE__ */ new Map());
|
|
@@ -165,64 +217,11 @@ class N {
|
|
|
165
217
|
}
|
|
166
218
|
}
|
|
167
219
|
a = new WeakMap();
|
|
168
|
-
var b, c, g;
|
|
169
|
-
class T {
|
|
170
|
-
constructor(e) {
|
|
171
|
-
h(this, b, new A());
|
|
172
|
-
h(this, c);
|
|
173
|
-
h(this, g, V(t(this, b)));
|
|
174
|
-
o(this, c, e);
|
|
175
|
-
}
|
|
176
|
-
getValue() {
|
|
177
|
-
return t(this, g).call(this), t(this, c);
|
|
178
|
-
}
|
|
179
|
-
setValue(e) {
|
|
180
|
-
t(this, c) !== e && (o(this, c, e), t(this, b).notify(e));
|
|
181
|
-
}
|
|
182
|
-
subscribe(e, s = !1) {
|
|
183
|
-
return s && e(t(this, c)), t(this, b).subscribe(e);
|
|
184
|
-
}
|
|
185
|
-
terminate() {
|
|
186
|
-
t(this, b).terminate();
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
b = new WeakMap(), c = new WeakMap(), g = new WeakMap();
|
|
190
|
-
var u, y, n;
|
|
191
|
-
class _ {
|
|
192
|
-
constructor(e) {
|
|
193
|
-
h(this, u, new A());
|
|
194
|
-
h(this, y, V(t(this, u)));
|
|
195
|
-
h(this, n);
|
|
196
|
-
o(this, n, e ?? /* @__PURE__ */ new Map());
|
|
197
|
-
}
|
|
198
|
-
/** Subscribe to updates of the set */
|
|
199
|
-
subscribe(e, s = !1) {
|
|
200
|
-
return s && e(t(this, n)), t(this, u).subscribe(() => e(t(this, n)));
|
|
201
|
-
}
|
|
202
|
-
/** Get the underlying map. Readonly because changing it won't trigger updates. */
|
|
203
|
-
getValue() {
|
|
204
|
-
return t(this, y).call(this), t(this, n);
|
|
205
|
-
}
|
|
206
|
-
set(e, s) {
|
|
207
|
-
return t(this, n).set(e, s), t(this, u).notify(), this;
|
|
208
|
-
}
|
|
209
|
-
delete(e) {
|
|
210
|
-
const s = t(this, n).delete(e);
|
|
211
|
-
return s && t(this, u).notify(), s;
|
|
212
|
-
}
|
|
213
|
-
clear() {
|
|
214
|
-
const e = t(this, n).size > 0;
|
|
215
|
-
t(this, n).clear(), e && t(this, u).notify();
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
u = new WeakMap(), y = new WeakMap(), n = new WeakMap();
|
|
219
|
-
const V = (i) => () => {
|
|
220
|
-
};
|
|
221
220
|
export {
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
221
|
+
T as A,
|
|
222
|
+
_ as H,
|
|
223
|
+
N as M,
|
|
225
224
|
A as N,
|
|
226
|
-
|
|
225
|
+
E as V,
|
|
227
226
|
w as h
|
|
228
227
|
};
|