Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MockHttpSocket and MockHttpAgent are not being garbage collected #2405

Open
4 tasks done
rossipedia opened this issue Jan 4, 2025 · 13 comments
Open
4 tasks done

MockHttpSocket and MockHttpAgent are not being garbage collected #2405

rossipedia opened this issue Jan 4, 2025 · 13 comments
Labels
bug Something isn't working help wanted Extra attention is needed needs:triage Issues that have not been investigated yet. scope:node Related to MSW running in Node

Comments

@rossipedia
Copy link

rossipedia commented Jan 4, 2025

Prerequisites

Environment check

  • I'm using the latest msw version
  • I'm using Node.js version 18 or higher

Node.js version

22.12.0

Reproduction repository

https://github.com/rossipedia/msw-leak-test

Reproduction steps

Instructions are in the reproduction repo, but they are essentially:

  1. clone repro
  2. npm install
  3. ./demo.sh

Current behavior

Note

This is a follow up to my colleague's issue #2390

Enabling MSW with no handlers and then load-testing using ab causes heap usage to balloon, even when manually invoking garbage collection.

As best I can tell, the largest percentage of retained objects are primarily:

  • MockHttpSocket
  • MockHttpAgent

I do not believe this is related to express, as only ClientRequest is intercepted, and I don't think express or http.createServer use ClientRequest, only IncomingMessage and ServerResponse (I could be wrong about that though).

Expected behavior

Memory usage should be stable under load when simply enabling MSW in a node application.

@rossipedia rossipedia added bug Something isn't working needs:triage Issues that have not been investigated yet. scope:node Related to MSW running in Node labels Jan 4, 2025
@mikeparker
Copy link

This is causing a large memory leak meaning we have to restart our production pods every day. Any update / acknowledgement of the issue would be great.

@mikeparker
Copy link

@kettanaito sorry for the direct ping and we really appreciate your work here, but this is causing us at Docker significant issues as use MSW in production to host a demo environment that matches our e2e tests and we have to restart production pods constantly due to this MSW memory leak.

We can potentially contribute engineering effort if you can help point us in the right direction as it would be a large lift to migrate away from MSW for this.

@kettanaito
Copy link
Member

@mikeparker, I am sorry to hear that this is blocking you. If you have time, could you please see what in MockHttpSocket causes it to persist?

My initial guess is that it can be request or response parser, although we try to free it at the first available moment (1, 2).

I will try to look into this but I am overburdened as of now. I would be grateful if you landed me a hand investigating this so I can roll out the appropriate fix as soon as we know what's causing the issue. Thanks.

@kettanaito
Copy link
Member

Another potential problem area is that the agent/socket interface may not have some of the methods implemented that result in it not being disposed of correctly. This can be proven/disproven by constructing and observing an actual net.Socket to see what gets called in your particular use case (debugger or Proxy are useful for this).

@kettanaito kettanaito added the help wanted Extra attention is needed label Jan 29, 2025
@85B622ACA6
Copy link

I think I'm seeing something related:
https://gist.github.com/85B622ACA6/48b57fe7c595522f3957e40d1392adc7

It would be nice to be able to use msw without the websocket interceptors being applied.

@kettanaito
Copy link
Member

@85B622ACA6, I don't believe we interfere with request at that level to result in the unexpected destroy() there. It may be a side effect of our implementation but I fail to see how it can result in a memory leak.

@kettanaito kettanaito changed the title MockHttpSocket and MockHttpAgent are not being garbage collected MockHttpSocket and MockHttpAgent are not being garbage collected Jan 30, 2025
@85B622ACA6
Copy link

I believe you are correct. After playing around with it some more, the results I was seeing seem to be related to how msw interacts with the 'ws' WebSocket client.

I hate to go of topic, but is msw expected to play nicely with clients from the 'ws' package?

@kettanaito
Copy link
Member

I've opened a pull request to try to measure the memory footprint of the interceptors in mswjs/interceptors#702. While I cannot see quite the same memory heap given more-or-less the same reproduction scenario, the memory snapshot with interceptors is ~50MB larger for 10,000 requests.

Alas, I have no idea how to navigate the heap snapshot to understand why MockHttpSocket (and the agent) aren't disposed of.

@kettanaito
Copy link
Member

I hate to go of topic, but is msw expected to play nicely with clients from the 'ws' package?

Yes, I believe so. We are using ws extensively for server-side testing so I'd expect it to work with ws client as well, given they implement the same logic. MSW supports anything that relies on the global WebSocket API.

@85B622ACA6
Copy link

For node versions <22 too? (22 introduced the built-in WebSocket client)

@kettanaito
Copy link
Member

@85B622ACA6, yes, as long as WebSocket is exposed globally, which is the case for Node.js.

@rossipedia
Copy link
Author

Another potential problem area is that the agent/socket interface may not have some of the methods implemented that result in it not being disposed of correctly. This can be proven/disproven by constructing and observing an actual net.Socket to see what gets called in your particular use case (debugger or Proxy are useful for this).

That's a great idea, lemme poke around at that and see what pops up

@rossipedia
Copy link
Author

Ok so playing around with Proxy, I have this test file I whipped up (probably super naive, but still interesting):

import net from 'node:net';

