| 446 | }; |
| 447 | |
| 448 | class RpcSessionImpl implements Importer, Exporter { |
| 449 | private exports: Array<ExportTableEntry> = []; |
| 450 | private reverseExports: Map<StubHook, ExportId> = new Map(); |
| 451 | private imports: Array<ImportTableEntry> = []; |
| 452 | private abortReason?: any; |
| 453 | private cancelReadLoop?: (error: any) => void; |
| 454 | |
| 455 | // We assign positive numbers to imports we initiate, and negative numbers to exports we |
| 456 | // initiate. So the next import ID is just `imports.length`, but the next export ID needs |
| 457 | // to be tracked explicitly. |
| 458 | private nextExportId = -1; |
| 459 | |
| 460 | // If set, call this when all incoming calls are complete. |
| 461 | private onBatchDone?: Omit<PromiseWithResolvers<void>, "promise">; |
| 462 | |
| 463 | // How many promises is our peer expecting us to resolve? |
| 464 | private pullCount = 0; |
| 465 | |
| 466 | // Sparse array of onBrokenCallback registrations. Items are strictly appended to the end but |
| 467 | // may be deleted from the middle (hence leaving the array sparse). |
| 468 | onBrokenCallbacks: ((error: any) => void)[] = []; |
| 469 | |
| 470 | // Encoding level from the transport (defaults to "string") |
| 471 | private encodingLevel: EncodingLevel; |
| 472 | |
| 473 | constructor(private transport: AnyRpcTransport, mainHook: StubHook, |
| 474 | private options: RpcSessionOptions) { |
| 475 | // `RpcTransport` has no `encodingLevel` field, so its presence is what marks a custom-encoding |
| 476 | // transport. Read it defensively: treat a present-but-`undefined` value (e.g. an uninitialized |
| 477 | // class field) as the default string level rather than mis-routing it down the custom-encoding |
| 478 | // path, and reject any other unrecognized value (e.g. a stale pre-rename level name) loudly |
| 479 | // instead of silently corrupting the wire. |
| 480 | let level: EncodingLevel = "string"; |
| 481 | if ('encodingLevel' in transport) { |
| 482 | let raw = transport.encodingLevel as unknown; |
| 483 | if (raw !== undefined) { |
| 484 | if (raw !== "string" && raw !== "jsonCompatible" && |
| 485 | raw !== "jsonCompatibleWithBytes" && raw !== "structuredClonable") { |
| 486 | throw new TypeError(`Unknown transport encodingLevel: ${String(raw)}`); |
| 487 | } |
| 488 | level = raw; |
| 489 | } |
| 490 | } |
| 491 | this.encodingLevel = level; |
| 492 | // Export zero is automatically the bootstrap object. |
| 493 | this.exports.push({hook: mainHook, refcount: 1}); |
| 494 | |
| 495 | // Import zero is the other side's bootstrap object. |
| 496 | this.imports.push(new ImportTableEntry(this, 0, false)); |
| 497 | |
| 498 | this.readLoop().catch(err => this.abort(err)); |
| 499 | } |
| 500 | |
| 501 | // Should only be called once immediately after construction. |
| 502 | getMainImport(): RpcImportHook { |
| 503 | return new RpcMainHook(this.imports[0]); |
| 504 | } |
| 505 |
nothing calls this directly
no outgoing calls
no test coverage detected
searching dependent graphs…