Skip to content
This repository was archived by the owner on Jul 10, 2025. It is now read-only.

Commit cabbe89

Browse files
authored
Fixed issue when a variable passed to Request flow could be undefined (#55)
1 parent 67a1f91 commit cabbe89

File tree

4 files changed

+38
-5
lines changed

4 files changed

+38
-5
lines changed

src/__test__/integration/client.spec.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { checkConnection, createClient, FluenceClient } from '../../FluenceClien
22
import Multiaddr from 'multiaddr';
33
import { nodes } from '../connection';
44
import { RequestFlowBuilder } from '../../internal/RequestFlowBuilder';
5+
import log from 'loglevel';
56

67
let client: FluenceClient;
78

@@ -245,6 +246,29 @@ describe('Typescript usage suite', () => {
245246
});
246247
});
247248

249+
it('Should not crash if undefined is passed as a variable', async () => {
250+
// arrange
251+
client = await createClient();
252+
const [request, promise] = new RequestFlowBuilder()
253+
.withRawScript(
254+
`
255+
(seq
256+
(call %init_peer_id% ("op" "identity") [arg] res)
257+
(call %init_peer_id% ("return" "return") [res])
258+
)
259+
`,
260+
)
261+
.withVariable('arg', undefined as any)
262+
.buildAsFetch<any[]>('return', 'return');
263+
264+
// act
265+
await client.initiateFlow(request);
266+
const [res] = await promise;
267+
268+
// assert
269+
expect(res).toBe(null);
270+
});
271+
248272
it('Should throw correct error when the client tries to send a particle not to the relay', async () => {
249273
// arrange
250274
client = await createClient();

src/internal/CallServiceHandler.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ export interface CallServiceData {
5353
/**
5454
* Type for all the possible ovjects that can be return to the AVM
5555
*/
56-
export type CallServiceResultType = object | boolean | number | string;
56+
export type CallServiceResultType = object | boolean | number | string | null;
5757

5858
/**
5959
* Represents the result of the `call` air instruction to be returned into AVM

src/internal/ClientImpl.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,13 @@ export class ClientImpl implements FluenceClient {
207207
},
208208
});
209209

210+
if (res.result === undefined) {
211+
log.error(
212+
`Call to serviceId=${serviceId} fnName=${fnName} unexpectedly returned undefined result, falling back to null`,
213+
);
214+
res.result = null;
215+
}
216+
210217
return {
211218
ret_code: res.retCode,
212219
result: JSON.stringify(res.result),

src/internal/RequestFlowBuilder.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import log from 'loglevel';
2-
import { CallServiceHandler } from './CallServiceHandler';
2+
import { CallServiceHandler, CallServiceResultType } from './CallServiceHandler';
33
import { DEFAULT_TTL, RequestFlow } from './RequestFlow';
44

55
export const loadVariablesService = 'load';
@@ -100,7 +100,7 @@ export class RequestFlowBuilder {
100100
private shouldInjectRelay: boolean = true;
101101

102102
private ttl: number = DEFAULT_TTL;
103-
private variables = new Map<string, any>();
103+
private variables = new Map<string, CallServiceResultType>();
104104
private handlerConfigs: Array<(handler: CallServiceHandler, request: RequestFlow) => void> = [];
105105
private buildScriptActions: Array<(sb: ScriptBuilder) => void> = [];
106106
private onTimeout: () => void;
@@ -268,7 +268,7 @@ export class RequestFlowBuilder {
268268
/**
269269
* Adds a variable to the list of injected variables
270270
*/
271-
withVariable(name: string, value: any): RequestFlowBuilder {
271+
withVariable(name: string, value: CallServiceResultType): RequestFlowBuilder {
272272
this.variables.set(name, value);
273273
return this;
274274
}
@@ -277,7 +277,9 @@ export class RequestFlowBuilder {
277277
* Adds a multiple variable to the list of injected variables.
278278
* Variables can be specified in form of either object or a map where keys correspond to variable names
279279
*/
280-
withVariables(data: Map<string, any> | Record<string, any>): RequestFlowBuilder {
280+
withVariables(
281+
data: Map<string, CallServiceResultType> | Record<string, CallServiceResultType>,
282+
): RequestFlowBuilder {
281283
if (data instanceof Map) {
282284
this.variables = new Map([...Array.from(this.variables.entries()), ...Array.from(data.entries())]);
283285
} else {

0 commit comments

Comments
 (0)