const handler = {
  get(t, p, r) {
    const v = Reflect.get(t, p, r);
    console.log(`-----------------------------------------------------`);
    console.log(
      `get socket[${p.toString()}]:\n${
        typeof v === 'function' ? 'function' : v
      }`
    );
    if (typeof v === 'function') {
      // trap for arguments
      return new Proxy(v, {
        apply(target, thisArg, args) {
          console.log(`-----------------------------------------------------`);
          console.log(`-> calling socket[${p.toString()}](${args.join(', ')})`);
          return Reflect.apply(target, thisArg, args);
        },
      });
    }
    return v;
  },
};

const server = net.createServer((c) => {
  const s = new Proxy(c, handler);
  s.pipe(s);
});

server.on('error', (err) => {
  throw err;
});

server.listen(8124, () => {
  console.log('server bound');
});

Kicking that up and then sending a 'foo' string into it with:

$ echo "foo" | nc localhost 8124

Gives the following output. I'll still dig in some more, but maybe you can see something I don't 😅

-----------------------------------------------------
get socket[pipe]:
function
-----------------------------------------------------
-----------------------------------------------------
get socket[Symbol(Symbol.toPrimitive)]:
undefined
-----------------------------------------------------
get socket[toString]:
function
-----------------------------------------------------
-> calling socket[toString]()
-----------------------------------------------------
get socket[Symbol(Symbol.toStringTag)]:
undefined
-> calling socket[pipe]([object Object])
-----------------------------------------------------
get socket[_readableState]:
[object Object]
-----------------------------------------------------
get socket[once]:
function
-----------------------------------------------------
-> calling socket[once](end, function onend() {
    debug('onend');
    dest.end();
  })
-----------------------------------------------------
get socket[on]:
function
-----------------------------------------------------
-> calling socket[on](end, function () { [native code] })
-----------------------------------------------------
get socket[_events]:
[object Object]
-----------------------------------------------------
get socket[_maxListeners]:
undefined
-----------------------------------------------------
get socket[_readableState]:
[object Object]
-----------------------------------------------------
get socket[on]:
function
-----------------------------------------------------
-> calling socket[on](unpipe, function onunpipe(readable, unpipeInfo) {
    debug('onunpipe');
    if (readable === src) {
      if (unpipeInfo && unpipeInfo.hasUnpiped === false) {
        unpipeInfo.hasUnpiped = true;
        cleanup();
      }
    }
  })
-----------------------------------------------------
get socket[_events]:
[object Object]
-----------------------------------------------------
get socket[_eventsCount]:
1
-----------------------------------------------------
get socket[_readableState]:
[object Object]
-----------------------------------------------------
get socket[on]:
function
-----------------------------------------------------
-> calling socket[on](data, function ondata(chunk) {
    debug('ondata');
    const ret = dest.write(chunk);
    debug('dest.write', ret);
    if (ret === false) {
      pause();
    }
  })
-----------------------------------------------------
get socket[_events]:
[object Object]
-----------------------------------------------------
get socket[_eventsCount]:
2
-----------------------------------------------------
get socket[_readableState]:
[object Object]
-----------------------------------------------------
get socket[listenerCount]:
function
-----------------------------------------------------
-> calling socket[listenerCount](readable)
-----------------------------------------------------
get socket[_events]:
[object Object]
-----------------------------------------------------
get socket[resume]:
function
-----------------------------------------------------
-> calling socket[resume]()
-----------------------------------------------------
get socket[Symbol(kBuffer)]:
null
-----------------------------------------------------
get socket[_readableState]:
[object Object]
-----------------------------------------------------
get socket[prependListener]:
function
-----------------------------------------------------
get socket[prependListener]:
function
-----------------------------------------------------
-> calling socket[prependListener](error, function onerror(er) {
    debug('onerror', er);
    unpipe();
    dest.removeListener('error', onerror);
    if (dest.listenerCount('error') === 0) {
      const s = dest._writableState || dest._readableState;
      if (s && !s.errorEmitted) {
        // User incorrectly emitted 'error' directly on the stream.
        errorOrDestroy(dest, er);
      } else {
        dest.emit('error', er);
      }
    }
  })
-----------------------------------------------------
get socket[_events]:
[object Object]
-----------------------------------------------------
get socket[_eventsCount]:
3
-----------------------------------------------------
get socket[once]:
function
-----------------------------------------------------
-> calling socket[once](close, function onclose() {
    dest.removeListener('finish', onfinish);
    unpipe();
  })
-----------------------------------------------------
get socket[on]:
function
-----------------------------------------------------
-> calling socket[on](close, function () { [native code] })
-----------------------------------------------------
get socket[_events]:
[object Object]
-----------------------------------------------------
get socket[_eventsCount]:
4
-----------------------------------------------------
get socket[_readableState]:
[object Object]
-----------------------------------------------------
get socket[once]:
function
-----------------------------------------------------
-> calling socket[once](finish, function onfinish() {
    debug('onfinish');
    dest.removeListener('close', onclose);
    unpipe();
  })
