1 |
|
2 | (function (global, factory) {
|
3 | typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
|
4 | typeof define === 'function' && define.amd ? define(['exports'], factory) :
|
5 | (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.AsyncCall = {}));
|
6 | }(this, (function (exports) { 'use strict';
|
7 |
|
8 | class CustomError extends Error {
|
9 | constructor( name, message, code, stack) {
|
10 | super(message);this.name = name;this.code = code;this.stack = stack;
|
11 | }
|
12 | }
|
13 | const Err_Cannot_find_a_running_iterator_with_given_ID = {};
|
14 | const Err_Only_string_can_be_the_RPC_method_name = {};
|
15 | const Err_Cannot_call_method_starts_with_rpc_dot_directly = {};
|
16 | const Err_Then_is_accessed_on_local_implementation_Please_explicitly_mark_if_it_is_thenable_in_the_options = {};
|
17 | const Messages = [
|
18 | Err_Cannot_find_a_running_iterator_with_given_ID,
|
19 | Err_Only_string_can_be_the_RPC_method_name,
|
20 | Err_Cannot_call_method_starts_with_rpc_dot_directly,
|
21 | Err_Then_is_accessed_on_local_implementation_Please_explicitly_mark_if_it_is_thenable_in_the_options,
|
22 | ];
|
23 |
|
24 | function makeHostedMessage(id, error) {
|
25 | const n = Messages.indexOf(id);
|
26 | error.message += `Error ${n}: https://github.com/Jack-Works/async-call-rpc/wiki/Errors#` + n;
|
27 | return error
|
28 | }
|
29 |
|
30 |
|
31 | const errors = {
|
32 |
|
33 | __proto__: null,
|
34 | Error,
|
35 | EvalError,
|
36 | RangeError,
|
37 | ReferenceError,
|
38 | SyntaxError,
|
39 | TypeError,
|
40 | URIError,
|
41 | };
|
42 | const DOMExceptionHeader = 'DOMException:';
|
43 | |
44 |
|
45 |
|
46 | const RecoverError = (type, message, code, stack) => {
|
47 | try {
|
48 | const E = globalDOMException();
|
49 | if (type.startsWith(DOMExceptionHeader) && E) {
|
50 | const name = type.slice(DOMExceptionHeader.length);
|
51 | return new E(message, name)
|
52 | } else if (type in errors) {
|
53 | const e = new errors[type](message);
|
54 | e.stack = stack;
|
55 |
|
56 | e.code = code;
|
57 | return e
|
58 | } else {
|
59 | return new CustomError(type, message, code, stack)
|
60 | }
|
61 | } catch (e2) {
|
62 | return new Error(`E${code} ${type}: ${message}\n${stack}`)
|
63 | }
|
64 | };
|
65 | const removeStackHeader = (stack) => String(stack).replace(/^.+\n.+\n/, '');
|
66 |
|
67 | const globalDOMException = (() => {
|
68 | try {
|
69 |
|
70 | return DOMException
|
71 | } catch (e3) {}
|
72 | });
|
73 |
|
74 | const isString = (x) => typeof x === 'string';
|
75 | const isBoolean = (x) => typeof x === 'boolean';
|
76 | const isFunction = (x) => typeof x === 'function';
|
77 | const isObject = (params) => typeof params === 'object' && params !== null;
|
78 | const ERROR = 'Error';
|
79 | const undefined$1 = void 0;
|
80 | const Object_setPrototypeOf = Object.setPrototypeOf;
|
81 | const Promise_reject = (x) => Promise.reject(x);
|
82 | const Promise_resolve = (x) => Promise.resolve(x);
|
83 | const isArray = Array.isArray;
|
84 | const replayFunction = () => '() => replay()';
|
85 |
|
86 | const jsonrpc = '2.0';
|
87 |
|
88 |
|
89 |
|
90 |
|
91 |
|
92 |
|
93 |
|
94 |
|
95 |
|
96 |
|
97 |
|
98 |
|
99 |
|
100 | const Request = (id, method, params, remoteStack) => {
|
101 | const x = { jsonrpc, id, method, params, remoteStack };
|
102 | deleteUndefined(x, 'id');
|
103 | deleteFalsy(x, 'remoteStack');
|
104 | return x
|
105 | };
|
106 |
|
107 | |
108 |
|
109 |
|
110 |
|
111 |
|
112 |
|
113 |
|
114 |
|
115 |
|
116 | const SuccessResponse = (id, result) => {
|
117 | const x = { jsonrpc, id, result };
|
118 | deleteUndefined(x, 'id');
|
119 | return x
|
120 | };
|
121 |
|
122 | |
123 |
|
124 |
|
125 |
|
126 |
|
127 |
|
128 |
|
129 |
|
130 |
|
131 |
|
132 |
|
133 | const ErrorResponse = (id, code, message, data) => {
|
134 | if (id === undefined$1) id = null;
|
135 | code = Math.floor(code);
|
136 | if (Number.isNaN(code)) code = -1;
|
137 | const x = { jsonrpc, id, error: { code, message, data } };
|
138 | deleteUndefined(x.error, 'data');
|
139 | return x
|
140 | };
|
141 |
|
142 |
|
143 | const ErrorResponseParseError = (e, mapper) => {
|
144 | const obj = ErrorResponseMapped({} , e, mapper);
|
145 | const o = obj.error;
|
146 | o.code = -32700;
|
147 | o.message = 'Parse error';
|
148 | return obj
|
149 | };
|
150 |
|
151 |
|
152 |
|
153 |
|
154 | const ErrorResponseInvalidRequest = (id) => ErrorResponse(id, -32600, 'Invalid Request');
|
155 | const ErrorResponseMethodNotFound = (id) => ErrorResponse(id, -32601, 'Method not found');
|
156 |
|
157 |
|
158 |
|
159 |
|
160 |
|
161 | const ErrorResponseMapped = (request, e, mapper) => {
|
162 | const { id } = request;
|
163 | const { code, message, data } = mapper(e, request);
|
164 | return ErrorResponse(id, code, message, data)
|
165 | };
|
166 |
|
167 | const defaultErrorMapper = (stack = '', code = -1) => (e) => {
|
168 | let message = toString('', () => (e ).message);
|
169 | let type = toString(ERROR, (ctor = (e ).constructor) => isFunction(ctor) && ctor.name);
|
170 | const E = globalDOMException();
|
171 | if (E && e instanceof E) type = DOMExceptionHeader + e.name;
|
172 | if (isString(e) || typeof e === 'number' || isBoolean(e) || typeof e === 'bigint') {
|
173 | type = ERROR;
|
174 | message = String(e);
|
175 | }
|
176 | const data = stack ? { stack, type } : { type };
|
177 | return { code, message, data }
|
178 | };
|
179 |
|
180 | |
181 |
|
182 |
|
183 |
|
184 |
|
185 | const isJSONRPCObject = (data) => {
|
186 | if (!isObject(data)) return false
|
187 | if (!hasKey(data, 'jsonrpc')) return false
|
188 | if (data.jsonrpc !== jsonrpc) return false
|
189 | if (hasKey(data, 'params')) {
|
190 | const params = (data ).params;
|
191 | if (!isArray(params) && !isObject(params)) return false
|
192 | }
|
193 | return true
|
194 | };
|
195 |
|
196 | const hasKey = (
|
197 | obj,
|
198 | key,
|
199 |
|
200 |
|
201 |
|
202 | ) => key in obj;
|
203 |
|
204 | const toString = (_default, val) => {
|
205 | try {
|
206 | const v = val();
|
207 | if (v === undefined$1) return _default
|
208 | return String(v)
|
209 | } catch (e2) {
|
210 | return _default
|
211 | }
|
212 | };
|
213 | const deleteUndefined = (x, key) => {
|
214 | if (x[key] === undefined$1) delete x[key];
|
215 | };
|
216 | const deleteFalsy = (x, key) => {
|
217 | if (!x[key]) delete x[key];
|
218 | };
|
219 |
|
220 |
|
221 |
|
222 |
|
223 |
|
224 | |
225 |
|
226 |
|
227 |
|
228 |
|
229 | const NoSerialization = {
|
230 | serialization(from) {
|
231 | return from
|
232 | },
|
233 | deserialization(serialized) {
|
234 | return serialized
|
235 | },
|
236 | };
|
237 |
|
238 | |
239 |
|
240 |
|
241 |
|
242 |
|
243 |
|
244 |
|
245 |
|
246 |
|
247 |
|
248 |
|
249 |
|
250 |
|
251 |
|
252 |
|
253 |
|
254 | const JSONSerialization = (
|
255 | replacerAndReceiver = [
|
256 | undefined$1,
|
257 | undefined$1,
|
258 | ],
|
259 | space,
|
260 | undefinedKeepingBehavior = 'null',
|
261 | ) => ({
|
262 | serialization(from) {
|
263 | if (undefinedKeepingBehavior && isObject(from) && hasKey(from, 'result') && from.result === undefined$1) {
|
264 | const alt = { ...from };
|
265 | alt.result = null;
|
266 | if (undefinedKeepingBehavior === 'keep') (alt ).undef = true;
|
267 | from = alt;
|
268 | }
|
269 | return JSON.stringify(from, replacerAndReceiver[0], space)
|
270 | },
|
271 | deserialization(serialized) {
|
272 | const result = JSON.parse(serialized , replacerAndReceiver[1]);
|
273 | if (
|
274 | isObject(result) &&
|
275 | hasKey(result, 'result') &&
|
276 | result.result === null &&
|
277 | hasKey(result, 'undef') &&
|
278 | result.undef === true
|
279 | ) {
|
280 | result.result = undefined$1;
|
281 | delete result.undef;
|
282 | }
|
283 | return result
|
284 | },
|
285 | });
|
286 |
|
287 |
|
288 | const i$1 = 'AsyncCall/';
|
289 |
|
290 | const AsyncCallIgnoreResponse = Symbol.for(i$1 + 'ignored');
|
291 | const AsyncCallNotify = Symbol.for(i$1 + 'notify');
|
292 | const AsyncCallBatch = Symbol.for(i$1 + 'batch');
|
293 |
|
294 | |
295 |
|
296 |
|
297 |
|
298 |
|
299 |
|
300 |
|
301 |
|
302 |
|
303 |
|
304 |
|
305 |
|
306 |
|
307 |
|
308 |
|
309 |
|
310 |
|
311 |
|
312 |
|
313 | |
314 |
|
315 |
|
316 |
|
317 |
|
318 |
|
319 |
|
320 |
|
321 | function notify(instanceOrFnOnInstance) {
|
322 | if (isFunction(instanceOrFnOnInstance)) return (instanceOrFnOnInstance )[AsyncCallNotify]
|
323 | return new Proxy(instanceOrFnOnInstance, { get: notifyTrap })
|
324 | }
|
325 | const notifyTrap = (target, p) => {
|
326 | return target[p][AsyncCallNotify]
|
327 | };
|
328 |
|
329 | |
330 |
|
331 |
|
332 |
|
333 |
|
334 |
|
335 |
|
336 |
|
337 |
|
338 |
|
339 |
|
340 |
|
341 |
|
342 |
|
343 |
|
344 |
|
345 |
|
346 |
|
347 | function batch(asyncCallInstance) {
|
348 | let queue = [];
|
349 | return [
|
350 | new Proxy({ __proto__: null } , {
|
351 | get(cache, p) {
|
352 | if (isString(p) && cache[p]) return cache[p]
|
353 |
|
354 | const f = (...args) => asyncCallInstance[AsyncCallBatch](queue, p, ...args);
|
355 |
|
356 | f[AsyncCallNotify] = (...args) =>
|
357 |
|
358 | asyncCallInstance[AsyncCallBatch][AsyncCallNotify](queue, p, ...args);
|
359 |
|
360 | f[AsyncCallNotify][AsyncCallNotify] = f[AsyncCallNotify];
|
361 | isString(p) && Object.defineProperty(cache, p, { value: f, configurable: true });
|
362 | return f
|
363 | },
|
364 | }),
|
365 | (r = queue.r) => r && r[0](),
|
366 | (error = new Error('Aborted'), r = queue.r) => {
|
367 | r && r[1](error);
|
368 | queue = [];
|
369 | },
|
370 | ]
|
371 | }
|
372 |
|
373 | const generateRandomID = () => Math.random().toString(36).slice(2);
|
374 |
|
375 | const undefinedToTrue = (x) => (x === void 0 ? true : x);
|
376 |
|
377 |
|
378 |
|
379 |
|
380 |
|
381 |
|
382 |
|
383 |
|
384 |
|
385 | const normalizeLogOptions = (log) => {
|
386 | if (log === 'all') return [true, true, true, true, true, true]
|
387 | if (!isBoolean(log)) {
|
388 | const { beCalled, localError, remoteError, type, requestReplay, sendLocalStack } = log;
|
389 | return [
|
390 | undefinedToTrue(beCalled),
|
391 | undefinedToTrue(localError),
|
392 | undefinedToTrue(remoteError),
|
393 | type !== 'basic',
|
394 | requestReplay,
|
395 | sendLocalStack,
|
396 | ]
|
397 | }
|
398 | if (log) return [true, true, true, true]
|
399 | return []
|
400 | };
|
401 |
|
402 | const normalizeStrictOptions = (strict) => {
|
403 | if (!isBoolean(strict)) {
|
404 | const { methodNotFound, unknownMessage } = strict;
|
405 | return [methodNotFound, unknownMessage]
|
406 | }
|
407 | return [strict, strict]
|
408 | };
|
409 |
|
410 | |
411 |
|
412 |
|
413 |
|
414 |
|
415 |
|
416 |
|
417 |
|
418 |
|
419 |
|
420 |
|
421 |
|
422 |
|
423 |
|
424 |
|
425 |
|
426 |
|
427 |
|
428 | function AsyncCall(
|
429 | thisSideImplementation,
|
430 | options,
|
431 | ) {
|
432 | let isThisSideImplementationPending = true;
|
433 | let resolvedThisSideImplementationValue = undefined$1;
|
434 | let rejectedThisSideImplementation = undefined$1;
|
435 |
|
436 | const awaitThisSideImplementation = async () => {
|
437 | try {
|
438 | resolvedThisSideImplementationValue = await thisSideImplementation;
|
439 | } catch (e) {
|
440 | rejectedThisSideImplementation = e;
|
441 | console_error('AsyncCall failed to start', e);
|
442 | } finally {
|
443 | isThisSideImplementationPending = false;
|
444 | }
|
445 | };
|
446 |
|
447 | const {
|
448 | serializer = NoSerialization,
|
449 | key: logKey = 'rpc',
|
450 | strict = true,
|
451 | log = true,
|
452 | parameterStructures = 'by-position',
|
453 | preferLocalImplementation = false,
|
454 | idGenerator = generateRandomID,
|
455 | mapError,
|
456 | logger,
|
457 | channel,
|
458 | thenable,
|
459 | } = options;
|
460 |
|
461 | if (thisSideImplementation instanceof Promise) awaitThisSideImplementation();
|
462 | else {
|
463 | resolvedThisSideImplementationValue = thisSideImplementation;
|
464 | isThisSideImplementationPending = false;
|
465 | }
|
466 |
|
467 | const [banMethodNotFound, banUnknownMessage] = normalizeStrictOptions(strict);
|
468 | const [
|
469 | log_beCalled,
|
470 | log_localError,
|
471 | log_remoteError,
|
472 | log_pretty,
|
473 | log_requestReplay,
|
474 | log_sendLocalStack,
|
475 | ] = normalizeLogOptions(log);
|
476 | const {
|
477 | log: console_log,
|
478 | error: console_error = console_log,
|
479 | debug: console_debug = console_log,
|
480 | groupCollapsed: console_groupCollapsed = console_log,
|
481 | groupEnd: console_groupEnd = console_log,
|
482 | warn: console_warn = console_log,
|
483 | } = (logger || console);
|
484 |
|
485 | const requestContext = new Map();
|
486 | const onRequest = async (data) => {
|
487 | if (isThisSideImplementationPending) await awaitThisSideImplementation();
|
488 | else {
|
489 |
|
490 | if (rejectedThisSideImplementation) return makeErrorObject(rejectedThisSideImplementation, '', data)
|
491 | }
|
492 | let frameworkStack = '';
|
493 | try {
|
494 | const { params, method, id: req_id, remoteStack } = data;
|
495 |
|
496 | const key = (method.startsWith('rpc.') ? Symbol.for(method) : method);
|
497 | const executor =
|
498 | resolvedThisSideImplementationValue && (resolvedThisSideImplementationValue )[key];
|
499 | if (!isFunction(executor)) {
|
500 | if (!banMethodNotFound) {
|
501 | if (log_localError) console_debug('Missing method', key, data);
|
502 | return
|
503 | } else return ErrorResponseMethodNotFound(req_id)
|
504 | }
|
505 | const args = isArray(params) ? params : [params];
|
506 | frameworkStack = removeStackHeader(new Error().stack);
|
507 | const promise = new Promise((resolve) => resolve(executor.apply(resolvedThisSideImplementationValue, args)));
|
508 | if (log_beCalled) {
|
509 | if (log_pretty) {
|
510 | const logArgs = [
|
511 | `${logKey}.%c${method}%c(${args.map(() => '%o').join(', ')}%c)\n%o %c@${req_id}`,
|
512 | 'color: #d2c057',
|
513 | '',
|
514 | ...args,
|
515 | '',
|
516 | promise,
|
517 | 'color: gray; font-style: italic;',
|
518 | ];
|
519 | if (log_requestReplay) {
|
520 |
|
521 |
|
522 | const replay = () => { debugger; return executor.apply(resolvedThisSideImplementationValue, args) };
|
523 | replay.toString = replayFunction;
|
524 | logArgs.push(replay);
|
525 | }
|
526 | if (remoteStack) {
|
527 | console_groupCollapsed(...logArgs);
|
528 | console_log(remoteStack);
|
529 | console_groupEnd();
|
530 | } else console_log(...logArgs);
|
531 | } else console_log(`${logKey}.${method}(${[...args].toString()}) @${req_id}`);
|
532 | }
|
533 | const result = await promise;
|
534 | if (result === AsyncCallIgnoreResponse) return
|
535 | return SuccessResponse(req_id, await promise)
|
536 | } catch (e) {
|
537 | return makeErrorObject(e, frameworkStack, data)
|
538 | }
|
539 | };
|
540 | const onResponse = async (data) => {
|
541 | let errorMessage = '',
|
542 | remoteErrorStack = '',
|
543 | errorCode = 0,
|
544 | errorType = ERROR;
|
545 | if (hasKey(data, 'error')) {
|
546 | const e = data.error;
|
547 | errorMessage = e.message;
|
548 | errorCode = e.code;
|
549 | const detail = e.data;
|
550 |
|
551 | if (isObject(detail) && hasKey(detail, 'stack') && isString(detail.stack)) remoteErrorStack = detail.stack;
|
552 | else remoteErrorStack = '<remote stack not available>';
|
553 |
|
554 | if (isObject(detail) && hasKey(detail, 'type') && isString(detail.type)) errorType = detail.type;
|
555 | else errorType = ERROR;
|
556 |
|
557 | if (log_remoteError)
|
558 | log_pretty
|
559 | ? console_error(
|
560 | `${errorType}: ${errorMessage}(${errorCode}) %c@${data.id}\n%c${remoteErrorStack}`,
|
561 | 'color: gray',
|
562 | '',
|
563 | )
|
564 | : console_error(`${errorType}: ${errorMessage}(${errorCode}) @${data.id}\n${remoteErrorStack}`);
|
565 | }
|
566 | if (data.id === null || data.id === undefined$1) return
|
567 | const { f: [resolve, reject] = [null, null], stack: localErrorStack = '' } = requestContext.get(data.id) || {};
|
568 | if (!resolve || !reject) return
|
569 | requestContext.delete(data.id);
|
570 | if (hasKey(data, 'error')) {
|
571 | reject(
|
572 | RecoverError(
|
573 | errorType,
|
574 | errorMessage,
|
575 | errorCode,
|
576 |
|
577 | remoteErrorStack + '\n \u0430t AsyncCall (rpc) \n' + localErrorStack,
|
578 | ),
|
579 | );
|
580 | } else {
|
581 | resolve(data.result);
|
582 | }
|
583 | return
|
584 | };
|
585 | const rawMessageReceiver = async (_) => {
|
586 | let data;
|
587 | let result = undefined$1;
|
588 | try {
|
589 | data = await deserialization(_);
|
590 | if (isJSONRPCObject(data)) {
|
591 | return (result = await handleSingleMessage(data))
|
592 | } else if (isArray(data) && data.every(isJSONRPCObject) && data.length !== 0) {
|
593 | return Promise.all(data.map(handleSingleMessage))
|
594 | } else {
|
595 | if (banUnknownMessage) {
|
596 | let id = (data ).id;
|
597 | if (id === undefined$1) id = null;
|
598 | return ErrorResponseInvalidRequest(id)
|
599 | } else {
|
600 |
|
601 | return undefined$1
|
602 | }
|
603 | }
|
604 | } catch (e) {
|
605 | if (log_localError) console_error(e, data, result);
|
606 | return ErrorResponseParseError(e, mapError || defaultErrorMapper(e && e.stack))
|
607 | }
|
608 | };
|
609 | const rawMessageSender = async (res) => {
|
610 | if (!res) return
|
611 | if (isArray(res)) {
|
612 | const reply = res.filter((x) => x && hasKey(x, 'id'));
|
613 | if (reply.length === 0) return
|
614 | return serialization(reply)
|
615 | } else {
|
616 | return serialization(res)
|
617 | }
|
618 | };
|
619 | const serialization = (x) => serializer.serialization(x);
|
620 | const deserialization = (x) => serializer.deserialization(x);
|
621 | const isEventBasedChannel = (x) => hasKey(x, 'send') && isFunction(x.send);
|
622 | const isCallbackBasedChannel = (x) =>
|
623 | hasKey(x, 'setup') && isFunction(x.setup);
|
624 |
|
625 | if (isCallbackBasedChannel(channel)) {
|
626 | channel.setup(
|
627 | (data) => rawMessageReceiver(data).then(rawMessageSender),
|
628 | (data) => {
|
629 | const _ = deserialization(data);
|
630 | if (isJSONRPCObject(_)) return true
|
631 | return Promise_resolve(_).then(isJSONRPCObject)
|
632 | },
|
633 | );
|
634 | }
|
635 | if (isEventBasedChannel(channel)) {
|
636 | const m = channel;
|
637 | m.on &&
|
638 | m.on((_) =>
|
639 | rawMessageReceiver(_)
|
640 | .then(rawMessageSender)
|
641 | .then((x) => x && m.send(x)),
|
642 | );
|
643 | }
|
644 | function makeErrorObject(e, frameworkStack, data) {
|
645 | if (isObject(e) && hasKey(e, 'stack'))
|
646 | e.stack = frameworkStack
|
647 | .split('\n')
|
648 | .reduce((stack, fstack) => stack.replace(fstack + '\n', ''), '' + e.stack);
|
649 | if (log_localError) console_error(e);
|
650 | return ErrorResponseMapped(data, e, mapError || defaultErrorMapper(log_sendLocalStack ? e.stack : undefined$1))
|
651 | }
|
652 |
|
653 | async function sendPayload(payload, removeQueueR = false) {
|
654 | if (removeQueueR) payload = [...(payload )];
|
655 | const data = await serialization(payload);
|
656 | return channel.send(data)
|
657 | }
|
658 | function rejectsQueue(queue, error) {
|
659 | for (const x of queue) {
|
660 | if (hasKey(x, 'id')) {
|
661 | const ctx = requestContext.get(x.id);
|
662 | ctx && ctx.f[1](error);
|
663 | }
|
664 | }
|
665 | }
|
666 | const handleSingleMessage = async (
|
667 | data,
|
668 | ) => {
|
669 | if (hasKey(data, 'method')) {
|
670 | const r = onRequest(data);
|
671 | if (hasKey(data, 'id')) return r
|
672 | try {
|
673 | await r;
|
674 | } catch (e2) {}
|
675 | return undefined$1
|
676 | }
|
677 | return onResponse(data)
|
678 | };
|
679 | return new Proxy({ __proto__: null } , {
|
680 | get(cache, method) {
|
681 | if (method === 'then') {
|
682 | if (thenable === undefined$1) {
|
683 | console_warn(
|
684 | makeHostedMessage(
|
685 | Err_Then_is_accessed_on_local_implementation_Please_explicitly_mark_if_it_is_thenable_in_the_options,
|
686 | new TypeError('RPC used as Promise: '),
|
687 | ),
|
688 | );
|
689 | }
|
690 | if (thenable !== true) return undefined$1
|
691 | }
|
692 | if (isString(method) && cache[method]) return cache[method]
|
693 | const factory = (notify) => (...params) => {
|
694 | let stack = removeStackHeader(new Error().stack);
|
695 | let queue = undefined$1;
|
696 | if (method === AsyncCallBatch) {
|
697 | queue = params.shift();
|
698 | method = params.shift();
|
699 | }
|
700 | if (typeof method === 'symbol') {
|
701 | const RPCInternalMethod = Symbol.keyFor(method) || (method ).description;
|
702 | if (RPCInternalMethod) {
|
703 | if (RPCInternalMethod.startsWith('rpc.')) method = RPCInternalMethod;
|
704 | else return Promise_reject(new TypeError('Not start with rpc.'))
|
705 | }
|
706 | } else if (method.startsWith('rpc.'))
|
707 | return Promise_reject(
|
708 | makeHostedMessage(Err_Cannot_call_method_starts_with_rpc_dot_directly, new TypeError()),
|
709 | )
|
710 | return new Promise((resolve, reject) => {
|
711 | if (preferLocalImplementation && !isThisSideImplementationPending && isString(method)) {
|
712 | const localImpl =
|
713 | resolvedThisSideImplementationValue && (resolvedThisSideImplementationValue )[method];
|
714 | if (isFunction(localImpl)) return resolve(localImpl(...params))
|
715 | }
|
716 | const id = idGenerator();
|
717 | const [param0] = params;
|
718 | const sendingStack = log_sendLocalStack ? stack : '';
|
719 | const param =
|
720 | parameterStructures === 'by-name' && params.length === 1 && isObject(param0) ? param0 : params;
|
721 | const request = Request(notify ? undefined$1 : id, method , param, sendingStack);
|
722 | if (queue) {
|
723 | queue.push(request);
|
724 | if (!queue.r) queue.r = [() => sendPayload(queue, true), (e) => rejectsQueue(queue, e)];
|
725 | } else sendPayload(request).catch(reject);
|
726 | if (notify) return resolve()
|
727 | requestContext.set(id, {
|
728 | f: [resolve, reject],
|
729 | stack,
|
730 | });
|
731 | })
|
732 | };
|
733 | const f = factory(false);
|
734 |
|
735 | f[AsyncCallNotify] = factory(true);
|
736 |
|
737 | f[AsyncCallNotify][AsyncCallNotify] = f[AsyncCallNotify];
|
738 | isString(method) && Object.defineProperty(cache, method, { value: f, configurable: true });
|
739 | return f
|
740 | },
|
741 | })
|
742 | }
|
743 |
|
744 |
|
745 | function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } |
746 |
|
747 |
|
748 |
|
749 | const i = 'rpc.async-iterator.';
|
750 |
|
751 | const AsyncIteratorStart = Symbol.for(i + 'start');
|
752 | const AsyncIteratorNext = Symbol.for(i + 'next');
|
753 | const AsyncIteratorReturn = Symbol.for(i + 'return');
|
754 | const AsyncIteratorThrow = Symbol.for(i + 'throw');
|
755 |
|
756 |
|
757 |
|
758 |
|
759 |
|
760 |
|
761 |
|
762 |
|
763 |
|
764 |
|
765 |
|
766 |
|
767 |
|
768 |
|
769 |
|
770 |
|
771 |
|
772 |
|
773 |
|
774 |
|
775 |
|
776 |
|
777 |
|
778 |
|
779 |
|
780 |
|
781 |
|
782 |
|
783 |
|
784 |
|
785 |
|
786 |
|
787 |
|
788 |
|
789 |
|
790 |
|
791 |
|
792 |
|
793 |
|
794 |
|
795 |
|
796 |
|
797 |
|
798 |
|
799 |
|
800 |
|
801 |
|
802 |
|
803 | |
804 |
|
805 |
|
806 |
|
807 |
|
808 |
|
809 |
|
810 |
|
811 |
|
812 |
|
813 |
|
814 |
|
815 |
|
816 |
|
817 |
|
818 |
|
819 |
|
820 |
|
821 |
|
822 |
|
823 |
|
824 |
|
825 |
|
826 |
|
827 |
|
828 |
|
829 |
|
830 |
|
831 |
|
832 |
|
833 |
|
834 |
|
835 |
|
836 |
|
837 |
|
838 |
|
839 | function AsyncGeneratorCall(
|
840 | thisSideImplementation,
|
841 | options,
|
842 | ) {
|
843 | const iterators = new Map();
|
844 | const [methodNotFound] = normalizeStrictOptions(_nullishCoalesce(options.strict, () => ( true)));
|
845 | const { idGenerator = generateRandomID } = options;
|
846 | const findIterator = (
|
847 | id,
|
848 | next,
|
849 | ) => {
|
850 | const it = iterators.get(id);
|
851 | if (!it) {
|
852 | if (methodNotFound)
|
853 | throw makeHostedMessage(Err_Cannot_find_a_running_iterator_with_given_ID, new Error(`Iterator ${id}, `))
|
854 | else return AsyncCallIgnoreResponse
|
855 | }
|
856 | const result = next(it);
|
857 | isFinished(result, () => iterators.delete(id));
|
858 | return result
|
859 | };
|
860 | const server = {
|
861 | async [AsyncIteratorStart](method, args) {
|
862 | const iteratorGenerator = ((await thisSideImplementation) )[method];
|
863 | if (!isFunction(iteratorGenerator)) {
|
864 | if (methodNotFound) throw new TypeError(method + ' is not a function')
|
865 | else return AsyncCallIgnoreResponse
|
866 | }
|
867 | const iterator = iteratorGenerator(...args);
|
868 | const id = idGenerator();
|
869 | iterators.set(id, iterator);
|
870 | return Promise_resolve(id)
|
871 | },
|
872 | [AsyncIteratorNext](id, val) {
|
873 | return findIterator(id, (it) => it.next(val ))
|
874 | },
|
875 | [AsyncIteratorReturn](id, val) {
|
876 | return findIterator(id, (it) => isFunction(it.return) && it.return(val))
|
877 | },
|
878 | [AsyncIteratorThrow](id, val) {
|
879 | return findIterator(id, (it) => isFunction(it.throw) && it.throw(val))
|
880 | },
|
881 | };
|
882 | const remote = AsyncCall(server, options);
|
883 | const proxyTrap = (cache, key) => {
|
884 | if (!isString(key))
|
885 | throw makeHostedMessage(Err_Only_string_can_be_the_RPC_method_name, new TypeError(''))
|
886 | if (cache[key]) return cache[key]
|
887 | const f = (...args) => {
|
888 | const id = remote[AsyncIteratorStart](key, args);
|
889 | return new _AsyncGenerator(remote, id)
|
890 | };
|
891 | Object.defineProperty(cache, key, { value: f, configurable: true });
|
892 | return f
|
893 | };
|
894 | return new Proxy({ __proto__: null }, { get: proxyTrap })
|
895 | }
|
896 | class _AsyncGenerator {
|
897 |
|
898 | __init() {this.d = false;}
|
899 |
|
900 | __init2() {this.c = async (val) => {
|
901 | await isFinished(val, () => (this.d = true));
|
902 | return val
|
903 | };}
|
904 | |
905 |
|
906 |
|
907 |
|
908 | constructor( r, i) {this.r = r;this.i = i;_AsyncGenerator.prototype.__init.call(this);_AsyncGenerator.prototype.__init2.call(this);}
|
909 | async return(val) {
|
910 | if (this.d) return makeIteratorResult(true, val)
|
911 | return this.c(this.r[AsyncIteratorReturn](await this.i, val))
|
912 | }
|
913 | async next(val) {
|
914 | if (this.d) return makeIteratorResult(true)
|
915 | return this.c(this.r[AsyncIteratorNext](await this.i, val))
|
916 | }
|
917 | async throw(val) {
|
918 | if (!this.d) return this.c(this.r[AsyncIteratorThrow](await this.i, val))
|
919 | throw val
|
920 | }
|
921 |
|
922 |
|
923 | }
|
924 |
|
925 | const EmptyAsyncGenerator = async function* () {};
|
926 | const AsyncGeneratorConstructor = EmptyAsyncGenerator.constructor;
|
927 | const AsyncGeneratorConstructorPrototype = AsyncGeneratorConstructor.prototype;
|
928 | Object_setPrototypeOf(_AsyncGenerator, AsyncGeneratorConstructorPrototype);
|
929 | const AsyncGeneratorPrototype = Object.getPrototypeOf(EmptyAsyncGenerator());
|
930 | Object_setPrototypeOf(_AsyncGenerator.prototype, AsyncGeneratorPrototype);
|
931 |
|
932 | const isFinished = async (result, cb) => {
|
933 | try {
|
934 | const x = await result;
|
935 | x && x.done && cb();
|
936 | } catch (e) {}
|
937 | };
|
938 |
|
939 | const makeIteratorResult = (done, value = undefined) => ({
|
940 | done,
|
941 | value,
|
942 | });
|
943 |
|
944 | exports.AsyncCall = AsyncCall;
|
945 | exports.AsyncGeneratorCall = AsyncGeneratorCall;
|
946 | exports.JSONSerialization = JSONSerialization;
|
947 | exports.NoSerialization = NoSerialization;
|
948 | exports.batch = batch;
|
949 | exports.notify = notify;
|
950 |
|
951 | Object.defineProperty(exports, '__esModule', { value: true });
|
952 |
|
953 | })));
|
954 |
|