diff --git a/packages/web3-providers/src/providers/IpcProvider.js b/packages/web3-providers/src/providers/IpcProvider.js index 11fe6629be4..1be45b70476 100644 --- a/packages/web3-providers/src/providers/IpcProvider.js +++ b/packages/web3-providers/src/providers/IpcProvider.js @@ -35,7 +35,7 @@ export default class IpcProvider extends AbstractSocketProvider { constructor(connection, path) { super(connection, null); this.host = path; - this.chunks = ''; + this.lastChunk = ''; } /** @@ -71,16 +71,37 @@ export default class IpcProvider extends AbstractSocketProvider { * @param {String|Buffer} message */ onMessage(message) { - const chunk = message.toString('utf8'); + let result = null; + let returnValues = []; + let dechunkedData = message + .toString() + .replace(/\}[\n\r]?\{/g, '}|--|{') // }{ + .replace(/\}\][\n\r]?\[\{/g, '}]|--|[{') // }][{ + .replace(/\}[\n\r]?\[\{/g, '}|--|[{') // }[{ + .replace(/\}\][\n\r]?\{/g, '}]|--|{') // }]{ + .split('|--|'); + + dechunkedData.forEach((data) => { + result = null; + if (this.lastChunk) { + data = this.lastChunk + data; + } - if (chunk.indexOf('\n') < 0) { - this.chunks += chunk; + try { + result = JSON.parse(data); + } catch (error) { + this.lastChunk = data; - return; - } + return; + } - super.onMessage(this.chunks + chunk.substring(0, chunk.indexOf('\n'))); - this.chunks = chunk.substring(chunk.indexOf('\n') + 1); + this.lastChunk = null; + returnValues.push(result); + }); + + returnValues.forEach((chunk) => { + super.onMessage(chunk); + }); } /** diff --git a/packages/web3-providers/tests/src/providers/IpcProviderTest.js b/packages/web3-providers/tests/src/providers/IpcProviderTest.js index 402ccca800f..284044bd7c4 100644 --- a/packages/web3-providers/tests/src/providers/IpcProviderTest.js +++ b/packages/web3-providers/tests/src/providers/IpcProviderTest.js @@ -66,16 +66,59 @@ describe('IpcProviderTest', () => { expect(socketMock.connect).toHaveBeenCalledWith({path: ipcProvider.path}); }); - it('calls onMessage', () => { + it('calls onMessage with one chunk', (done) => { const objWithToString = { toString: jest.fn(() => { return '{"id":"0x0"}'; }) }; + ipcProvider.on('0x0', (response) => { + expect(response).toEqual({id: '0x0'}); + + done(); + }); + ipcProvider.onMessage(objWithToString); - expect(objWithToString.toString).toHaveBeenCalled(); + expect(objWithToString.toString).toHaveBeenCalledWith(); + }); + + it('calls onMessage with more than one chunk', (done) => { + let callCount = 0; + const firstChunk = { + toString: jest.fn(() => { + return '{"id":"0x0"}{"id":"0x0"}'; + }) + }; + const secondChunk = { + toString: jest.fn(() => { + return '{"id":"0x0"}{"id":"0x'; + }) + }; + const thirdChunk = { + toString: jest.fn(() => { + return '0"}'; + }) + }; + + ipcProvider.on('0x0', (response) => { + expect(response).toEqual({id: '0x0'}); + + if (callCount === 1) { + done(); + } + + callCount++; + }); + + ipcProvider.onMessage(firstChunk); + ipcProvider.onMessage(secondChunk); + ipcProvider.onMessage(thirdChunk); + + expect(firstChunk.toString).toHaveBeenCalledWith(); + expect(secondChunk.toString).toHaveBeenCalledWith(); + expect(thirdChunk.toString).toHaveBeenCalledWith(); }); it('calls registEventListener with a Socket object as connection', () => {