-----------------------------------------------------
get socket[on]:
function
-----------------------------------------------------
-> calling socket[on](finish, function () { [native code] })
-----------------------------------------------------
get socket[_events]:
[object Object]
-----------------------------------------------------
get socket[_eventsCount]:
5
-----------------------------------------------------
get socket[_readableState]:
[object Object]
-----------------------------------------------------
get socket[emit]:
function
-----------------------------------------------------
-----------------------------------------------------
get socket[Symbol(Symbol.toPrimitive)]:
undefined
-----------------------------------------------------
get socket[toString]:
function
-----------------------------------------------------
-> calling socket[toString]()
-----------------------------------------------------
get socket[Symbol(Symbol.toStringTag)]:
undefined
-> calling socket[emit](pipe, [object Object])
-----------------------------------------------------
get socket[_events]:
[object Object]
-----------------------------------------------------
get socket[_writableState]:
[object Object]
-----------------------------------------------------
get socket[writableNeedDrain]:
false
-----------------------------------------------------
get socket[emit]:
function
-----------------------------------------------------
-> calling socket[emit](resume)
-----------------------------------------------------
get socket[_events]:
[object Object]
-----------------------------------------------------
get socket[_readableState]:
[object Object]
-----------------------------------------------------
get socket[read]:
function
-----------------------------------------------------
-> calling socket[read]()
-----------------------------------------------------
get socket[Symbol(kBuffer)]:
null
-----------------------------------------------------
get socket[_readableState]:
[object Object]
-----------------------------------------------------
get socket[write]:
function
-----------------------------------------------------
-> calling socket[write](foo
)
-----------------------------------------------------
get socket[_writableState]:
[object Object]
-----------------------------------------------------
get socket[_write]:
function
-----------------------------------------------------
-> calling socket[_write](foo
, buffer, function () { [native code] })
-----------------------------------------------------
get socket[_writeGeneric]:
function
-----------------------------------------------------
-> calling socket[_writeGeneric](false, foo
, buffer, function () { [native code] })
-----------------------------------------------------
get socket[connecting]:
false
-----------------------------------------------------
get socket[Symbol(kHandle)]:
[object Object]
-----------------------------------------------------
get socket[_handle]:
[object Object]
-----------------------------------------------------
get socket[_unrefTimer]:
function
-----------------------------------------------------
-> calling socket[_unrefTimer]()
-----------------------------------------------------
get socket[Symbol(timeout)]:
null
-----------------------------------------------------
get socket[_parent]:
null
-----------------------------------------------------
get socket[Symbol(kHandle)]:
[object Object]
-----------------------------------------------------
get socket[removeListener]:
function
-----------------------------------------------------
-> calling socket[removeListener](end, function () { [native code] })
-----------------------------------------------------
get socket[_readableState]:
[object Object]
-----------------------------------------------------
get socket[_events]:
[object Object]
-----------------------------------------------------
get socket[_events]:
[object Object]
-----------------------------------------------------
get socket[_events]:
[object Object]
-----------------------------------------------------
get socket[end]:
function
-----------------------------------------------------
-> calling socket[end]()
-----------------------------------------------------
get socket[_writableState]:
[object Object]
-----------------------------------------------------
get socket[_final]:
function
-----------------------------------------------------
get socket[_final]:
function
-----------------------------------------------------
-> calling socket[_final]((err) => onFinish(stream, state, err))
-----------------------------------------------------
get socket[connecting]:
false
-----------------------------------------------------
get socket[Symbol(kHandle)]:
[object Object]
-----------------------------------------------------
get socket[_handle]:
[object Object]
-----------------------------------------------------
get socket[Symbol(kHandle)]:
[object Object]
-----------------------------------------------------
get socket[_handle]:
[object Object]
-----------------------------------------------------
get socket[Symbol(kHandle)]:
[object Object]
-----------------------------------------------------
get socket[_handle]:
[object Object]
-----------------------------------------------------
get socket[emit]:
function
-----------------------------------------------------
-> calling socket[emit](prefinish)
-----------------------------------------------------
get socket[_events]:
[object Object]
-----------------------------------------------------
get socket[emit]:
function
-----------------------------------------------------
-> calling socket[emit](finish)
-----------------------------------------------------
get socket[_events]:
[object Object]
-----------------------------------------------------
get socket[removeListener]:
function
-----------------------------------------------------
-> calling socket[removeListener](finish, function () { [native code] })
-----------------------------------------------------
get socket[_readableState]:
[object Object]
-----------------------------------------------------
get socket[_events]:
[object Object]
-----------------------------------------------------
get socket[_events]:
[object Object]
-----------------------------------------------------
get socket[_events]:
[object Object]
-----------------------------------------------------
get socket[_eventsCount]:
6
-----------------------------------------------------
get socket[Symbol(shapeMode)]:
true
-----------------------------------------------------
get socket[removeListener]:
function
-----------------------------------------------------
-> calling socket[removeListener](close, function onclose() {
    dest.removeListener('finish', onfinish);
    unpipe();
  })
