node.js: Cannot read property 'defaultEncoding' of undefined - node.js

I wanted to write a changeable write() function.
var write = function(s) {
process.stdout.write(s);
}
write("Hello world!");
I thought you could just write it shorter:
var write = process.stdout.write;
write("Hello world!");
But here I will receive this error:
TypeError: Cannot read property 'defaultEncoding' of undefined
at Writable.write (_stream_writable.js:172:21)
at Socket.write (net.js:613:40)
at repl:1:2
at REPLServer.self.eval (repl.js:110:21)
at Interface.<anonymous> (repl.js:239:12)
at Interface.EventEmitter.emit (events.js:95:17)
at Interface._onLine (readline.js:202:10)
at Interface._line (readline.js:531:8)
at Interface._ttyWrite (readline.js:760:14)
at ReadStream.onkeypress (readline.js:99:10)
Why is that?

It all has to do with how javascript handles this. Inside the function process.stdout.write there is a call to defaultEncoding() using this variable.
In javascript, this is not assigned a value until an object invokes the function where this is defined and it is relative to the calling object.
So in your first example, this points to process.stdout object and it has the method defaultEncoding.
In your second example, this is undefined since the function is being called from the global namespace. When process.stdout.write tries to call defaultEncoding, it will throw the error you mentioned.
You can manually define the this value for a function using Function.prototype.call() method. Example:
var write = process.stdout.write;
write.call(process.stdout, "Hello world!");
The first argument of call is the object to be used as this inside the function.
I recommend reading this article, it explains a lot about this in javascript.

Use the .bind() method, it is designed exactly for your case.
var write = process.stdout.write.bind(process.stdout);
write("Hello world!");
This sets this variable inside the process.stdout.write method to process.stdout.

Related

Improving error reporting for a dynamically built module.exports in NODEJS

