nodejs / readable-stream

Node-core streams for userland
https://nodejs.org/api/stream.html
Other
1.03k stars 227 forks source link

TypeError: this.once is not a function #315

Closed FreedCapybara closed 6 years ago

FreedCapybara commented 7 years ago

Hello,

I have a project that uses Webpack and I'm getting the error TypeError: this.once is not a function inside of _stream_duplex.js:

function Duplex(options) {
  if (!(this instanceof Duplex))
    return new Duplex(options);

  Readable.call(this, options);
  Writable.call(this, options);

  if (options && options.readable === false)
    this.readable = false;

  if (options && options.writable === false)
    this.writable = false;

  this.allowHalfOpen = true;
  if (options && options.allowHalfOpen === false)
    this.allowHalfOpen = false;

  this.once('end', onend); // <--- this guy
}

Please see this issue for more details https://github.com/mqttjs/MQTT.js/issues/696

Thank you!

mcollina commented 7 years ago

Can you please prove a way to reproduce it?

FreedCapybara commented 7 years ago

Thanks for the quick reply! You'll have to forgive me because my steps to reproduce come from projects that use readable-stream as a dependency (mqtt stuff), but here you go:

  1. Set up Angular Starter (I just downloaded the zip instead of cloning)
  2. npm install --save ngx-mqtt
  3. Set up ngx-mqtt in src/app/app.module.ts:
    
    // ...
    import {
    MqttModule
    MqttMessage
    MqttService
    } from 'ngx-mqtt';

export const MQTT_SERVICE_OPTIONS = { hostname: 'iot.eclipse.org', port: 80, path: '/ws' }

export function mqttServiceFactory() { return new MqttService(MQTT_SERVICE_OPTIONS); }

// ... @NgModule({ // ... imports: [ // ... MqttModule.forRoot({ provide: MqttService, useFactory: mqttServiceFactory }) ] })

4. Inject MqttService in `src/app/home/home.component.ts`:
```js
// ...
import { MqttService } from 'ngx-mqtt';

export class HomeComponent implements OnInit {

  constructor(
    // ...
    private ngxMqttService: MqttService
  ) {}
}
  1. npm start and navigate to localhost:3000
  2. Check your browser console (I used Chrome)
FreedCapybara commented 7 years ago

It looks like something in the Angular Starter configuration causes problems with the prototype assignment see this issue and the once.js source.

Perhaps the file could be adjusted to avoid relying on the prototype assignment?

FreedCapybara commented 7 years ago

Just from messing with the files in my node_modules, it seems like changing _stream_duplex.js as follows solves this issue (but causes different errors with this project setup):

var once = require('once');

function Duplex(options) {
  // ...
  once('end', onend);
}

After making this adjustment I get TypeError: Cannot set property 'needReadable' of undefined inside of _stream_transform.js:

function Transform(options) {
  if (!(this instanceof Transform))
    return new Transform(options);

  Duplex.call(this, options);

  this._transformState = new TransformState(options, this);

  var stream = this;

  this._readableState.needReadable = true; // <-------------------------------- here

  this._readableState.sync = false;

  this.once('prefinish', function() {
    if (util.isFunction(this._flush))
      this._flush(function(er) {
        done(stream, er);
      });
    else
      done(stream);
  });
}
mcollina commented 7 years ago

@FreedCapybara can you upload all the steps in https://github.com/nodejs/readable-stream/issues/315#issuecomment-336526623 in a github repo so that we can speed up the process? Thanks.

FreedCapybara commented 7 years ago

Thanks @mcollina, here you go: https://github.com/FreedCapybara/reproduce-mqtt-issue

FreedCapybara commented 7 years ago

It seems like it's just little things, where ensuring that everything is defined would fix issues with TypeScript/Webpack-like environments 👍

mcollina commented 7 years ago

What's should I do to reproduce the issue on that repo?

FreedCapybara commented 7 years ago

Just run the app with npm start. You should see the error in your console.

mcollina commented 7 years ago

I've just run it, and it works smoothly here. There is no error in the console.

FreedCapybara commented 6 years ago

Alright, well, up to you if you want to do anything about it, then ¯_(ツ)_/¯

Ensuring everything is defined would be a good thing to do to make the code more robust, but I guess it's not a big deal if I'm the only person running into this.

I ended up using a different mqtt library that doesn't rely on readable-stream, so I'm not really blocked by this issue anymore. Closing.

stewhi commented 6 years ago

Ran into the exact same thing, would highly recommend taking FreedCapybara's fix, it worked like a charm.

mcollina commented 6 years ago

As I said, can somebody shows me instructions to reproduce? When I run the example above, I got no error and it seemed a cache/bug in the transpiler or bundler or package manager as starting fresh did not cause any problems here. We cannot fix something that we cannot reproduce.

stewhi commented 6 years ago

Mine was

import * as jwt from "jsonwebtoken";
const token = jwt.sign(
            {    
                documentId,
                permission: "read:write",   
                tenantId,    
                user: {    
                    id: userId,    
                },    
            },    
            secret);

On hitting this, it eventually ended up in stream, where it would throw the error this.once is not a function.

chromakode commented 4 years ago

Apologies for bumping a dead thread. I've just run into this and want to add some additional context to the top google result.

I'm running a pika build of readable-stream here: https://cdn.pika.dev/-/readable-stream@v3.6.0-OKumKRBjsyH8yLExcy0D/dist=es2019/readable-stream.js

The bundle contains the following lines (in this order):

inherits(Duplex$1, _stream_readable);
...
var _stream_readable = Readable;
...
function Readable(options) {

At the time inherits(Duplex$1, _stream_readable) runs, _stream_readable is hoisted but not yet defined, which is why Duplex.once ends up not defined.

This appears to be an issue with the source transforms of some bundlers, not caused by readable-stream itself.