-----------------------------------------------------
get socket[_readableState]:
[object Object]
-----------------------------------------------------
get socket[_events]:
[object Object]
-----------------------------------------------------
get socket[_events]:
[object Object]
-----------------------------------------------------
get socket[_events]:
[object Object]
-----------------------------------------------------
get socket[_eventsCount]:
5
-----------------------------------------------------
get socket[Symbol(shapeMode)]:
true
-----------------------------------------------------
get socket[unpipe]:
function
-----------------------------------------------------
-----------------------------------------------------
get socket[Symbol(Symbol.toPrimitive)]:
undefined
-----------------------------------------------------
get socket[toString]:
function
-----------------------------------------------------
-> calling socket[toString]()
-----------------------------------------------------
get socket[Symbol(Symbol.toStringTag)]:
undefined
-> calling socket[unpipe]([object Object])
-----------------------------------------------------
get socket[_readableState]:
[object Object]
-----------------------------------------------------
get socket[pause]:
function
-----------------------------------------------------
-> calling socket[pause]()
-----------------------------------------------------
get socket[Symbol(kBuffer)]:
null
-----------------------------------------------------
get socket[_readableState]:
[object Object]
-----------------------------------------------------
get socket[emit]:
function
-----------------------------------------------------
-> calling socket[emit](pause)
-----------------------------------------------------
get socket[_events]:
[object Object]
-----------------------------------------------------
get socket[emit]:
function
-----------------------------------------------------
-----------------------------------------------------
get socket[Symbol(Symbol.toPrimitive)]:
undefined
-----------------------------------------------------
get socket[toString]:
function
-----------------------------------------------------
-> calling socket[toString]()
-----------------------------------------------------
get socket[Symbol(Symbol.toStringTag)]:
undefined
-> calling socket[emit](unpipe, [object Object], [object Object])
-----------------------------------------------------
get socket[_events]:
[object Object]
-----------------------------------------------------
get socket[removeListener]:
function
-----------------------------------------------------
-> calling socket[removeListener](close, function onclose() {
    dest.removeListener('finish', onfinish);
    unpipe();
  })
-----------------------------------------------------
get socket[_readableState]:
[object Object]
-----------------------------------------------------
get socket[_events]:
[object Object]
-----------------------------------------------------
get socket[_events]:
[object Object]
-----------------------------------------------------
get socket[removeListener]:
function
-----------------------------------------------------
-> calling socket[removeListener](finish, function onfinish() {
    debug('onfinish');
    dest.removeListener('close', onclose);
    unpipe();
  })
-----------------------------------------------------
get socket[_readableState]:
[object Object]
-----------------------------------------------------
get socket[_events]:
[object Object]
-----------------------------------------------------
get socket[_events]:
[object Object]
-----------------------------------------------------
get socket[removeListener]:
function
-----------------------------------------------------
-> calling socket[removeListener](error, function onerror(er) {
    debug('onerror', er);
    unpipe();
    dest.removeListener('error', onerror);
    if (dest.listenerCount('error') === 0) {
      const s = dest._writableState || dest._readableState;
      if (s && !s.errorEmitted) {
        // User incorrectly emitted 'error' directly on the stream.
        errorOrDestroy(dest, er);
      } else {
        dest.emit('error', er);
      }
    }
  })
-----------------------------------------------------
get socket[_readableState]:
[object Object]
-----------------------------------------------------
get socket[_events]:
[object Object]
-----------------------------------------------------
get socket[_events]:
[object Object]
-----------------------------------------------------
get socket[_events]:
[object Object]
-----------------------------------------------------
get socket[_eventsCount]:
4
-----------------------------------------------------
get socket[Symbol(shapeMode)]:
true
-----------------------------------------------------
get socket[removeListener]:
function
-----------------------------------------------------
-> calling socket[removeListener](unpipe, function onunpipe(readable, unpipeInfo) {
    debug('onunpipe');
    if (readable === src) {
      if (unpipeInfo && unpipeInfo.hasUnpiped === false) {
        unpipeInfo.hasUnpiped = true;
        cleanup();
      }
    }
  })
-----------------------------------------------------
get socket[_readableState]:
[object Object]
-----------------------------------------------------
get socket[_events]:
[object Object]
-----------------------------------------------------
get socket[_events]:
[object Object]
-----------------------------------------------------
get socket[_events]:
[object Object]
-----------------------------------------------------
get socket[_eventsCount]:
3
-----------------------------------------------------
get socket[Symbol(shapeMode)]:
true
-----------------------------------------------------
get socket[removeListener]:
function
-----------------------------------------------------
-> calling socket[removeListener](end, function onend() {
    debug('onend');
    dest.end();
  })
-----------------------------------------------------
get socket[_readableState]:
[object Object]
-----------------------------------------------------
get socket[_events]:
[object Object]
-----------------------------------------------------
get socket[_events]:
[object Object]
-----------------------------------------------------
get socket[_events]:
[object Object]
-----------------------------------------------------
get socket[removeListener]:
function
-----------------------------------------------------
-> calling socket[removeListener](end, function unpipe() {
    debug('unpipe');
    src.unpipe(dest);
  })
-----------------------------------------------------
get socket[_readableState]:
[object Object]
-----------------------------------------------------
get socket[_events]:
[object Object]
-----------------------------------------------------
get socket[_events]:
[object Object]
-----------------------------------------------------
get socket[_events]:
[object Object]
-----------------------------------------------------
get socket[removeListener]:
function
-----------------------------------------------------
-> calling socket[removeListener](data, function ondata(chunk) {
    debug('ondata');
    const ret = dest.write(chunk);
    debug('dest.write', ret);
    if (ret === false) {
      pause();
    }
  })
