| 1171 | // The payload is automatically disposed after the call completes. The caller should not call |
| 1172 | // dispose(). |
| 1173 | public async deliverCall(func: Function, thisArg: object | undefined): Promise<RpcPayload> { |
| 1174 | try { |
| 1175 | let promises: Promise<void>[] = []; |
| 1176 | this.deliverTo(this, "value", promises); |
| 1177 | |
| 1178 | // WARNING: It is critical that if the promises list is empty, we do not await anything, so |
| 1179 | // that the function is called immediately and synchronously. Otherwise, we might violate |
| 1180 | // e-order. |
| 1181 | if (promises.length > 0) { |
| 1182 | await Promise.all(promises); |
| 1183 | } |
| 1184 | |
| 1185 | // Call the function. |
| 1186 | let result = Function.prototype.apply.call(func, thisArg, this.value); |
| 1187 | |
| 1188 | if (result instanceof RpcPromise) { |
| 1189 | // Special case: If the function immediately returns RpcPromise, we don't want to await it, |
| 1190 | // since that will actually wait for the promise. Instead we want to construct a payload |
| 1191 | // around it directly. |
| 1192 | return RpcPayload.fromAppReturn(result); |
| 1193 | } else { |
| 1194 | // In all other cases, await the result (which may or may not be a promise, but `await` |
| 1195 | // will just pass through non-promises). |
| 1196 | return RpcPayload.fromAppReturn(await result); |
| 1197 | } |
| 1198 | } finally { |
| 1199 | this.dispose(); |
| 1200 | } |
| 1201 | } |
| 1202 | |
| 1203 | // Produce a promise for this payload for return to the application. Any RpcPromises in the |
| 1204 | // payload are awaited and substituted with their results first. |