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

Commit 2cfff78

Browse files
authored
Merge pull request #2545 from ethereum/issue/2539
IpcProvider chunks handling fix
2 parents 52717e0 + 293e07e commit 2cfff78

File tree

2 files changed

+74
-10
lines changed

2 files changed

+74
-10
lines changed

packages/web3-providers/src/providers/IpcProvider.js

+29-8
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ export default class IpcProvider extends AbstractSocketProvider {
3535
constructor(connection, path) {
3636
super(connection, null);
3737
this.host = path;
38-
this.chunks = '';
38+
this.lastChunk = '';
3939
}
4040

4141
/**
@@ -71,16 +71,37 @@ export default class IpcProvider extends AbstractSocketProvider {
7171
* @param {String|Buffer} message
7272
*/
7373
onMessage(message) {
74-
const chunk = message.toString('utf8');
74+
let result = null;
75+
let returnValues = [];
76+
let dechunkedData = message
77+
.toString()
78+
.replace(/\}[\n\r]?\{/g, '}|--|{') // }{
79+
.replace(/\}\][\n\r]?\[\{/g, '}]|--|[{') // }][{
80+
.replace(/\}[\n\r]?\[\{/g, '}|--|[{') // }[{
81+
.replace(/\}\][\n\r]?\{/g, '}]|--|{') // }]{
82+
.split('|--|');
83+
84+
dechunkedData.forEach((data) => {
85+
result = null;
86+
if (this.lastChunk) {
87+
data = this.lastChunk + data;
88+
}
7589

76-
if (chunk.indexOf('\n') < 0) {
77-
this.chunks += chunk;
90+
try {
91+
result = JSON.parse(data);
92+
} catch (error) {
93+
this.lastChunk = data;
7894

79-
return;
80-
}
95+
return;
96+
}
8197

82-
super.onMessage(this.chunks + chunk.substring(0, chunk.indexOf('\n')));
83-
this.chunks = chunk.substring(chunk.indexOf('\n') + 1);
98+
this.lastChunk = null;
99+
returnValues.push(result);
100+
});
101+
102+
returnValues.forEach((chunk) => {
103+
super.onMessage(chunk);
104+
});
84105
}
85106

86107
/**

packages/web3-providers/tests/src/providers/IpcProviderTest.js

+45-2
Original file line numberDiff line numberDiff line change
@@ -66,16 +66,59 @@ describe('IpcProviderTest', () => {
6666
expect(socketMock.connect).toHaveBeenCalledWith({path: ipcProvider.path});
6767
});
6868

69-
it('calls onMessage', () => {
69+
it('calls onMessage with one chunk', (done) => {
7070
const objWithToString = {
7171
toString: jest.fn(() => {
7272
return '{"id":"0x0"}';
7373
})
7474
};
7575

76+
ipcProvider.on('0x0', (response) => {
77+
expect(response).toEqual({id: '0x0'});
78+
79+
done();
80+
});
81+
7682
ipcProvider.onMessage(objWithToString);
7783

78-
expect(objWithToString.toString).toHaveBeenCalled();
84+
expect(objWithToString.toString).toHaveBeenCalledWith();
85+
});
86+
87+
it('calls onMessage with more than one chunk', (done) => {
88+
let callCount = 0;
89+
const firstChunk = {
90+
toString: jest.fn(() => {
91+
return '{"id":"0x0"}{"id":"0x0"}';
92+
})
93+
};
94+
const secondChunk = {
95+
toString: jest.fn(() => {
96+
return '{"id":"0x0"}{"id":"0x';
97+
})
98+
};
99+
const thirdChunk = {
100+
toString: jest.fn(() => {
101+
return '0"}';
102+
})
103+
};
104+
105+
ipcProvider.on('0x0', (response) => {
106+
expect(response).toEqual({id: '0x0'});
107+
108+
if (callCount === 1) {
109+
done();
110+
}
111+
112+
callCount++;
113+
});
114+
115+
ipcProvider.onMessage(firstChunk);
116+
ipcProvider.onMessage(secondChunk);
117+
ipcProvider.onMessage(thirdChunk);
118+
119+
expect(firstChunk.toString).toHaveBeenCalledWith();
120+
expect(secondChunk.toString).toHaveBeenCalledWith();
121+
expect(thirdChunk.toString).toHaveBeenCalledWith();
79122
});
80123

81124
it('calls registEventListener with a Socket object as connection', () => {

0 commit comments

Comments
 (0)