-----------------------------------------------------
get socket[_readableState]:
[object Object]
-----------------------------------------------------
get socket[_events]:
[object Object]
-----------------------------------------------------
get socket[_events]:
[object Object]
-----------------------------------------------------
get socket[_events]:
[object Object]
-----------------------------------------------------
get socket[_eventsCount]:
2
-----------------------------------------------------
get socket[Symbol(shapeMode)]:
true
-----------------------------------------------------
get socket[listenerCount]:
function
-----------------------------------------------------
-> calling socket[listenerCount](data)
-----------------------------------------------------
get socket[_events]:
[object Object]
-----------------------------------------------------
get socket[_readableState]:
[object Object]
-----------------------------------------------------
get socket[destroy]:
function
-----------------------------------------------------
-> calling socket[destroy]()
-----------------------------------------------------
get socket[_writableState]:
[object Object]
-----------------------------------------------------
get socket[_readableState]:
[object Object]
-----------------------------------------------------
get socket[_writableState]:
[object Object]
-----------------------------------------------------
get socket[_destroy]:
function
-----------------------------------------------------
-> calling socket[_destroy](, function onDestroy(err) {
    if (called) {
      return;
    }
    called = true;

    const r = self._readableState;
    const w = self._writableState;

    checkError(err, w, r);

    if (w) {
      w[kState] |= kClosed;
    }
    if (r) {
      r[kState] |= kClosed;
    }

    if (typeof cb === 'function') {
      cb(err);
    }

    if (err) {
      process.nextTick(emitErrorCloseNT, self, err);
    } else {
      process.nextTick(emitCloseNT, self);
    }
  })
-----------------------------------------------------
get socket[Symbol(timeout)]:
null
-----------------------------------------------------
get socket[_parent]:
null
-----------------------------------------------------
get socket[Symbol(kHandle)]:
[object Object]
-----------------------------------------------------
get socket[_handle]:
[object Object]
-----------------------------------------------------
get socket[Symbol(kHandle)]:
[object Object]
-----------------------------------------------------
get socket[_handle]:
[object Object]
-----------------------------------------------------
get socket[Symbol(kHandle)]:

~/Desktop via  v22.13.0 took 13m5s 
❯ node socktest.mjs        
server bound
-----------------------------------------------------
get socket[pipe]:
function
-----------------------------------------------------
-----------------------------------------------------
get socket[Symbol(Symbol.toPrimitive)]:
undefined
-----------------------------------------------------
get socket[toString]:
function
-----------------------------------------------------
-> calling socket[toString]()
-----------------------------------------------------
get socket[Symbol(Symbol.toStringTag)]:
undefined
-> calling socket[pipe]([object Object])
-----------------------------------------------------
get socket[_readableState]:
[object Object]
-----------------------------------------------------
get socket[once]:
function
-----------------------------------------------------
-> calling socket[once](end, function onend() {
    debug('onend');
    dest.end();
  })
-----------------------------------------------------
get socket[on]:
function
-----------------------------------------------------
-> calling socket[on](end, function () { [native code] })
-----------------------------------------------------
get socket[_events]:
[object Object]
-----------------------------------------------------
get socket[_maxListeners]:
undefined
-----------------------------------------------------
get socket[_readableState]:
[object Object]
-----------------------------------------------------
get socket[on]:
function
-----------------------------------------------------
-> calling socket[on](unpipe, function onunpipe(readable, unpipeInfo) {
    debug('onunpipe');
    if (readable === src) {
      if (unpipeInfo && unpipeInfo.hasUnpiped === false) {
        unpipeInfo.hasUnpiped = true;
        cleanup();
      }
    }
  })
-----------------------------------------------------
get socket[_events]:
[object Object]
-----------------------------------------------------
get socket[_eventsCount]:
1
-----------------------------------------------------
get socket[_readableState]:
[object Object]
-----------------------------------------------------
get socket[on]:
function
-----------------------------------------------------
-> calling socket[on](data, function ondata(chunk) {
    debug('ondata');
    const ret = dest.write(chunk);
    debug('dest.write', ret);
    if (ret === false) {
      pause();
    }
  })
-----------------------------------------------------
get socket[_events]:
[object Object]
-----------------------------------------------------
get socket[_eventsCount]:
2
-----------------------------------------------------
get socket[_readableState]:
[object Object]
-----------------------------------------------------
get socket[listenerCount]:
function
-----------------------------------------------------
-> calling socket[listenerCount](readable)
-----------------------------------------------------
get socket[_events]:
[object Object]
-----------------------------------------------------
get socket[resume]:
function
-----------------------------------------------------
-> calling socket[resume]()
-----------------------------------------------------
get socket[Symbol(kBuffer)]:
null
-----------------------------------------------------
get socket[_readableState]:
[object Object]
-----------------------------------------------------
get socket[prependListener]:
function
-----------------------------------------------------
get socket[prependListener]:
function
-----------------------------------------------------
-> calling socket[prependListener](error, function onerror(er) {
    debug('onerror', er);
    unpipe();
    dest.removeListener('error', onerror);
    if (dest.listenerCount('error') === 0) {
      const s = dest._writableState || dest._readableState;
      if (s && !s.errorEmitted) {
        // User incorrectly emitted 'error' directly on the stream.
        errorOrDestroy(dest, er);
      } else {
        dest.emit('error', er);
      }
    }
  })
