diff --git a/app/scripts/lib/createMetaRPCHandler.js b/app/scripts/lib/createMetaRPCHandler.js index 24ac0ff6a..9b25c6ce7 100644 --- a/app/scripts/lib/createMetaRPCHandler.js +++ b/app/scripts/lib/createMetaRPCHandler.js @@ -2,6 +2,9 @@ import { ethErrors, serializeError } from 'eth-rpc-errors'; const createMetaRPCHandler = (api, outStream) => { return (data) => { + if (outStream._writableState.ended) { + return; + } if (!api[data.method]) { outStream.write({ jsonrpc: '2.0', @@ -13,6 +16,9 @@ const createMetaRPCHandler = (api, outStream) => { return; } api[data.method](...data.params, (err, result) => { + if (outStream._writableState.ended) { + return; + } if (err) { outStream.write({ jsonrpc: '2.0', diff --git a/app/scripts/lib/createMetaRPCHandler.test.js b/app/scripts/lib/createMetaRPCHandler.test.js index 638b018b6..d6472b5e1 100644 --- a/app/scripts/lib/createMetaRPCHandler.test.js +++ b/app/scripts/lib/createMetaRPCHandler.test.js @@ -58,4 +58,40 @@ describe('createMetaRPCHandler', function () { done(); }); }); + it('can not throw an error for writing an error after end', function (done) { + const api = { + foo: (param1, cb) => { + assert.strictEqual(param1, 'bar'); + cb(new Error('foo-error')); + }, + }; + const streamTest = createThoughStream(); + const handler = createMetaRPCHandler(api, streamTest); + streamTest.end(); + handler({ + id: 1, + method: 'foo', + params: ['bar'], + }); + done(); + }); + it('can not throw an error for write after end', function (done) { + const api = { + foo: (param1, cb) => { + assert.strictEqual(param1, 'bar'); + cb(undefined, { + foo: 'bar', + }); + }, + }; + const streamTest = createThoughStream(); + const handler = createMetaRPCHandler(api, streamTest); + streamTest.end(); + handler({ + id: 1, + method: 'foo', + params: ['bar'], + }); + done(); + }); }); diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 611def916..4587ba89b 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -2048,6 +2048,9 @@ export default class MetamaskController extends EventEmitter { // set up postStream transport outStream.on('data', createMetaRPCHandler(api, outStream)); const handleUpdate = (update) => { + if (outStream._writableState.ended) { + return; + } // send notification to client-side outStream.write({ jsonrpc: '2.0',