@flighthq/ipc 0.3.1-next.975.01aea94 → 0.4.0-edge.1908.751021c
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/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/ipc.d.ts +5 -1
- package/dist/ipc.d.ts.map +1 -1
- package/dist/ipc.js +62 -30
- package/dist/ipc.js.map +1 -1
- package/package.json +3 -3
- package/src/ipc.test.ts +99 -19
package/dist/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { createIpcChannel, enableIpcSignals, getIpcListenerCount, getIpcSignals, invokeIpc, invokeIpcWithTimeout, onIpcInvoke, onIpcMessage, onIpcMessageEvent, onceIpcMessage, removeAllIpcListeners, sendIpcMessage, sendIpcMessageTo, } from './contract';
|
|
1
|
+
export { createIpcChannel, enableIpcSignals, explainIpcBackend, getIpcListenerCount, getIpcSignals, invokeIpc, invokeIpcWithTimeout, onIpcInvoke, onIpcMessage, onIpcMessageEvent, onceIpcMessage, removeAllIpcListeners, sendIpcMessage, sendIpcMessageTo, } from './contract';
|
|
2
2
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,mBAAmB,EACnB,aAAa,EACb,SAAS,EACT,oBAAoB,EACpB,WAAW,EACX,YAAY,EACZ,iBAAiB,EACjB,cAAc,EACd,qBAAqB,EACrB,cAAc,EACd,gBAAgB,GACjB,MAAM,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,iBAAiB,EACjB,mBAAmB,EACnB,aAAa,EACb,SAAS,EACT,oBAAoB,EACpB,WAAW,EACX,YAAY,EACZ,iBAAiB,EACjB,cAAc,EACd,qBAAqB,EACrB,cAAc,EACd,gBAAgB,GACjB,MAAM,YAAY,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { createIpcChannel, enableIpcSignals, getIpcListenerCount, getIpcSignals, invokeIpc, invokeIpcWithTimeout, onIpcInvoke, onIpcMessage, onIpcMessageEvent, onceIpcMessage, removeAllIpcListeners, sendIpcMessage, sendIpcMessageTo, } from './contract';
|
|
1
|
+
export { createIpcChannel, enableIpcSignals, explainIpcBackend, getIpcListenerCount, getIpcSignals, invokeIpc, invokeIpcWithTimeout, onIpcInvoke, onIpcMessage, onIpcMessageEvent, onceIpcMessage, removeAllIpcListeners, sendIpcMessage, sendIpcMessageTo, } from './contract';
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,mBAAmB,EACnB,aAAa,EACb,SAAS,EACT,oBAAoB,EACpB,WAAW,EACX,YAAY,EACZ,iBAAiB,EACjB,cAAc,EACd,qBAAqB,EACrB,cAAc,EACd,gBAAgB,GACjB,MAAM,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,iBAAiB,EACjB,mBAAmB,EACnB,aAAa,EACb,SAAS,EACT,oBAAoB,EACpB,WAAW,EACX,YAAY,EACZ,iBAAiB,EACjB,cAAc,EACd,qBAAqB,EACrB,cAAc,EACd,gBAAgB,GACjB,MAAM,YAAY,CAAC"}
|
package/dist/ipc.d.ts
CHANGED
|
@@ -1,18 +1,22 @@
|
|
|
1
|
+
import type { BackendExplanation } from '@flighthq/types/contract';
|
|
1
2
|
import type { IpcBackend, IpcChannel, IpcMessageEvent, IpcSignals, IpcTarget } from '@flighthq/types/contract';
|
|
2
3
|
export declare function createIpcChannel(name: string): IpcChannel;
|
|
3
|
-
export declare function createWebIpcBackend(): IpcBackend;
|
|
4
4
|
export declare function enableIpcSignals(): IpcSignals;
|
|
5
|
+
export declare function explainIpcBackend(): BackendExplanation;
|
|
5
6
|
export declare function getIpcBackend(): IpcBackend;
|
|
6
7
|
export declare function getIpcListenerCount(channel: string | Readonly<IpcChannel>): number;
|
|
7
8
|
export declare function getIpcSignals(): Readonly<IpcSignals> | null;
|
|
8
9
|
export declare function hasIpcBackend(): boolean;
|
|
10
|
+
export declare function installIpcHostBackend(backend: IpcBackend): void;
|
|
9
11
|
export declare function invokeIpc(channel: string | Readonly<IpcChannel>, ...args: readonly unknown[]): Promise<unknown>;
|
|
10
12
|
export declare function invokeIpcWithTimeout(channel: string | Readonly<IpcChannel>, timeoutMs: number, ...args: readonly unknown[]): Promise<unknown>;
|
|
13
|
+
export declare function observeIpcHostResult(operation: string, succeeded: boolean): void;
|
|
11
14
|
export declare function onceIpcMessage(channel: string | Readonly<IpcChannel>, listener: (...args: readonly unknown[]) => void): () => void;
|
|
12
15
|
export declare function onIpcInvoke(channel: string | Readonly<IpcChannel>, handler: (...args: readonly unknown[]) => unknown | Promise<unknown>): () => void;
|
|
13
16
|
export declare function onIpcMessage(channel: string | Readonly<IpcChannel>, listener: (...args: readonly unknown[]) => void): () => void;
|
|
14
17
|
export declare function onIpcMessageEvent(channel: string | Readonly<IpcChannel>, listener: (event: Readonly<IpcMessageEvent>) => void): () => void;
|
|
15
18
|
export declare function removeAllIpcListeners(channel?: string | Readonly<IpcChannel>): void;
|
|
19
|
+
export declare function resetIpcBackendForTest(): void;
|
|
16
20
|
export declare function sendIpcMessage(channel: string | Readonly<IpcChannel>, ...args: readonly unknown[]): void;
|
|
17
21
|
export declare function sendIpcMessageTo(target: Readonly<IpcTarget>, channel: string | Readonly<IpcChannel>, ...args: readonly unknown[]): void;
|
|
18
22
|
export declare function setIpcBackend(backend: IpcBackend | null): void;
|
package/dist/ipc.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ipc.d.ts","sourceRoot":"","sources":["../src/ipc.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,UAAU,EAEV,UAAU,EACV,eAAe,EACf,UAAU,EACV,SAAS,EACV,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"ipc.d.ts","sourceRoot":"","sources":["../src/ipc.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AACnE,OAAO,KAAK,EACV,UAAU,EAEV,UAAU,EACV,eAAe,EACf,UAAU,EACV,SAAS,EACV,MAAM,0BAA0B,CAAC;AAkClC,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,CAEzD;AAKD,wBAAgB,gBAAgB,IAAI,UAAU,CAQ7C;AAGD,wBAAgB,iBAAiB,IAAI,kBAAkB,CAatD;AAGD,wBAAgB,aAAa,IAAI,UAAU,CAE1C;AAGD,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,QAAQ,CAAC,UAAU,CAAC,GAAG,MAAM,CAGlF;AAGD,wBAAgB,aAAa,IAAI,QAAQ,CAAC,UAAU,CAAC,GAAG,IAAI,CAE3D;AAGD,wBAAgB,aAAa,IAAI,OAAO,CAEvC;AAID,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,UAAU,GAAG,IAAI,CAM/D;AAID,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,QAAQ,CAAC,UAAU,CAAC,EAAE,GAAG,IAAI,EAAE,SAAS,OAAO,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAE/G;AAID,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,MAAM,GAAG,QAAQ,CAAC,UAAU,CAAC,EACtC,SAAS,EAAE,MAAM,EACjB,GAAG,IAAI,EAAE,SAAS,OAAO,EAAE,GAC1B,OAAO,CAAC,OAAO,CAAC,CAYlB;AAGD,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,GAAG,IAAI,CAKhF;AAID,wBAAgB,cAAc,CAC5B,OAAO,EAAE,MAAM,GAAG,QAAQ,CAAC,UAAU,CAAC,EACtC,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,SAAS,OAAO,EAAE,KAAK,IAAI,GAC9C,MAAM,IAAI,CAOZ;AAKD,wBAAgB,WAAW,CACzB,OAAO,EAAE,MAAM,GAAG,QAAQ,CAAC,UAAU,CAAC,EACtC,OAAO,EAAE,CAAC,GAAG,IAAI,EAAE,SAAS,OAAO,EAAE,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,GACnE,MAAM,IAAI,CAIZ;AAID,wBAAgB,YAAY,CAC1B,OAAO,EAAE,MAAM,GAAG,QAAQ,CAAC,UAAU,CAAC,EACtC,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,SAAS,OAAO,EAAE,KAAK,IAAI,GAC9C,MAAM,IAAI,CAgBZ;AAID,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,MAAM,GAAG,QAAQ,CAAC,UAAU,CAAC,EACtC,QAAQ,EAAE,CAAC,KAAK,EAAE,QAAQ,CAAC,eAAe,CAAC,KAAK,IAAI,GACnD,MAAM,IAAI,CAyBZ;AAGD,wBAAgB,qBAAqB,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC,UAAU,CAAC,GAAG,IAAI,CAYnF;AAGD,wBAAgB,sBAAsB,IAAI,IAAI,CAK7C;AAGD,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,QAAQ,CAAC,UAAU,CAAC,EAAE,GAAG,IAAI,EAAE,SAAS,OAAO,EAAE,GAAG,IAAI,CAExG;AAID,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,QAAQ,CAAC,SAAS,CAAC,EAC3B,OAAO,EAAE,MAAM,GAAG,QAAQ,CAAC,UAAU,CAAC,EACtC,GAAG,IAAI,EAAE,SAAS,OAAO,EAAE,GAC1B,IAAI,CAEN;AAGD,wBAAgB,aAAa,CAAC,OAAO,EAAE,UAAU,GAAG,IAAI,GAAG,IAAI,CAG9D"}
|
package/dist/ipc.js
CHANGED
|
@@ -4,7 +4,6 @@ import { IpcTimeoutError } from '@flighthq/types/contract';
|
|
|
4
4
|
function resolveChannel(channel) {
|
|
5
5
|
return typeof channel === 'string' ? channel : channel.name;
|
|
6
6
|
}
|
|
7
|
-
// ---- Bronze: listener registry for once/removeAll/count ----
|
|
8
7
|
// Package-local listener tracking, keyed by channel name. Used by onceIpcMessage,
|
|
9
8
|
// removeAllIpcListeners, and getIpcListenerCount. Each entry is the unsubscribe thunk
|
|
10
9
|
// returned by the backend, associated with a channel string.
|
|
@@ -25,30 +24,12 @@ function _untrackListener(channel, unsubscribe) {
|
|
|
25
24
|
_listeners.delete(channel);
|
|
26
25
|
}
|
|
27
26
|
}
|
|
28
|
-
// ---- IpcSignals (Silver opt-in) ----
|
|
29
27
|
let _ipcSignals = null;
|
|
30
|
-
// ---- Core backend ----
|
|
31
28
|
// Creates a typed channel descriptor. Functions that accept a channel string also accept an
|
|
32
29
|
// IpcChannel, so a feature can publish its channel constants once and get a single grep target.
|
|
33
30
|
export function createIpcChannel(name) {
|
|
34
31
|
return { name };
|
|
35
32
|
}
|
|
36
|
-
// Builds the default web backend. There is no main process on web, so send no-ops, invoke resolves
|
|
37
|
-
// to undefined, and subscribe returns an inert unsubscribe — a native host is required for real IPC.
|
|
38
|
-
export function createWebIpcBackend() {
|
|
39
|
-
return {
|
|
40
|
-
send() { },
|
|
41
|
-
invoke() {
|
|
42
|
-
return Promise.resolve(undefined);
|
|
43
|
-
},
|
|
44
|
-
subscribe() {
|
|
45
|
-
return () => { };
|
|
46
|
-
},
|
|
47
|
-
getCapabilities() {
|
|
48
|
-
return { canHandle: false, canInvoke: false, canSend: false, canTarget: false };
|
|
49
|
-
},
|
|
50
|
-
};
|
|
51
|
-
}
|
|
52
33
|
// Activates the optional IpcSignals group and returns it. Calling this is when the cost is assumed.
|
|
53
34
|
// The returned object is shared for the lifetime of the package; calling enableIpcSignals multiple
|
|
54
35
|
// times returns the same instance.
|
|
@@ -61,11 +42,24 @@ export function enableIpcSignals() {
|
|
|
61
42
|
}
|
|
62
43
|
return _ipcSignals;
|
|
63
44
|
}
|
|
64
|
-
// Returns
|
|
45
|
+
// Returns a BackendExplanation describing the active backend layer, conflict state, and viability.
|
|
46
|
+
export function explainIpcBackend() {
|
|
47
|
+
if (_custom !== null) {
|
|
48
|
+
return { conflict: _hostConflict, layer: 'custom', operation: null, viability: 'unobserved' };
|
|
49
|
+
}
|
|
50
|
+
if (_host !== null) {
|
|
51
|
+
return {
|
|
52
|
+
conflict: _hostConflict,
|
|
53
|
+
layer: 'host',
|
|
54
|
+
operation: _hostObservation !== null ? _hostObservation.operation : null,
|
|
55
|
+
viability: _hostObservation !== null ? _hostObservation.viability : 'unobserved',
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
return { conflict: false, layer: 'host-not-enabled', operation: null, viability: 'unobserved' };
|
|
59
|
+
}
|
|
60
|
+
// Returns the active IpcBackend. Precedence: custom > host > sentinel.
|
|
65
61
|
export function getIpcBackend() {
|
|
66
|
-
|
|
67
|
-
_backend = createWebIpcBackend();
|
|
68
|
-
return _backend;
|
|
62
|
+
return _custom ?? _host ?? _sentinel;
|
|
69
63
|
}
|
|
70
64
|
// Returns the count of active in-package listeners on a channel. Returns 0 for an unknown channel.
|
|
71
65
|
export function getIpcListenerCount(channel) {
|
|
@@ -76,10 +70,19 @@ export function getIpcListenerCount(channel) {
|
|
|
76
70
|
export function getIpcSignals() {
|
|
77
71
|
return _ipcSignals;
|
|
78
72
|
}
|
|
79
|
-
// Returns true when a
|
|
80
|
-
// Use this to distinguish "no main process" (web) from a connected host without performing an invoke.
|
|
73
|
+
// Returns true when a custom or host backend is installed, false when only the sentinel is active.
|
|
81
74
|
export function hasIpcBackend() {
|
|
82
|
-
return
|
|
75
|
+
return _custom !== null || _host !== null;
|
|
76
|
+
}
|
|
77
|
+
// Installs the host-layer IPC backend. Idempotent: a second call with the same backend is a no-op;
|
|
78
|
+
// a second call with a different backend sets the conflict flag and keeps the first.
|
|
79
|
+
export function installIpcHostBackend(backend) {
|
|
80
|
+
if (_host !== null) {
|
|
81
|
+
if (_host !== backend)
|
|
82
|
+
_hostConflict = true;
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
_host = backend;
|
|
83
86
|
}
|
|
84
87
|
// Sends a request on `channel` and resolves with the host's response, or undefined on web.
|
|
85
88
|
// Rejects with a plain Error if the host handler throws.
|
|
@@ -98,6 +101,13 @@ export function invokeIpcWithTimeout(channel, timeoutMs, ...args) {
|
|
|
98
101
|
});
|
|
99
102
|
return Promise.race([invoke, timeout]);
|
|
100
103
|
}
|
|
104
|
+
// Records the result of a host-layer IPC operation for diagnostic reporting via explainIpcBackend.
|
|
105
|
+
export function observeIpcHostResult(operation, succeeded) {
|
|
106
|
+
_hostObservation = {
|
|
107
|
+
operation,
|
|
108
|
+
viability: succeeded ? 'available' : 'runtime-api-unavailable',
|
|
109
|
+
};
|
|
110
|
+
}
|
|
101
111
|
// Subscribes `listener` to a single message on `channel`, then auto-unsubscribes.
|
|
102
112
|
// Returns an unsubscribe thunk for the not-yet-fired case.
|
|
103
113
|
export function onceIpcMessage(channel, listener) {
|
|
@@ -180,7 +190,14 @@ export function removeAllIpcListeners(channel) {
|
|
|
180
190
|
}
|
|
181
191
|
}
|
|
182
192
|
}
|
|
183
|
-
//
|
|
193
|
+
// Resets all backend state to initial values. Test-only — not part of the public API.
|
|
194
|
+
export function resetIpcBackendForTest() {
|
|
195
|
+
_custom = null;
|
|
196
|
+
_host = null;
|
|
197
|
+
_hostConflict = false;
|
|
198
|
+
_hostObservation = null;
|
|
199
|
+
}
|
|
200
|
+
// Sends a fire-and-forget message on `channel`. No-ops when only the sentinel is active.
|
|
184
201
|
export function sendIpcMessage(channel, ...args) {
|
|
185
202
|
getIpcBackend().send(resolveChannel(channel), args);
|
|
186
203
|
}
|
|
@@ -189,11 +206,26 @@ export function sendIpcMessage(channel, ...args) {
|
|
|
189
206
|
export function sendIpcMessageTo(target, channel, ...args) {
|
|
190
207
|
getIpcBackend().sendTo?.(target, resolveChannel(channel), args);
|
|
191
208
|
}
|
|
192
|
-
// Installs a
|
|
209
|
+
// Installs a custom IPC backend; pass null to clear and fall back to host or sentinel.
|
|
193
210
|
export function setIpcBackend(backend) {
|
|
194
|
-
|
|
211
|
+
_custom = backend;
|
|
195
212
|
if (_ipcSignals !== null)
|
|
196
213
|
emitSignal(_ipcSignals.onBackendChanged);
|
|
197
214
|
}
|
|
198
|
-
|
|
215
|
+
const _sentinel = {
|
|
216
|
+
send() { },
|
|
217
|
+
invoke() {
|
|
218
|
+
return Promise.resolve(undefined);
|
|
219
|
+
},
|
|
220
|
+
subscribe() {
|
|
221
|
+
return () => { };
|
|
222
|
+
},
|
|
223
|
+
getCapabilities() {
|
|
224
|
+
return { canHandle: false, canInvoke: false, canSend: false, canTarget: false };
|
|
225
|
+
},
|
|
226
|
+
};
|
|
227
|
+
let _custom = null;
|
|
228
|
+
let _host = null;
|
|
229
|
+
let _hostConflict = false;
|
|
230
|
+
let _hostObservation = null;
|
|
199
231
|
//# sourceMappingURL=ipc.js.map
|
package/dist/ipc.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ipc.js","sourceRoot":"","sources":["../src/ipc.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"ipc.js","sourceRoot":"","sources":["../src/ipc.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@flighthq/ipc",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0-edge.1908.751021c",
|
|
4
4
|
"author": "Joshua Granick and other contributors",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -38,8 +38,8 @@
|
|
|
38
38
|
"clean:dist": "tsx ../../scripts/clean-package-dist.ts"
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@flighthq/signals": "0.
|
|
42
|
-
"@flighthq/types": "0.
|
|
41
|
+
"@flighthq/signals": "0.4.0-edge.1908.751021c",
|
|
42
|
+
"@flighthq/types": "0.4.0-edge.1908.751021c"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
45
|
"typescript": "^5.3.0"
|
package/src/ipc.test.ts
CHANGED
|
@@ -3,7 +3,6 @@ import { IpcTimeoutError } from '@flighthq/types/contract';
|
|
|
3
3
|
|
|
4
4
|
import {
|
|
5
5
|
createIpcChannel,
|
|
6
|
-
createWebIpcBackend,
|
|
7
6
|
enableIpcSignals,
|
|
8
7
|
getIpcBackend,
|
|
9
8
|
getIpcListenerCount,
|
|
@@ -19,6 +18,10 @@ import {
|
|
|
19
18
|
sendIpcMessage,
|
|
20
19
|
sendIpcMessageTo,
|
|
21
20
|
setIpcBackend,
|
|
21
|
+
explainIpcBackend,
|
|
22
|
+
installIpcHostBackend,
|
|
23
|
+
observeIpcHostResult,
|
|
24
|
+
resetIpcBackendForTest,
|
|
22
25
|
} from './ipc';
|
|
23
26
|
|
|
24
27
|
interface FakeIpcBackend extends IpcBackend {
|
|
@@ -101,24 +104,6 @@ describe('createIpcChannel', () => {
|
|
|
101
104
|
});
|
|
102
105
|
});
|
|
103
106
|
|
|
104
|
-
describe('createWebIpcBackend', () => {
|
|
105
|
-
it('no-ops send, resolves invoke to undefined, returns an inert unsubscribe', async () => {
|
|
106
|
-
const backend = createWebIpcBackend();
|
|
107
|
-
expect(() => backend.send('channel', [1])).not.toThrow();
|
|
108
|
-
expect(await backend.invoke('channel', [])).toBeUndefined();
|
|
109
|
-
expect(typeof backend.subscribe('channel', () => {})).toBe('function');
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
it('reports canSend/canInvoke/canHandle/canTarget as false', () => {
|
|
113
|
-
const backend = createWebIpcBackend();
|
|
114
|
-
const caps = backend.getCapabilities!();
|
|
115
|
-
expect(caps.canSend).toBe(false);
|
|
116
|
-
expect(caps.canInvoke).toBe(false);
|
|
117
|
-
expect(caps.canHandle).toBe(false);
|
|
118
|
-
expect(caps.canTarget).toBe(false);
|
|
119
|
-
});
|
|
120
|
-
});
|
|
121
|
-
|
|
122
107
|
describe('enableIpcSignals', () => {
|
|
123
108
|
it('returns an IpcSignals group', () => {
|
|
124
109
|
const signals: IpcSignals = enableIpcSignals();
|
|
@@ -175,6 +160,34 @@ describe('enableIpcSignals', () => {
|
|
|
175
160
|
});
|
|
176
161
|
});
|
|
177
162
|
|
|
163
|
+
describe('explainIpcBackend', () => {
|
|
164
|
+
afterEach(() => resetIpcBackendForTest());
|
|
165
|
+
|
|
166
|
+
it('reports host-not-enabled when no backend is installed', () => {
|
|
167
|
+
resetIpcBackendForTest();
|
|
168
|
+
const explanation = explainIpcBackend();
|
|
169
|
+
expect(explanation.layer).toBe('host-not-enabled');
|
|
170
|
+
expect(explanation.conflict).toBe(false);
|
|
171
|
+
expect(explanation.viability).toBe('unobserved');
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
it('reports custom layer when a custom backend is set', () => {
|
|
175
|
+
setIpcBackend(fakeBackend());
|
|
176
|
+
expect(explainIpcBackend().layer).toBe('custom');
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
it('reports host layer when a host backend is installed', () => {
|
|
180
|
+
installIpcHostBackend(fakeBackend());
|
|
181
|
+
expect(explainIpcBackend().layer).toBe('host');
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
it('reports conflict when two different host backends are installed', () => {
|
|
185
|
+
installIpcHostBackend(fakeBackend());
|
|
186
|
+
installIpcHostBackend(fakeBackend());
|
|
187
|
+
expect(explainIpcBackend().conflict).toBe(true);
|
|
188
|
+
});
|
|
189
|
+
});
|
|
190
|
+
|
|
178
191
|
describe('getIpcBackend', () => {
|
|
179
192
|
it('falls back to a web backend', () => {
|
|
180
193
|
expect(getIpcBackend()).not.toBeNull();
|
|
@@ -187,6 +200,24 @@ describe('getIpcBackend', () => {
|
|
|
187
200
|
});
|
|
188
201
|
});
|
|
189
202
|
|
|
203
|
+
describe('getIpcBackend (sentinel)', () => {
|
|
204
|
+
it('no-ops send, resolves invoke to undefined, returns an inert unsubscribe', async () => {
|
|
205
|
+
const backend = getIpcBackend();
|
|
206
|
+
expect(() => backend.send('channel', [1])).not.toThrow();
|
|
207
|
+
expect(await backend.invoke('channel', [])).toBeUndefined();
|
|
208
|
+
expect(typeof backend.subscribe('channel', () => {})).toBe('function');
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
it('reports canSend/canInvoke/canHandle/canTarget as false', () => {
|
|
212
|
+
const backend = getIpcBackend();
|
|
213
|
+
const caps = backend.getCapabilities!();
|
|
214
|
+
expect(caps.canSend).toBe(false);
|
|
215
|
+
expect(caps.canInvoke).toBe(false);
|
|
216
|
+
expect(caps.canHandle).toBe(false);
|
|
217
|
+
expect(caps.canTarget).toBe(false);
|
|
218
|
+
});
|
|
219
|
+
});
|
|
220
|
+
|
|
190
221
|
describe('getIpcListenerCount', () => {
|
|
191
222
|
it('returns 0 for an unknown channel', () => {
|
|
192
223
|
expect(getIpcListenerCount('never')).toBe(0);
|
|
@@ -260,6 +291,25 @@ describe('hasIpcBackend', () => {
|
|
|
260
291
|
});
|
|
261
292
|
});
|
|
262
293
|
|
|
294
|
+
describe('installIpcHostBackend', () => {
|
|
295
|
+
afterEach(() => resetIpcBackendForTest());
|
|
296
|
+
|
|
297
|
+
it('installs a host backend that getIpcBackend returns', () => {
|
|
298
|
+
const backend = fakeBackend();
|
|
299
|
+
installIpcHostBackend(backend);
|
|
300
|
+
expect(getIpcBackend()).toBe(backend);
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
it('is first-host-wins: a second different backend sets conflict', () => {
|
|
304
|
+
const first = fakeBackend();
|
|
305
|
+
const second = fakeBackend();
|
|
306
|
+
installIpcHostBackend(first);
|
|
307
|
+
installIpcHostBackend(second);
|
|
308
|
+
expect(getIpcBackend()).toBe(first);
|
|
309
|
+
expect(explainIpcBackend().conflict).toBe(true);
|
|
310
|
+
});
|
|
311
|
+
});
|
|
312
|
+
|
|
263
313
|
describe('invokeIpc', () => {
|
|
264
314
|
it('passes variadic args as an array and resolves the backend result', async () => {
|
|
265
315
|
const backend = fakeBackend();
|
|
@@ -307,6 +357,24 @@ describe('invokeIpcWithTimeout', () => {
|
|
|
307
357
|
});
|
|
308
358
|
});
|
|
309
359
|
|
|
360
|
+
describe('observeIpcHostResult', () => {
|
|
361
|
+
afterEach(() => resetIpcBackendForTest());
|
|
362
|
+
|
|
363
|
+
it('records a successful observation', () => {
|
|
364
|
+
installIpcHostBackend(fakeBackend());
|
|
365
|
+
observeIpcHostResult('send', true);
|
|
366
|
+
const explanation = explainIpcBackend();
|
|
367
|
+
expect(explanation.operation).toBe('send');
|
|
368
|
+
expect(explanation.viability).toBe('available');
|
|
369
|
+
});
|
|
370
|
+
|
|
371
|
+
it('records a failed observation', () => {
|
|
372
|
+
installIpcHostBackend(fakeBackend());
|
|
373
|
+
observeIpcHostResult('send', false);
|
|
374
|
+
expect(explainIpcBackend().viability).toBe('runtime-api-unavailable');
|
|
375
|
+
});
|
|
376
|
+
});
|
|
377
|
+
|
|
310
378
|
describe('onceIpcMessage', () => {
|
|
311
379
|
it('auto-unsubscribes after the first message', () => {
|
|
312
380
|
const backend = fakeBackend();
|
|
@@ -461,6 +529,18 @@ describe('removeAllIpcListeners', () => {
|
|
|
461
529
|
});
|
|
462
530
|
});
|
|
463
531
|
|
|
532
|
+
describe('resetIpcBackendForTest', () => {
|
|
533
|
+
it('clears all backend slots', () => {
|
|
534
|
+
setIpcBackend(fakeBackend());
|
|
535
|
+
installIpcHostBackend(fakeBackend());
|
|
536
|
+
observeIpcHostResult('send', true);
|
|
537
|
+
resetIpcBackendForTest();
|
|
538
|
+
expect(explainIpcBackend().layer).toBe('host-not-enabled');
|
|
539
|
+
expect(explainIpcBackend().conflict).toBe(false);
|
|
540
|
+
expect(explainIpcBackend().viability).toBe('unobserved');
|
|
541
|
+
});
|
|
542
|
+
});
|
|
543
|
+
|
|
464
544
|
describe('sendIpcMessage', () => {
|
|
465
545
|
it('forwards channel and args array to the backend', () => {
|
|
466
546
|
const backend = fakeBackend();
|