-----------------------------------------------------
get socket[_events]:
[object Object]
-----------------------------------------------------
get socket[_eventsCount]:
3
-----------------------------------------------------
get socket[once]:
function
-----------------------------------------------------
-> calling socket[once](close, function onclose() {
    dest.removeListener('finish', onfinish);
    unpipe();
  })
-----------------------------------------------------
get socket[on]:
function
-----------------------------------------------------
-> calling socket[on](close, function () { [native code] })
-----------------------------------------------------
get socket[_events]:
[object Object]
-----------------------------------------------------
get socket[_eventsCount]:
4
-----------------------------------------------------
get socket[_readableState]:
[object Object]
-----------------------------------------------------
get socket[once]:
function
-----------------------------------------------------
-> calling socket[once](finish, function onfinish() {
    debug('onfinish');
    dest.removeListener('close', onclose);
    unpipe();
  })
-----------------------------------------------------
get socket[on]:
function
-----------------------------------------------------
-> calling socket[on](finish, function () { [native code] })
-----------------------------------------------------
get socket[_events]:
[object Object]
-----------------------------------------------------
get socket[_eventsCount]:
5
-----------------------------------------------------
get socket[_readableState]:
[object Object]
-----------------------------------------------------
get socket[emit]:
function
-----------------------------------------------------
-----------------------------------------------------
get socket[Symbol(Symbol.toPrimitive)]:
undefined
-----------------------------------------------------
get socket[toString]:
function
-----------------------------------------------------
-> calling socket[toString]()
-----------------------------------------------------
get socket[Symbol(Symbol.toStringTag)]:
undefined
-> calling socket[emit](pipe, [object Object])
-----------------------------------------------------
get socket[_events]:
[object Object]
-----------------------------------------------------
get socket[_writableState]:
[object Object]
-----------------------------------------------------
get socket[writableNeedDrain]:
false
-----------------------------------------------------
get socket[emit]:
function
-----------------------------------------------------
-> calling socket[emit](resume)
-----------------------------------------------------
get socket[_events]:
[object Object]
-----------------------------------------------------
get socket[_readableState]:
[object Object]
-----------------------------------------------------
get socket[read]:
function
-----------------------------------------------------
-> calling socket[read]()
-----------------------------------------------------
get socket[Symbol(kBuffer)]:
null
-----------------------------------------------------
get socket[_readableState]:
[object Object]
-----------------------------------------------------
get socket[write]:
function
-----------------------------------------------------
-> calling socket[write](foo
)
-----------------------------------------------------
get socket[_writableState]:
[object Object]
-----------------------------------------------------
get socket[_write]:
function
-----------------------------------------------------
-> calling socket[_write](foo
, buffer, function () { [native code] })
-----------------------------------------------------
get socket[_writeGeneric]:
function
-----------------------------------------------------
-> calling socket[_writeGeneric](false, foo
, buffer, function () { [native code] })
-----------------------------------------------------
get socket[connecting]:
false
-----------------------------------------------------
get socket[Symbol(kHandle)]:
[object Object]
-----------------------------------------------------
get socket[_handle]:
[object Object]
-----------------------------------------------------
get socket[_unrefTimer]:
function
-----------------------------------------------------
-> calling socket[_unrefTimer]()
-----------------------------------------------------
get socket[Symbol(timeout)]:
null
-----------------------------------------------------
get socket[_parent]:
null
-----------------------------------------------------
get socket[Symbol(kHandle)]:
[object Object]
-----------------------------------------------------
get socket[removeListener]:
function
-----------------------------------------------------
-> calling socket[removeListener](end, function () { [native code] })
-----------------------------------------------------
get socket[_readableState]:
[object Object]
-----------------------------------------------------
get socket[_events]:
[object Object]
-----------------------------------------------------
get socket[_events]:
[object Object]
-----------------------------------------------------
get socket[_events]:
[object Object]
-----------------------------------------------------
get socket[end]:
function
-----------------------------------------------------
-> calling socket[end]()
-----------------------------------------------------
get socket[_writableState]:
[object Object]
-----------------------------------------------------
get socket[_final]:
function
-----------------------------------------------------
get socket[_final]:
function
-----------------------------------------------------
-> calling socket[_final]((err) => onFinish(stream, state, err))
-----------------------------------------------------
get socket[connecting]:
false
-----------------------------------------------------
get socket[Symbol(kHandle)]:
[object Object]
-----------------------------------------------------
get socket[_handle]:
[object Object]
-----------------------------------------------------
get socket[Symbol(kHandle)]:
[object Object]
-----------------------------------------------------
get socket[_handle]:
[object Object]
-----------------------------------------------------
get socket[Symbol(kHandle)]:
[object Object]
-----------------------------------------------------
get socket[_handle]:
[object Object]
-----------------------------------------------------
get socket[emit]:
function
-----------------------------------------------------
-> calling socket[emit](prefinish)
-----------------------------------------------------
get socket[_events]:
[object Object]
-----------------------------------------------------
get socket[emit]:
function
-----------------------------------------------------
-> calling socket[emit](finish)
-----------------------------------------------------
get socket[_events]:
[object Object]
-----------------------------------------------------
get socket[removeListener]:
function
-----------------------------------------------------
-> calling socket[removeListener](finish, function () { [native code] })
-----------------------------------------------------
get socket[_readableState]:
[object Object]
-----------------------------------------------------
get socket[_events]:
[object Object]
-----------------------------------------------------
get socket[_events]:
[object Object]
-----------------------------------------------------
get socket[_events]:
[object Object]
-----------------------------------------------------
get socket[_eventsCount]:
6
-----------------------------------------------------
get socket[Symbol(shapeMode)]:
true
-----------------------------------------------------
get socket[removeListener]:
function
-----------------------------------------------------
-> calling socket[removeListener](close, function onclose() {
    dest.removeListener('finish', onfinish);
    unpipe();
  })
