@elliemae/microfe-common 2.21.4 → 2.23.0
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/cjs/event.js +5 -2
- package/dist/cjs/index.js +1 -0
- package/dist/cjs/remoting.js +64 -40
- package/dist/cjs/scriptingObjectManager.js +15 -9
- package/dist/esm/event.js +5 -2
- package/dist/esm/index.js +5 -1
- package/dist/esm/remoting.js +64 -40
- package/dist/esm/scriptingObjectManager.js +15 -9
- package/dist/types/lib/event.d.ts +1 -1
- package/dist/types/lib/guest.d.ts +3 -3
- package/dist/types/lib/index.d.ts +1 -1
- package/dist/types/lib/remoting.d.ts +5 -0
- package/dist/types/lib/scriptingObjectManager.d.ts +2 -5
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +18 -19
package/dist/cjs/event.js
CHANGED
|
@@ -58,9 +58,9 @@ class ProxyEvent {
|
|
|
58
58
|
* @returns true if given object is an instance of ProxyEvent
|
|
59
59
|
*/
|
|
60
60
|
static [Symbol.hasInstance](obj) {
|
|
61
|
-
return obj.getType
|
|
61
|
+
return typeof obj === "object" && obj !== null && "getType" in obj && typeof obj.getType === "function" && obj.getType() === "ProxyEvent";
|
|
62
62
|
}
|
|
63
|
-
/* eslint-
|
|
63
|
+
/* eslint-enable indent */
|
|
64
64
|
/**
|
|
65
65
|
* module that owns this event management. SSF Guest or App Bridge host
|
|
66
66
|
*/
|
|
@@ -90,6 +90,9 @@ class ProxyEvent {
|
|
|
90
90
|
*/
|
|
91
91
|
constructor(param) {
|
|
92
92
|
const { name, objectId, eventSrc } = param;
|
|
93
|
+
if (!name) throw new Error("Event name is required");
|
|
94
|
+
if (!objectId) throw new Error("Scripting object id is required");
|
|
95
|
+
if (!eventSrc) throw new Error("Event source is required");
|
|
93
96
|
this.objectId = objectId;
|
|
94
97
|
this.name = name;
|
|
95
98
|
this.#eventSrc = eventSrc;
|
package/dist/cjs/index.js
CHANGED
|
@@ -25,6 +25,7 @@ __export(index_exports, {
|
|
|
25
25
|
ScriptingObject: () => import_scriptingObject.ScriptingObject,
|
|
26
26
|
ScriptingObjectManager: () => import_scriptingObjectManager.ScriptingObjectManager,
|
|
27
27
|
ScriptingObjectProxy: () => import_proxy.ScriptingObjectProxy,
|
|
28
|
+
SecurityContext: () => import_scriptingObjectManager.SecurityContext,
|
|
28
29
|
getEventId: () => import_event.getEventId,
|
|
29
30
|
isPublicFunction: () => import_scriptingObject.isPublicFunction,
|
|
30
31
|
isScriptingObjectProxy: () => import_proxy.isScriptingObjectProxy,
|
package/dist/cjs/remoting.js
CHANGED
|
@@ -29,9 +29,10 @@ const EXCEPTION_MESSAGE_TYPE = "elli:remoting:exception";
|
|
|
29
29
|
const createMessage = ({
|
|
30
30
|
messageType,
|
|
31
31
|
messageBody,
|
|
32
|
+
requestId,
|
|
32
33
|
onewayMsg = false
|
|
33
34
|
}) => ({
|
|
34
|
-
requestId: !onewayMsg ? (0, import_uuid.v4)() : null,
|
|
35
|
+
requestId: requestId ?? (!onewayMsg ? (0, import_uuid.v4)() : null),
|
|
35
36
|
source: MESSAGE_SOURCE,
|
|
36
37
|
type: messageType,
|
|
37
38
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
@@ -57,6 +58,10 @@ class Remoting {
|
|
|
57
58
|
* The handle to the timeout monitor
|
|
58
59
|
*/
|
|
59
60
|
#timeoutMonitorHandle = null;
|
|
61
|
+
/**
|
|
62
|
+
* The window that remoting was initialized on
|
|
63
|
+
*/
|
|
64
|
+
#initializedWindow = null;
|
|
60
65
|
/**
|
|
61
66
|
* The set of windows that are allowed to send messages to this window
|
|
62
67
|
*/
|
|
@@ -72,53 +77,45 @@ class Remoting {
|
|
|
72
77
|
this.#correlationId = correlationId;
|
|
73
78
|
this.#logger = logger;
|
|
74
79
|
}
|
|
75
|
-
// Evaluates the timeouts on any waiting invocations
|
|
80
|
+
// Evaluates the timeouts on any waiting invocations and schedules the next check
|
|
76
81
|
#evaluateTimeouts = () => {
|
|
82
|
+
this.#timeoutMonitorHandle = null;
|
|
77
83
|
const ts = Date.now();
|
|
78
84
|
const canceledItems = [];
|
|
85
|
+
let nextCancelTime = null;
|
|
79
86
|
this.#invocations.forEach((eventData, key) => {
|
|
80
87
|
const { requestId, cancelTime } = eventData;
|
|
81
|
-
|
|
82
|
-
`Checking response timeout for requestId: ${requestId}) @ ${cancelTime ?? ""}`
|
|
83
|
-
);
|
|
84
|
-
if (eventData.cancelTime && eventData.cancelTime < ts) {
|
|
88
|
+
if (cancelTime && cancelTime <= ts) {
|
|
85
89
|
this.#logger.debug(
|
|
86
90
|
`Detected response timeout for requestId: ${requestId}...`
|
|
87
91
|
);
|
|
88
92
|
canceledItems.push(key);
|
|
89
|
-
eventData.resolve();
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
);
|
|
93
|
+
eventData.resolve(void 0);
|
|
94
|
+
} else if (cancelTime) {
|
|
95
|
+
nextCancelTime = nextCancelTime === null ? cancelTime : Math.min(nextCancelTime, cancelTime);
|
|
93
96
|
}
|
|
94
97
|
});
|
|
95
98
|
canceledItems.forEach((key) => {
|
|
96
|
-
this.#logger.debug(
|
|
97
|
-
`removing invocations with requestId ${key} from cache since response time has expired`
|
|
98
|
-
);
|
|
99
99
|
this.#invocations.delete(key);
|
|
100
100
|
});
|
|
101
|
-
if (
|
|
102
|
-
|
|
103
|
-
this.#
|
|
101
|
+
if (nextCancelTime !== null) {
|
|
102
|
+
const delay = Math.max(nextCancelTime - Date.now(), 0);
|
|
103
|
+
this.#scheduleTimeoutCheck(delay);
|
|
104
104
|
}
|
|
105
105
|
};
|
|
106
|
-
//
|
|
107
|
-
#
|
|
108
|
-
if (this.#timeoutMonitorHandle
|
|
109
|
-
|
|
110
|
-
this.#
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
);
|
|
114
|
-
}
|
|
106
|
+
// Schedule a timeout check after a delay
|
|
107
|
+
#scheduleTimeoutCheck = (delayMs) => {
|
|
108
|
+
if (this.#timeoutMonitorHandle !== null) return;
|
|
109
|
+
this.#timeoutMonitorHandle = window.setTimeout(
|
|
110
|
+
this.#evaluateTimeouts,
|
|
111
|
+
delayMs
|
|
112
|
+
);
|
|
115
113
|
};
|
|
116
|
-
// Stops the timeout monitor
|
|
114
|
+
// Stops the timeout monitor
|
|
117
115
|
#stopResponseMonitor = () => {
|
|
118
116
|
if (this.#timeoutMonitorHandle !== null) {
|
|
119
|
-
window.
|
|
117
|
+
window.clearTimeout(this.#timeoutMonitorHandle);
|
|
120
118
|
this.#timeoutMonitorHandle = null;
|
|
121
|
-
this.#logger.debug("Stopped response timeout evaluator");
|
|
122
119
|
}
|
|
123
120
|
};
|
|
124
121
|
// Pops an invocation from the incovation list
|
|
@@ -182,14 +179,14 @@ class Remoting {
|
|
|
182
179
|
};
|
|
183
180
|
// Processes a message received thru the window's message event
|
|
184
181
|
#processMessage = (message) => {
|
|
185
|
-
this.#logger.debug(
|
|
186
|
-
`Remoting: Received message ${JSON.stringify(message.data)}`
|
|
187
|
-
);
|
|
188
182
|
if (this.#allowedSenders.size === 0) return false;
|
|
189
183
|
if (!message.source) return false;
|
|
190
184
|
const senderOrigin = this.#allowedSenders.get(message.source);
|
|
191
185
|
if (!senderOrigin) return false;
|
|
192
186
|
if (message?.data?.source !== MESSAGE_SOURCE) return false;
|
|
187
|
+
this.#logger.debug(
|
|
188
|
+
`Remoting: Received message of type "${message.data.type}"`
|
|
189
|
+
);
|
|
193
190
|
if (message.data.type === RESPONSE_MESSAGE_TYPE)
|
|
194
191
|
this.#processResponse(message.data);
|
|
195
192
|
else if (message.data.type === EXCEPTION_MESSAGE_TYPE)
|
|
@@ -217,15 +214,28 @@ class Remoting {
|
|
|
217
214
|
* @param win The window to initialize remoting for
|
|
218
215
|
*/
|
|
219
216
|
initialize = (win) => {
|
|
220
|
-
|
|
217
|
+
if (this.#initializedWindow) {
|
|
218
|
+
this.#initializedWindow.removeEventListener(
|
|
219
|
+
"message",
|
|
220
|
+
this.#processMessage
|
|
221
|
+
);
|
|
222
|
+
}
|
|
221
223
|
win.addEventListener("message", this.#processMessage);
|
|
224
|
+
this.#initializedWindow = win;
|
|
222
225
|
this.#logger.debug(`initialized remoting id: ${this.#correlationId}`);
|
|
223
226
|
};
|
|
224
227
|
/**
|
|
225
228
|
* Closes the remoting service for a window
|
|
226
229
|
*/
|
|
227
230
|
close = () => {
|
|
228
|
-
|
|
231
|
+
if (this.#initializedWindow) {
|
|
232
|
+
this.#initializedWindow.removeEventListener(
|
|
233
|
+
"message",
|
|
234
|
+
this.#processMessage
|
|
235
|
+
);
|
|
236
|
+
this.#initializedWindow = null;
|
|
237
|
+
}
|
|
238
|
+
this.#stopResponseMonitor();
|
|
229
239
|
this.#logger.debug(`closed remoting id: ${this.#correlationId}`);
|
|
230
240
|
};
|
|
231
241
|
/**
|
|
@@ -247,7 +257,7 @@ class Remoting {
|
|
|
247
257
|
requestId: msg.requestId,
|
|
248
258
|
resolve,
|
|
249
259
|
reject,
|
|
250
|
-
cancelTime: responseTimeoutMs ? Date.now() +
|
|
260
|
+
cancelTime: responseTimeoutMs ? Date.now() + responseTimeoutMs : null
|
|
251
261
|
});
|
|
252
262
|
targetWin.postMessage(msg, targetOrigin);
|
|
253
263
|
const { requestId } = msg;
|
|
@@ -256,9 +266,9 @@ class Remoting {
|
|
|
256
266
|
);
|
|
257
267
|
if (responseTimeoutMs) {
|
|
258
268
|
this.#logger.debug(
|
|
259
|
-
`
|
|
269
|
+
`scheduling timeout check for requestId: ${requestId || ""} in ${responseTimeoutMs} ms`
|
|
260
270
|
);
|
|
261
|
-
this.#
|
|
271
|
+
this.#scheduleTimeoutCheck(responseTimeoutMs);
|
|
262
272
|
}
|
|
263
273
|
});
|
|
264
274
|
};
|
|
@@ -272,6 +282,19 @@ class Remoting {
|
|
|
272
282
|
items.push(callback);
|
|
273
283
|
this.#listeners.set(messageType, items);
|
|
274
284
|
};
|
|
285
|
+
/**
|
|
286
|
+
* Remove a previously registered callback for a specific message type
|
|
287
|
+
* @param {ListenParam<T>} param The parameters identifying the listener to remove
|
|
288
|
+
*/
|
|
289
|
+
unlisten = (param) => {
|
|
290
|
+
const { messageType, callback } = param;
|
|
291
|
+
const items = this.#listeners.get(messageType);
|
|
292
|
+
if (!items) return;
|
|
293
|
+
const index = items.indexOf(callback);
|
|
294
|
+
if (index !== -1) {
|
|
295
|
+
items.splice(index, 1);
|
|
296
|
+
}
|
|
297
|
+
};
|
|
275
298
|
/**
|
|
276
299
|
* Send a message without any form of response. Fire and forget
|
|
277
300
|
* @param {SendParam} param The parameters for the send
|
|
@@ -302,9 +325,9 @@ class Remoting {
|
|
|
302
325
|
const { targetWin, targetOrigin, requestId, response } = param;
|
|
303
326
|
const msg = createMessage({
|
|
304
327
|
messageType: RESPONSE_MESSAGE_TYPE,
|
|
305
|
-
messageBody: response
|
|
328
|
+
messageBody: response,
|
|
329
|
+
requestId
|
|
306
330
|
});
|
|
307
|
-
msg.requestId = requestId;
|
|
308
331
|
targetWin.postMessage(msg, targetOrigin);
|
|
309
332
|
this.#logger.debug(
|
|
310
333
|
`Response sent to caller for invocation requestId: ${requestId}`
|
|
@@ -316,11 +339,12 @@ class Remoting {
|
|
|
316
339
|
*/
|
|
317
340
|
raiseException = (param) => {
|
|
318
341
|
const { targetWin, targetOrigin, requestId, ex } = param;
|
|
342
|
+
const messageBody = ex instanceof Error ? ex.message : ex;
|
|
319
343
|
const msg = createMessage({
|
|
320
344
|
messageType: EXCEPTION_MESSAGE_TYPE,
|
|
321
|
-
messageBody
|
|
345
|
+
messageBody,
|
|
346
|
+
requestId
|
|
322
347
|
});
|
|
323
|
-
msg.requestId = requestId;
|
|
324
348
|
targetWin.postMessage(msg, targetOrigin);
|
|
325
349
|
this.#logger.debug(
|
|
326
350
|
`Exception sent to caller for invocation. requestId: ${requestId}`
|
|
@@ -30,6 +30,7 @@ var SecurityContext = /* @__PURE__ */ ((SecurityContext2) => {
|
|
|
30
30
|
return SecurityContext2;
|
|
31
31
|
})(SecurityContext || {});
|
|
32
32
|
class ScriptingObjectManager {
|
|
33
|
+
#normalizeId = (id) => id.trim().toLowerCase();
|
|
33
34
|
/**
|
|
34
35
|
* collection of registered scripting objects
|
|
35
36
|
*/
|
|
@@ -40,7 +41,7 @@ class ScriptingObjectManager {
|
|
|
40
41
|
#guestScriptingObjects = /* @__PURE__ */ new Map();
|
|
41
42
|
#addGuestScriptingObject = (params) => {
|
|
42
43
|
const { so, guestId } = params;
|
|
43
|
-
const objectId = so.id
|
|
44
|
+
const objectId = this.#normalizeId(so.id);
|
|
44
45
|
const guestSOs = this.#guestScriptingObjects.get(guestId);
|
|
45
46
|
if (!guestSOs) {
|
|
46
47
|
this.#guestScriptingObjects.set(guestId, /* @__PURE__ */ new Map([[objectId, params]]));
|
|
@@ -54,7 +55,10 @@ class ScriptingObjectManager {
|
|
|
54
55
|
};
|
|
55
56
|
#disposeSO = ({ so }) => {
|
|
56
57
|
if (so._dispose && typeof so._dispose === "function") {
|
|
57
|
-
|
|
58
|
+
try {
|
|
59
|
+
so._dispose();
|
|
60
|
+
} catch {
|
|
61
|
+
}
|
|
58
62
|
}
|
|
59
63
|
};
|
|
60
64
|
/**
|
|
@@ -119,8 +123,8 @@ class ScriptingObjectManager {
|
|
|
119
123
|
if (!so?.id || !so?._toJSON) {
|
|
120
124
|
throw new Error("Object is not derived from ScriptingObject");
|
|
121
125
|
}
|
|
122
|
-
const objectId = so.id
|
|
123
|
-
if (objectId
|
|
126
|
+
const objectId = this.#normalizeId(so.id);
|
|
127
|
+
if (objectId === MODULE_OBJECT && !guestId) {
|
|
124
128
|
throw new Error(`Guest id is required to add Module scripting object`);
|
|
125
129
|
}
|
|
126
130
|
if (guestId) {
|
|
@@ -138,7 +142,7 @@ class ScriptingObjectManager {
|
|
|
138
142
|
* @returns proxied scripting object reference
|
|
139
143
|
*/
|
|
140
144
|
getObject = (objectId, guest) => {
|
|
141
|
-
const id = objectId
|
|
145
|
+
const id = this.#normalizeId(objectId);
|
|
142
146
|
let soInfo = this.#getGuestScriptingObject({
|
|
143
147
|
objectId: id,
|
|
144
148
|
guestId: guest?.id
|
|
@@ -161,10 +165,12 @@ class ScriptingObjectManager {
|
|
|
161
165
|
* @returns name of scripting objects for the given guest
|
|
162
166
|
*/
|
|
163
167
|
listScriptingObjects = (guestId) => {
|
|
164
|
-
|
|
168
|
+
const objects = new Set(this.#scriptingObjects.keys());
|
|
165
169
|
const guestSOs = this.#guestScriptingObjects.get(guestId);
|
|
166
|
-
|
|
167
|
-
|
|
170
|
+
if (guestSOs) {
|
|
171
|
+
for (const key of guestSOs.keys()) objects.add(key);
|
|
172
|
+
}
|
|
173
|
+
return Array.from(objects);
|
|
168
174
|
};
|
|
169
175
|
/**
|
|
170
176
|
* removes scripting object
|
|
@@ -172,7 +178,7 @@ class ScriptingObjectManager {
|
|
|
172
178
|
* @param guestId unique id of the guest
|
|
173
179
|
*/
|
|
174
180
|
removeScriptingObject = (objectId, guestId) => {
|
|
175
|
-
const id = objectId
|
|
181
|
+
const id = this.#normalizeId(objectId);
|
|
176
182
|
if (guestId) {
|
|
177
183
|
this.#removeGuestScriptingObject({ objectId: id, guestId });
|
|
178
184
|
} else {
|
package/dist/esm/event.js
CHANGED
|
@@ -32,9 +32,9 @@ class ProxyEvent {
|
|
|
32
32
|
* @returns true if given object is an instance of ProxyEvent
|
|
33
33
|
*/
|
|
34
34
|
static [Symbol.hasInstance](obj) {
|
|
35
|
-
return obj.getType
|
|
35
|
+
return typeof obj === "object" && obj !== null && "getType" in obj && typeof obj.getType === "function" && obj.getType() === "ProxyEvent";
|
|
36
36
|
}
|
|
37
|
-
/* eslint-
|
|
37
|
+
/* eslint-enable indent */
|
|
38
38
|
/**
|
|
39
39
|
* module that owns this event management. SSF Guest or App Bridge host
|
|
40
40
|
*/
|
|
@@ -64,6 +64,9 @@ class ProxyEvent {
|
|
|
64
64
|
*/
|
|
65
65
|
constructor(param) {
|
|
66
66
|
const { name, objectId, eventSrc } = param;
|
|
67
|
+
if (!name) throw new Error("Event name is required");
|
|
68
|
+
if (!objectId) throw new Error("Scripting object id is required");
|
|
69
|
+
if (!eventSrc) throw new Error("Event source is required");
|
|
67
70
|
this.objectId = objectId;
|
|
68
71
|
this.name = name;
|
|
69
72
|
this.#eventSrc = eventSrc;
|
package/dist/esm/index.js
CHANGED
|
@@ -3,7 +3,10 @@ import { getEventId, ProxyEvent } from "./event.js";
|
|
|
3
3
|
import { Event } from "./event.js";
|
|
4
4
|
import { ScriptingObject, isPublicFunction } from "./scriptingObject.js";
|
|
5
5
|
import { MessageType } from "./messageType.js";
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
ScriptingObjectManager,
|
|
8
|
+
SecurityContext
|
|
9
|
+
} from "./scriptingObjectManager.js";
|
|
7
10
|
import { ScriptingObjectProxy, isScriptingObjectProxy } from "./proxy.js";
|
|
8
11
|
export {
|
|
9
12
|
Event,
|
|
@@ -13,6 +16,7 @@ export {
|
|
|
13
16
|
ScriptingObject,
|
|
14
17
|
ScriptingObjectManager,
|
|
15
18
|
ScriptingObjectProxy,
|
|
19
|
+
SecurityContext,
|
|
16
20
|
getEventId,
|
|
17
21
|
isPublicFunction,
|
|
18
22
|
isScriptingObjectProxy,
|
package/dist/esm/remoting.js
CHANGED
|
@@ -5,9 +5,10 @@ const EXCEPTION_MESSAGE_TYPE = "elli:remoting:exception";
|
|
|
5
5
|
const createMessage = ({
|
|
6
6
|
messageType,
|
|
7
7
|
messageBody,
|
|
8
|
+
requestId,
|
|
8
9
|
onewayMsg = false
|
|
9
10
|
}) => ({
|
|
10
|
-
requestId: !onewayMsg ? uuidv4() : null,
|
|
11
|
+
requestId: requestId ?? (!onewayMsg ? uuidv4() : null),
|
|
11
12
|
source: MESSAGE_SOURCE,
|
|
12
13
|
type: messageType,
|
|
13
14
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
@@ -33,6 +34,10 @@ class Remoting {
|
|
|
33
34
|
* The handle to the timeout monitor
|
|
34
35
|
*/
|
|
35
36
|
#timeoutMonitorHandle = null;
|
|
37
|
+
/**
|
|
38
|
+
* The window that remoting was initialized on
|
|
39
|
+
*/
|
|
40
|
+
#initializedWindow = null;
|
|
36
41
|
/**
|
|
37
42
|
* The set of windows that are allowed to send messages to this window
|
|
38
43
|
*/
|
|
@@ -48,53 +53,45 @@ class Remoting {
|
|
|
48
53
|
this.#correlationId = correlationId;
|
|
49
54
|
this.#logger = logger;
|
|
50
55
|
}
|
|
51
|
-
// Evaluates the timeouts on any waiting invocations
|
|
56
|
+
// Evaluates the timeouts on any waiting invocations and schedules the next check
|
|
52
57
|
#evaluateTimeouts = () => {
|
|
58
|
+
this.#timeoutMonitorHandle = null;
|
|
53
59
|
const ts = Date.now();
|
|
54
60
|
const canceledItems = [];
|
|
61
|
+
let nextCancelTime = null;
|
|
55
62
|
this.#invocations.forEach((eventData, key) => {
|
|
56
63
|
const { requestId, cancelTime } = eventData;
|
|
57
|
-
|
|
58
|
-
`Checking response timeout for requestId: ${requestId}) @ ${cancelTime ?? ""}`
|
|
59
|
-
);
|
|
60
|
-
if (eventData.cancelTime && eventData.cancelTime < ts) {
|
|
64
|
+
if (cancelTime && cancelTime <= ts) {
|
|
61
65
|
this.#logger.debug(
|
|
62
66
|
`Detected response timeout for requestId: ${requestId}...`
|
|
63
67
|
);
|
|
64
68
|
canceledItems.push(key);
|
|
65
|
-
eventData.resolve();
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
);
|
|
69
|
+
eventData.resolve(void 0);
|
|
70
|
+
} else if (cancelTime) {
|
|
71
|
+
nextCancelTime = nextCancelTime === null ? cancelTime : Math.min(nextCancelTime, cancelTime);
|
|
69
72
|
}
|
|
70
73
|
});
|
|
71
74
|
canceledItems.forEach((key) => {
|
|
72
|
-
this.#logger.debug(
|
|
73
|
-
`removing invocations with requestId ${key} from cache since response time has expired`
|
|
74
|
-
);
|
|
75
75
|
this.#invocations.delete(key);
|
|
76
76
|
});
|
|
77
|
-
if (
|
|
78
|
-
|
|
79
|
-
this.#
|
|
77
|
+
if (nextCancelTime !== null) {
|
|
78
|
+
const delay = Math.max(nextCancelTime - Date.now(), 0);
|
|
79
|
+
this.#scheduleTimeoutCheck(delay);
|
|
80
80
|
}
|
|
81
81
|
};
|
|
82
|
-
//
|
|
83
|
-
#
|
|
84
|
-
if (this.#timeoutMonitorHandle
|
|
85
|
-
|
|
86
|
-
this.#
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
);
|
|
90
|
-
}
|
|
82
|
+
// Schedule a timeout check after a delay
|
|
83
|
+
#scheduleTimeoutCheck = (delayMs) => {
|
|
84
|
+
if (this.#timeoutMonitorHandle !== null) return;
|
|
85
|
+
this.#timeoutMonitorHandle = window.setTimeout(
|
|
86
|
+
this.#evaluateTimeouts,
|
|
87
|
+
delayMs
|
|
88
|
+
);
|
|
91
89
|
};
|
|
92
|
-
// Stops the timeout monitor
|
|
90
|
+
// Stops the timeout monitor
|
|
93
91
|
#stopResponseMonitor = () => {
|
|
94
92
|
if (this.#timeoutMonitorHandle !== null) {
|
|
95
|
-
window.
|
|
93
|
+
window.clearTimeout(this.#timeoutMonitorHandle);
|
|
96
94
|
this.#timeoutMonitorHandle = null;
|
|
97
|
-
this.#logger.debug("Stopped response timeout evaluator");
|
|
98
95
|
}
|
|
99
96
|
};
|
|
100
97
|
// Pops an invocation from the incovation list
|
|
@@ -158,14 +155,14 @@ class Remoting {
|
|
|
158
155
|
};
|
|
159
156
|
// Processes a message received thru the window's message event
|
|
160
157
|
#processMessage = (message) => {
|
|
161
|
-
this.#logger.debug(
|
|
162
|
-
`Remoting: Received message ${JSON.stringify(message.data)}`
|
|
163
|
-
);
|
|
164
158
|
if (this.#allowedSenders.size === 0) return false;
|
|
165
159
|
if (!message.source) return false;
|
|
166
160
|
const senderOrigin = this.#allowedSenders.get(message.source);
|
|
167
161
|
if (!senderOrigin) return false;
|
|
168
162
|
if (message?.data?.source !== MESSAGE_SOURCE) return false;
|
|
163
|
+
this.#logger.debug(
|
|
164
|
+
`Remoting: Received message of type "${message.data.type}"`
|
|
165
|
+
);
|
|
169
166
|
if (message.data.type === RESPONSE_MESSAGE_TYPE)
|
|
170
167
|
this.#processResponse(message.data);
|
|
171
168
|
else if (message.data.type === EXCEPTION_MESSAGE_TYPE)
|
|
@@ -193,15 +190,28 @@ class Remoting {
|
|
|
193
190
|
* @param win The window to initialize remoting for
|
|
194
191
|
*/
|
|
195
192
|
initialize = (win) => {
|
|
196
|
-
|
|
193
|
+
if (this.#initializedWindow) {
|
|
194
|
+
this.#initializedWindow.removeEventListener(
|
|
195
|
+
"message",
|
|
196
|
+
this.#processMessage
|
|
197
|
+
);
|
|
198
|
+
}
|
|
197
199
|
win.addEventListener("message", this.#processMessage);
|
|
200
|
+
this.#initializedWindow = win;
|
|
198
201
|
this.#logger.debug(`initialized remoting id: ${this.#correlationId}`);
|
|
199
202
|
};
|
|
200
203
|
/**
|
|
201
204
|
* Closes the remoting service for a window
|
|
202
205
|
*/
|
|
203
206
|
close = () => {
|
|
204
|
-
|
|
207
|
+
if (this.#initializedWindow) {
|
|
208
|
+
this.#initializedWindow.removeEventListener(
|
|
209
|
+
"message",
|
|
210
|
+
this.#processMessage
|
|
211
|
+
);
|
|
212
|
+
this.#initializedWindow = null;
|
|
213
|
+
}
|
|
214
|
+
this.#stopResponseMonitor();
|
|
205
215
|
this.#logger.debug(`closed remoting id: ${this.#correlationId}`);
|
|
206
216
|
};
|
|
207
217
|
/**
|
|
@@ -223,7 +233,7 @@ class Remoting {
|
|
|
223
233
|
requestId: msg.requestId,
|
|
224
234
|
resolve,
|
|
225
235
|
reject,
|
|
226
|
-
cancelTime: responseTimeoutMs ? Date.now() +
|
|
236
|
+
cancelTime: responseTimeoutMs ? Date.now() + responseTimeoutMs : null
|
|
227
237
|
});
|
|
228
238
|
targetWin.postMessage(msg, targetOrigin);
|
|
229
239
|
const { requestId } = msg;
|
|
@@ -232,9 +242,9 @@ class Remoting {
|
|
|
232
242
|
);
|
|
233
243
|
if (responseTimeoutMs) {
|
|
234
244
|
this.#logger.debug(
|
|
235
|
-
`
|
|
245
|
+
`scheduling timeout check for requestId: ${requestId || ""} in ${responseTimeoutMs} ms`
|
|
236
246
|
);
|
|
237
|
-
this.#
|
|
247
|
+
this.#scheduleTimeoutCheck(responseTimeoutMs);
|
|
238
248
|
}
|
|
239
249
|
});
|
|
240
250
|
};
|
|
@@ -248,6 +258,19 @@ class Remoting {
|
|
|
248
258
|
items.push(callback);
|
|
249
259
|
this.#listeners.set(messageType, items);
|
|
250
260
|
};
|
|
261
|
+
/**
|
|
262
|
+
* Remove a previously registered callback for a specific message type
|
|
263
|
+
* @param {ListenParam<T>} param The parameters identifying the listener to remove
|
|
264
|
+
*/
|
|
265
|
+
unlisten = (param) => {
|
|
266
|
+
const { messageType, callback } = param;
|
|
267
|
+
const items = this.#listeners.get(messageType);
|
|
268
|
+
if (!items) return;
|
|
269
|
+
const index = items.indexOf(callback);
|
|
270
|
+
if (index !== -1) {
|
|
271
|
+
items.splice(index, 1);
|
|
272
|
+
}
|
|
273
|
+
};
|
|
251
274
|
/**
|
|
252
275
|
* Send a message without any form of response. Fire and forget
|
|
253
276
|
* @param {SendParam} param The parameters for the send
|
|
@@ -278,9 +301,9 @@ class Remoting {
|
|
|
278
301
|
const { targetWin, targetOrigin, requestId, response } = param;
|
|
279
302
|
const msg = createMessage({
|
|
280
303
|
messageType: RESPONSE_MESSAGE_TYPE,
|
|
281
|
-
messageBody: response
|
|
304
|
+
messageBody: response,
|
|
305
|
+
requestId
|
|
282
306
|
});
|
|
283
|
-
msg.requestId = requestId;
|
|
284
307
|
targetWin.postMessage(msg, targetOrigin);
|
|
285
308
|
this.#logger.debug(
|
|
286
309
|
`Response sent to caller for invocation requestId: ${requestId}`
|
|
@@ -292,11 +315,12 @@ class Remoting {
|
|
|
292
315
|
*/
|
|
293
316
|
raiseException = (param) => {
|
|
294
317
|
const { targetWin, targetOrigin, requestId, ex } = param;
|
|
318
|
+
const messageBody = ex instanceof Error ? ex.message : ex;
|
|
295
319
|
const msg = createMessage({
|
|
296
320
|
messageType: EXCEPTION_MESSAGE_TYPE,
|
|
297
|
-
messageBody
|
|
321
|
+
messageBody,
|
|
322
|
+
requestId
|
|
298
323
|
});
|
|
299
|
-
msg.requestId = requestId;
|
|
300
324
|
targetWin.postMessage(msg, targetOrigin);
|
|
301
325
|
this.#logger.debug(
|
|
302
326
|
`Exception sent to caller for invocation. requestId: ${requestId}`
|
|
@@ -5,6 +5,7 @@ var SecurityContext = /* @__PURE__ */ ((SecurityContext2) => {
|
|
|
5
5
|
return SecurityContext2;
|
|
6
6
|
})(SecurityContext || {});
|
|
7
7
|
class ScriptingObjectManager {
|
|
8
|
+
#normalizeId = (id) => id.trim().toLowerCase();
|
|
8
9
|
/**
|
|
9
10
|
* collection of registered scripting objects
|
|
10
11
|
*/
|
|
@@ -15,7 +16,7 @@ class ScriptingObjectManager {
|
|
|
15
16
|
#guestScriptingObjects = /* @__PURE__ */ new Map();
|
|
16
17
|
#addGuestScriptingObject = (params) => {
|
|
17
18
|
const { so, guestId } = params;
|
|
18
|
-
const objectId = so.id
|
|
19
|
+
const objectId = this.#normalizeId(so.id);
|
|
19
20
|
const guestSOs = this.#guestScriptingObjects.get(guestId);
|
|
20
21
|
if (!guestSOs) {
|
|
21
22
|
this.#guestScriptingObjects.set(guestId, /* @__PURE__ */ new Map([[objectId, params]]));
|
|
@@ -29,7 +30,10 @@ class ScriptingObjectManager {
|
|
|
29
30
|
};
|
|
30
31
|
#disposeSO = ({ so }) => {
|
|
31
32
|
if (so._dispose && typeof so._dispose === "function") {
|
|
32
|
-
|
|
33
|
+
try {
|
|
34
|
+
so._dispose();
|
|
35
|
+
} catch {
|
|
36
|
+
}
|
|
33
37
|
}
|
|
34
38
|
};
|
|
35
39
|
/**
|
|
@@ -94,8 +98,8 @@ class ScriptingObjectManager {
|
|
|
94
98
|
if (!so?.id || !so?._toJSON) {
|
|
95
99
|
throw new Error("Object is not derived from ScriptingObject");
|
|
96
100
|
}
|
|
97
|
-
const objectId = so.id
|
|
98
|
-
if (objectId
|
|
101
|
+
const objectId = this.#normalizeId(so.id);
|
|
102
|
+
if (objectId === MODULE_OBJECT && !guestId) {
|
|
99
103
|
throw new Error(`Guest id is required to add Module scripting object`);
|
|
100
104
|
}
|
|
101
105
|
if (guestId) {
|
|
@@ -113,7 +117,7 @@ class ScriptingObjectManager {
|
|
|
113
117
|
* @returns proxied scripting object reference
|
|
114
118
|
*/
|
|
115
119
|
getObject = (objectId, guest) => {
|
|
116
|
-
const id = objectId
|
|
120
|
+
const id = this.#normalizeId(objectId);
|
|
117
121
|
let soInfo = this.#getGuestScriptingObject({
|
|
118
122
|
objectId: id,
|
|
119
123
|
guestId: guest?.id
|
|
@@ -136,10 +140,12 @@ class ScriptingObjectManager {
|
|
|
136
140
|
* @returns name of scripting objects for the given guest
|
|
137
141
|
*/
|
|
138
142
|
listScriptingObjects = (guestId) => {
|
|
139
|
-
|
|
143
|
+
const objects = new Set(this.#scriptingObjects.keys());
|
|
140
144
|
const guestSOs = this.#guestScriptingObjects.get(guestId);
|
|
141
|
-
|
|
142
|
-
|
|
145
|
+
if (guestSOs) {
|
|
146
|
+
for (const key of guestSOs.keys()) objects.add(key);
|
|
147
|
+
}
|
|
148
|
+
return Array.from(objects);
|
|
143
149
|
};
|
|
144
150
|
/**
|
|
145
151
|
* removes scripting object
|
|
@@ -147,7 +153,7 @@ class ScriptingObjectManager {
|
|
|
147
153
|
* @param guestId unique id of the guest
|
|
148
154
|
*/
|
|
149
155
|
removeScriptingObject = (objectId, guestId) => {
|
|
150
|
-
const id = objectId
|
|
156
|
+
const id = this.#normalizeId(objectId);
|
|
151
157
|
if (guestId) {
|
|
152
158
|
this.#removeGuestScriptingObject({ objectId: id, guestId });
|
|
153
159
|
} else {
|
|
@@ -143,7 +143,7 @@ export declare class ProxyEvent<AppEvents extends EventListeners = Events> imple
|
|
|
143
143
|
* @param obj object to be compared
|
|
144
144
|
* @returns true if given object is an instance of ProxyEvent
|
|
145
145
|
*/
|
|
146
|
-
static [Symbol.hasInstance](obj:
|
|
146
|
+
static [Symbol.hasInstance](obj: unknown): boolean;
|
|
147
147
|
/**
|
|
148
148
|
* unique id of scripting object
|
|
149
149
|
*/
|
|
@@ -2,7 +2,7 @@ import { ScriptingObjectTypes, Events } from '@elliemae/pui-scripting-object';
|
|
|
2
2
|
import { LogLevels } from '@elliemae/pui-diagnostics';
|
|
3
3
|
import { EventListeners } from './common.js';
|
|
4
4
|
import { IEventManager } from './event.js';
|
|
5
|
-
import { ScriptingObjects } from './
|
|
5
|
+
import { ScriptingObjects } from './scriptingObject.js';
|
|
6
6
|
/**
|
|
7
7
|
* parameters for connecting to the host
|
|
8
8
|
*/
|
|
@@ -11,7 +11,7 @@ export type ConnectParam = {
|
|
|
11
11
|
* reference to the guest window
|
|
12
12
|
*/
|
|
13
13
|
window?: Window;
|
|
14
|
-
} & Record<string,
|
|
14
|
+
} & Record<string, unknown>;
|
|
15
15
|
/**
|
|
16
16
|
* Interface for SSF guest
|
|
17
17
|
*/
|
|
@@ -46,7 +46,7 @@ export interface ISSFGuest<AppObjects extends ScriptingObjects = Partial<Scripti
|
|
|
46
46
|
* Get names of scripting objects exposed by the host
|
|
47
47
|
* @returns scripting objects exposed by the host
|
|
48
48
|
*/
|
|
49
|
-
listObjects: () => Promise<keyof AppObjects
|
|
49
|
+
listObjects: () => Promise<Array<Extract<keyof AppObjects, string>>>;
|
|
50
50
|
/**
|
|
51
51
|
* remove the guest from the host
|
|
52
52
|
*/
|