I have an app that dynamically loads individual smaller files into module.export at runtime, it has been working well for a couple of years.
This is the main part of the code that iterates folders, reads them, and then appends them to the desired module.exports after a bit of validation.
var path = module.path+"/lib";
require('async').eachSeries(require('fs').readdirSync(path),function(file,next){
require('fs').readFile(path+'/'+file,'utf8',function(err,code){
var id = file.split('.')[0];
if(id in module.exports) module.exports._errs.push({'lib':id,'err':'mod/'+module.name+'/lib/'+file.replace(/\.obj|\.fnc|\.str/,'.xxx')+' filename duplicated.'});
try{module.exports[id] = eval('false ||'+code);}
catch(err){
module.exports[id]={'_err':err.message};
module.exports._errs.push({'lib':id,'err':err.message})
}
next();
})
},function(){
This all works, but the issue is when there is an error generated, it appears that all of the files / objects / functions are loaded anonymously which make it impossible to determine from the stack trace errors exactly which function failed, as all appear to be anonymous.
Is it possible to either modify the code so that they are non-anonymous or alternatively modify the stack trace error reporting to show the code (& preferably variables) that actually caused the crash ??
TypeError: Cannot read property 'replace' of undefined
at eval (eval at <anonymous> (eval at <anonymous> (/snapshot/src/x3-bin/source/mod/va/index.js:1:462)), <anonymous>:1:1642)
at Query.<anonymous> (/snapshot/src/x3-bin/source/lib/mysql.js:1:2474)
at Query.<anonymous> (/snapshot/src/x3-bin/source/node_modules/mysql/lib/Connection.js:502:10)
at Query.domain [as _callback] (/snapshot/src/x3-bin/source/node_modules/mysql/lib/Connection.js:468:16)
at Query.Sequence.end (/snapshot/src/x-bin/source/node_modules/mysql/lib/protocol/sequences/Sequence.js:83:24)
at Query._handleFinalResultPacket (/snapshot/src/x3-bin/source/node_modules/mysql/lib/protocol/sequences/Query.js:139:8)
at Query.EofPacket (/snapshot/src/x3-bin/source/node_modules/mysql/lib/protocol/sequences/Query.js:123:8)
at Protocol._parsePacket (/snapshot/src/x-bin/source/node_modules/mysql/lib/protocol/Protocol.js:278:23)
at Parser.write (/snapshot/src/x3-bin/source/node_modules/mysql/lib/protocol/Parser.js:76:12)
at Protocol.write (/snapshot/src/x-bin/source/node_modules/mysql/lib/protocol/Protocol.js:38:16)
at Socket.<anonymous> (/snapshot/src/x3-bin/source/node_modules/mysql/lib/Connection.js:91:28)
at Socket.<anonymous> (/snapshot/src/x-bin/source/node_modules/mysql/lib/Connection.js:502:10)
at emitOne (events.js:116:13)
at Socket.emit (events.js:211:7)
at addChunk (_stream_readable.js:263:12)
at readableAddChunk (_stream_readable.js:250:11)
As you can see, the info to identify the source of the problem is very vague (eval at ) and impossible to identify exactly which module.exports function was the cause ?
TypeError: Cannot read property 'replace' of undefined
at eval (eval at <anonymous> (eval at <anonymous> (/snapshot/src/x3-bin/source/mod/va/index.js:1:462)), <anonymous>:1:1642)
Is it possible to either modify the code so that they are non-anonymous
Well, function(err,code){...} is an anonymous function, function NotAnonymous(err, code){...} is not. See this example Node session:
> (function() { eval("let x; x.replace;"); })()
Uncaught TypeError: Cannot read properties of undefined (reading 'replace')
at eval (eval at <anonymous> (REPL9:1:15), <anonymous>:1:10)
at REPL9:1:15
> (function NotAnonymous() { eval("let x; x.replace;"); })()
Uncaught TypeError: Cannot read properties of undefined (reading 'replace')
at eval (eval at NotAnonymous (REPL10:1:28), <anonymous>:1:10)
at NotAnonymous (REPL10:1:28)
> (function NotAnonymous() { eval("(function AlsoNicelyNamed() {let x; x.replace;})()"); })()
Uncaught TypeError: Cannot read properties of undefined (reading 'replace')
at AlsoNicelyNamed (eval at NotAnonymous (REPL11:1:28), <anonymous>:1:39)
at eval (eval at NotAnonymous (REPL11:1:28), <anonymous>:1:49)
at NotAnonymous (REPL11:1:28)
Note how the second and third versions contain the snippet eval at NotAnonymous.
The other occurrence of <anonymous> (<anonymous>:1:10 in my example, <anonymous>:1:1642 in yours) is due to the fact that strings that get evaled don't have a file name. To get change that, you'd have to stop using eval. The line/column information should be accurate though (at least, it is when I put an \n into a test string); so it looks like the file you loaded in this particular example was minified and had at least 1642 characters on its first line.
impossible to identify exactly which module.exports function was the cause ?
You already have that information: in
module.exports._errs.push({'lib':id,'err':err.message}),
id is the export that caused the problem.
Aside from that, it really depends on what's in the files you're evaling. If there are anonymous functions in there, then of course they'll show up as "anonymous", and you'd have to fix that in there by providing names for all functions.

bluebird npm TypeError: Cannot read property 'call' of null

I am using bluebird npm,I am getting the above error
I am calling three different function & doing some database operation, but I am getting this error.
If I tried with two functions, it is working but with three function it is throwing error, TypeError: Cannot read property 'call' of null.
If you go to bluebird/js/release/using.js and comment the line no 39 ;
If I comment this line, then this issue is not coming & all is working fine.
If you want more info please Click Here
This is main.js
var myModule = require('../lib/myModule');
var sync = require('deasync');
var id = 90;
var moduleObj = new moduleEntity(id);
console.log(moduleObj);
var id = 90;
var moduleObj = new moduleEntity(id);
console.log(moduleObj);
var id = 90;
var moduleObj = new moduleEntity(id);
console.log(moduleObj);
In MyModule.js
var deasync = require('deasync');
var dbEntity = require('../db/dbEntity');
module.exports = function (id) {
var outputEntity;
dbEntity(id, function(data){
outputEntity = data
});
while(outputEntity === undefined) { deasync.runLoopOnce();};
return outputEntity;
};
In dbEntery.js
var Promise = require("bluebird");
var getConnection = require('./dbcon');
module.exports = function (id,cb) {
var sql_getRecords = SELECT * from tanle_name;
Promise.using(getConnection, function (conn) {
return conn.query(sql_getRecords).then(function(data){
cb(data[0]);
})
});
};
Here is error stack trace
TypeError: Cannot read property 'call' of null
at FunctionDisposer.doDispose (/home/user/Projects/project_name/node_modules/bluebird/js/release/using.js:98:18)
at FunctionDisposer.Disposer.tryDispose (/home/user/Projects/project_name/node_modules/bluebird/js/release/using.js:78:20)
at iterator (/home/user/Projects/project_name/node_modules/bluebird/js/release/using.js:36:53)
at dispose (/home/user/Projects/project_name/node_modules/bluebird/js/release/using.js:48:9)
at /home/user/Projects/project_name/node_modules/bluebird/js/release/using.js:194:20
at PassThroughHandlerContext.finallyHandler (/home/user/Projects/project_name/node_modules/bluebird/js/release/finally.js:55:23)
at PassThroughHandlerContext.tryCatcher (/home/user/Projects/project_name/node_modules/bluebird/js/release/util.js:16:23)
at Promise._settlePromiseFromHandler (/home/user/Projects/project_name/node_modules/bluebird/js/release/promise.js:510:31)
at Promise._settlePromise (/home/user/Projects/project_name/node_modules/bluebird/js/release/promise.js:567:18)
at Promise._settlePromise0 (/home/user/Projects/project_name/node_modules/bluebird/js/release/promise.js:612:10)
at Promise._settlePromises (/home/user/Projects/project_name/node_modules/bluebird/js/release/promise.js:687:18)
at Async._drainQueue (/home/user/Projects/project_name/node_modules/bluebird/js/release/async.js:133:16)
at Async._drainQueues (/home/user/Projects/project_name/node_modules/bluebird/js/release/async.js:143:10)
at Immediate.Async.drainQueues (/home/user/Projects/project_name/node_modules/bluebird/js/release/async.js:17:14)
at runCallback (timers.js:651:20)
at tryOnImmediate (timers.js:624:5)
Bluebird version -- 3.5
Node Version -- v7.6.0
You provided no code examples so it's hard to give you any detailed answer but here are some things that you have to keep in mind when you get error like this.
TypeError: Cannot read property 'call' of null means that some code (also impossible to tell you which code because you didn't provide an example and full error stack trace) tries to bind some function to some this object and arguments using Function.prototype.call() - see:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call
but instead of the function it got null.
Now you need to follow the stack trace and see which code is trying to call the function and where the null originated to fix your problem.
Note that it is null and not undefined so it must have been provided explicitly instead of just being a missing argument to a function call or a missing property on an object. This is an important hint that should let you diagnose the problem much easier.

Assert.fail (node.js): what does Operator parameter mean?

Node.js unit-testing module has basic assertion assert.fail:
assert.fail(actual, expected, message, operator)
What does operator mean? I'm really new to unit-testing...
What the documentation says: The value of operator is being used to separate the values of actual and expected when providing an error message. This is described in Node.js' documentation for the assert module.
But, if you try this in the interactive shell you see that the parameter seems to be ignored:
> assert.fail(23, 42, 'Malfunction in test.', '###')
AssertionError: Malfunction in test.
at repl:1:9
at REPLServer.self.eval (repl.js:111:21)
at Interface.<anonymous> (repl.js:250:12)
at Interface.EventEmitter.emit (events.js:88:17)
at Interface._onLine (readline.js:199:10)
at Interface._line (readline.js:517:8)
at Interface._ttyWrite (readline.js:735:14)
at ReadStream.onkeypress (readline.js:98:10)
at ReadStream.EventEmitter.emit (events.js:115:20)
at emitKey (readline.js:1057:12)
It all makes sense when you take a look at the implementation of the assert module, lines 101-109:
function fail(actual, expected, message, operator, stackStartFunction) {
throw new assert.AssertionError({
message: message,
actual: actual,
expected: expected,
operator: operator,
stackStartFunction: stackStartFunction
});
}
So, a better description might be that it is not used automatically in the message, but it can be used if you catch the exception and create an appropriate message yourself. In consequence, this parameter may be useful if you are going to create your own testing framework.
You can force Node.js to use that parameter if you omit the message parameter, e.g. by passing undefined explicitly:
> assert.fail(23, 42, undefined, '###')
AssertionError: 23 ### 42
[...]

Custom REPL in nodejs

I'm trying to play with the nodejs built in REPL from the documentation.
http://nodejs.org/api/repl.html
The example of adding an item is as follows:
repl.start().context.m = msg;
I cant seem to find away to add multiple menus. I've tried doing:
menus = {m = 'hello', f = 'foo'}
repl.start().context = menus
But that doesn't work either. I get:
testREPL> m
TypeError: needs a 'context' argument.
at REPLServer.self.eval (repl.js:113:21)
at Interface.<anonymous> (repl.js:250:12)
at Interface.EventEmitter.emit (events.js:88:17)
at Interface._onLine (readline.js:199:10)
at Interface._normalWrite._line_buffer (readline.js:308:12)
at Array.forEach (native)
at Interface._normalWrite (readline.js:307:11)
at Socket.ondata (readline.js:90:10)
at Socket.EventEmitter.emit (events.js:115:20)
at TCP.onread (net.js:395:14)
Does anybody know how to get this working?
You can't assign to the context property, you have to add properties to it. What you are trying is "overwriting" it with your own object. Try to assign each property by itself instead:
var context = repl.start({}).context;
context.m = 'hello';
context.f = 'foo';

custom stream object? (nodejs)

Is it possible to extend / initialize the require('stream').Stream; object ? I would like to be able to create a stream object that i can push data to and have all the listeners notified when new data arrive.
I tried the following:
var stream = require('stream');
var test = new stream.Stream();
test.write(new Buffer('mads'));
But i get the following error:
TypeError: Object [object Object] has no method 'write'
at repl:1:6
at Interface.<anonymous> (repl.js:168:22)
at Interface.emit (events.js:67:17)
at Interface._onLine (readline.js:153:10)
at Interface._line (readline.js:408:8)
at Interface._ttyWrite (readline.js:585:14)
at ReadStream.<anonymous> (readline.js:73:12)
at ReadStream.emit (events.js:88:20)
at ReadStream._emitKey (tty_posix.js:306:10)
at ReadStream.onData (tty_posix.js:69:12)
at ReadStream.emit (events.js:67:17)
For anyone who stumbles on this question today (node v0.10.x), this can be easily achieved using the PassThrough stream introduced with streams2.
var stream = require('stream');
var test = stream.PassThrough();
test.write('mads');
test.end();
You have to create those methods yourself and also set the writable property to true, and don't forget to emit the events in those methods you override as well so that you can use it as a regular event emitter. Check this question for more information.

Resources