-----------------------------------------------------
get socket[_readableState]:
[object Object]
-----------------------------------------------------
get socket[_events]:
[object Object]
-----------------------------------------------------
get socket[_events]:
[object Object]
-----------------------------------------------------
get socket[_events]:
[object Object]
-----------------------------------------------------
get socket[_eventsCount]:
5
-----------------------------------------------------
get socket[Symbol(shapeMode)]:
true
-----------------------------------------------------
get socket[unpipe]:
function
-----------------------------------------------------
-----------------------------------------------------
get socket[Symbol(Symbol.toPrimitive)]:
undefined
-----------------------------------------------------
get socket[toString]:
function
-----------------------------------------------------
-> calling socket[toString]()
-----------------------------------------------------
get socket[Symbol(Symbol.toStringTag)]:
undefined
-> calling socket[unpipe]([object Object])
-----------------------------------------------------
get socket[_readableState]:
[object Object]
-----------------------------------------------------
get socket[pause]:
function
-----------------------------------------------------
-> calling socket[pause]()
-----------------------------------------------------
get socket[Symbol(kBuffer)]:
null
-----------------------------------------------------
get socket[_readableState]:
[object Object]
-----------------------------------------------------
get socket[emit]:
function
-----------------------------------------------------
-> calling socket[emit](pause)
-----------------------------------------------------
get socket[_events]:
[object Object]
-----------------------------------------------------
get socket[emit]:
function
-----------------------------------------------------
-----------------------------------------------------
get socket[Symbol(Symbol.toPrimitive)]:
undefined
-----------------------------------------------------
get socket[toString]:
function
-----------------------------------------------------
-> calling socket[toString]()
-----------------------------------------------------
get socket[Symbol(Symbol.toStringTag)]:
undefined
-> calling socket[emit](unpipe, [object Object], [object Object])
-----------------------------------------------------
get socket[_events]:
[object Object]
-----------------------------------------------------
get socket[removeListener]:
function
-----------------------------------------------------
-> calling socket[removeListener](close, function onclose() {
    dest.removeListener('finish', onfinish);
    unpipe();
  })
-----------------------------------------------------
get socket[_readableState]:
[object Object]
-----------------------------------------------------
get socket[_events]:
[object Object]
-----------------------------------------------------
get socket[_events]:
[object Object]
-----------------------------------------------------
get socket[removeListener]:
function
-----------------------------------------------------
-> calling socket[removeListener](finish, function onfinish() {
    debug('onfinish');
    dest.removeListener('close', onclose);
    unpipe();
  })
-----------------------------------------------------
get socket[_readableState]:
[object Object]
-----------------------------------------------------
get socket[_events]:
[object Object]
-----------------------------------------------------
get socket[_events]:
[object Object]
-----------------------------------------------------
get socket[removeListener]:
function
-----------------------------------------------------
-> calling socket[removeListener](error, function onerror(er) {
    debug('onerror', er);
    unpipe();
    dest.removeListener('error', onerror);
    if (dest.listenerCount('error') === 0) {
      const s = dest._writableState || dest._readableState;
      if (s && !s.errorEmitted) {
        // User incorrectly emitted 'error' directly on the stream.
        errorOrDestroy(dest, er);
      } else {
        dest.emit('error', er);
      }
    }
  })
-----------------------------------------------------
get socket[_readableState]:
[object Object]
-----------------------------------------------------
get socket[_events]:
[object Object]
-----------------------------------------------------
get socket[_events]:
[object Object]
-----------------------------------------------------
get socket[_events]:
[object Object]
-----------------------------------------------------
get socket[_eventsCount]:
4
-----------------------------------------------------
get socket[Symbol(shapeMode)]:
true
-----------------------------------------------------
get socket[removeListener]:
function
-----------------------------------------------------
-> calling socket[removeListener](unpipe, function onunpipe(readable, unpipeInfo) {
    debug('onunpipe');
    if (readable === src) {
      if (unpipeInfo && unpipeInfo.hasUnpiped === false) {
        unpipeInfo.hasUnpiped = true;
        cleanup();
      }
    }
  })
-----------------------------------------------------
get socket[_readableState]:
[object Object]
-----------------------------------------------------
get socket[_events]:
[object Object]
-----------------------------------------------------
get socket[_events]:
[object Object]
-----------------------------------------------------
get socket[_events]:
[object Object]
-----------------------------------------------------
get socket[_eventsCount]:
3
-----------------------------------------------------
get socket[Symbol(shapeMode)]:
true
-----------------------------------------------------
get socket[removeListener]:
function
-----------------------------------------------------
-> calling socket[removeListener](end, function onend() {
    debug('onend');
    dest.end();
  })
-----------------------------------------------------
get socket[_readableState]:
[object Object]
-----------------------------------------------------
get socket[_events]:
[object Object]
-----------------------------------------------------
get socket[_events]:
[object Object]
-----------------------------------------------------
get socket[_events]:
[object Object]
-----------------------------------------------------
get socket[removeListener]:
function
-----------------------------------------------------
-> calling socket[removeListener](end, function unpipe() {
    debug('unpipe');
    src.unpipe(dest);
  })
-----------------------------------------------------
get socket[_readableState]:
[object Object]
-----------------------------------------------------
get socket[_events]:
[object Object]
-----------------------------------------------------
get socket[_events]:
[object Object]
-----------------------------------------------------
get socket[_events]:
[object Object]
-----------------------------------------------------
get socket[removeListener]:
function
-----------------------------------------------------
-> calling socket[removeListener](data, function ondata(chunk) {
    debug('ondata');
    const ret = dest.write(chunk);
    debug('dest.write', ret);
    if (ret === false) {
      pause();
    }
  })
-----------------------------------------------------
get socket[_readableState]:
[object Object]
-----------------------------------------------------
get socket[_events]:
[object Object]
-----------------------------------------------------
get socket[_events]:
[object Object]
-----------------------------------------------------
get socket[_events]:
[object Object]
-----------------------------------------------------
get socket[_eventsCount]:
2
-----------------------------------------------------
get socket[Symbol(shapeMode)]:
true
-----------------------------------------------------
get socket[listenerCount]:
function
-----------------------------------------------------
-> calling socket[listenerCount](data)
-----------------------------------------------------
get socket[_events]:
[object Object]
-----------------------------------------------------
get socket[_readableState]:
[object Object]
-----------------------------------------------------
get socket[destroy]:
function
-----------------------------------------------------
-> calling socket[destroy]()
-----------------------------------------------------
get socket[_writableState]:
[object Object]
-----------------------------------------------------
get socket[_readableState]:
[object Object]
-----------------------------------------------------
get socket[_writableState]:
[object Object]
-----------------------------------------------------
get socket[_destroy]:
function
-----------------------------------------------------
-> calling socket[_destroy](, function onDestroy(err) {
    if (called) {
      return;
    }
    called = true;

    const r = self._readableState;
    const w = self._writableState;

    checkError(err, w, r);

    if (w) {
      w[kState] |= kClosed;
    }
    if (r) {
      r[kState] |= kClosed;
    }

    if (typeof cb === 'function') {
      cb(err);
    }

    if (err) {
      process.nextTick(emitErrorCloseNT, self, err);
    } else {
      process.nextTick(emitCloseNT, self);
    }
  })
-----------------------------------------------------
get socket[Symbol(timeout)]:
null
-----------------------------------------------------
get socket[_parent]:
null
-----------------------------------------------------
get socket[Symbol(kHandle)]:
[object Object]
-----------------------------------------------------
get socket[_handle]:
[object Object]
-----------------------------------------------------
get socket[Symbol(kHandle)]:
[object Object]
-----------------------------------------------------
get socket[_handle]:
[object Object]
-----------------------------------------------------
get socket[Symbol(kHandle)]:
[object Object]
-----------------------------------------------------
get socket[_handle]:
[object Object]
-----------------------------------------------------
get socket[resetAndClosing]:
undefined
-----------------------------------------------------
get socket[_closeAfterHandlingError]:
false
-----------------------------------------------------
get socket[Symbol(kHandle)]:
[object Object]
-----------------------------------------------------
get socket[_handle]:
[object Object]
-----------------------------------------------------
get socket[Symbol(kHandle)]:
[object Object]
-----------------------------------------------------
get socket[_handle]:
[object Object]
-----------------------------------------------------
get socket[_closeAfterHandlingError]:
false
-----------------------------------------------------
get socket[Symbol(kHandle)]:
[object Object]
-----------------------------------------------------
get socket[_handle]:
[object Object]
-----------------------------------------------------
get socket[_readableState]:
[object Object]
-----------------------------------------------------
get socket[_writableState]:
[object Object]
-----------------------------------------------------
get socket[_server]:
[object Object]
-----------------------------------------------------
get socket[_server]:
[object Object]
-----------------------------------------------------
get socket[_server]:
[object Object]
-----------------------------------------------------
get socket[_server]:
[object Object]
-----------------------------------------------------
get socket[_readableState]:
[object Object]
-----------------------------------------------------
get socket[_writableState]:
[object Object]
-----------------------------------------------------
get socket[emit]:
function
-----------------------------------------------------
-> calling socket[emit](close, false)
-----------------------------------------------------
get socket[_events]:
[object Object]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working help wanted Extra attention is needed needs:triage Issues that have not been investigated yet. scope:node Related to MSW running in Node
Projects
None yet
Development

No branches or pull requests

4 participants