ESLint no-undef on ES6 function with named arguments - node.js

I have a function defined like this:
const generate = (report={}, buffer=false) => {
// do stuff
}
Notice how both of the parameters have default values.
When I call that function and name an argument I get a no-undef ESLint error.
generate(buffer = true);
ESLint says that "buffer" is not defined. It's not detecting that it is a named argument. Does anyone know how to change my .eslintrc to account for named arguments. I can't find anything online.
Thanks in advance!

What you are expecting from this code does not exists in Javascript.
You are getting no-undef ESLint error because buffer is never declared. Since there are no named params in JS, you could just call generate(true).
Although that would actually result in report being equal to true and buffer being settted to its default, which you have setted tofalse.
To achieve something closer to what you are looking for, you could switch the variable orders:
generate(buffer = false, report = {})
And then calling generate(true) would cause a call having the parameters:
buffer = true and report = {}.
Hope that makes sense.
For further reading, I recommend: http://2ality.com/2011/11/keyword-parameters.html

Related

How Node.js implements require() in its own internals?

While going through the source of require() in the GitHub repository for Node.js, I am surprised and confused by one thing:
The file loader.js that actually defines the require() logic, uses require() calls in itself.
How is this possible?
Is there some other code for the require() calls used in the internals of Node.js, for e.g. all the require() calls used in loader.js file.
I know that all require() calls in a Node.js program that I write in a given editor, on my machine, are resolved using the Module.prototype.require method declared in loader.js.
It seems like the actual base require is defined here, in /internal/bootstrap/loaders.js. This line makes use of [compileFunction][3] in /lib/vm.js. That again uses _compileFunction which is defined as such:
const {
ContextifyScript,
MicrotaskQueue,
makeContext,
isContext: _isContext,
constants,
compileFunction: _compileFunction,
measureMemory: _measureMemory,
} = internalBinding('contextify');
Which, if we go back to /internal/bootstrap/loaders.js, is defined as such:
let internalBinding;
{
const bindingObj = ObjectCreate(null);
// eslint-disable-next-line no-global-assign
internalBinding = function internalBinding(module) {
let mod = bindingObj[module];
if (typeof mod !== 'object') {
mod = bindingObj[module] = getInternalBinding(module);
ArrayPrototypePush(moduleLoadList, `Internal Binding ${module}`);
}
return mod;
};
}
And getInternalBinding we find at the top of that file, in this comment:
// This file is compiled as if it's wrapped in a function with arguments
// passed by node::RunBootstrapping()
/* global process, getLinkedBinding, getInternalBinding, primordials */
Which brings an end to our tour here. So yes, there's still some code between the require() defined in loader.js and the actual C binding. As for what happens in C-land, I'm not sure myself.

Conditionally import conditionally existing file in Vue

I need to import a file into my project when an environment variable is set, say dist/built.esm.js. It's implied that when the environment variable is set, the file will exist, otherwise it may or may not exist. It seems straightforward to just wrap a call to import in an if statement that checks for the environment variable, but Vue throws the below warning even if the if statement never passes:
And the code:
if (process.env.VUE_APP_USE_COMPILED == 'true') {
const compiledPackage = require('./dist/built.esm.js')
Vue.use(compiledPackage)
}
Setting the if statement to always be false in a nondeterminate way (setting a string var and then comparing it to a different value, instead of just if (false)) results in the same problem, which rules out any possibility of the environment variable being 'true' when it isn't supposed to be.
A temporary workaround I found is to wrap the import in a try/catch, which instead displays a warning instead of an error:
How can I get rid of the errors and warnings completely? I do want it to still error if the file doesn't exist but the environment variable has been set to true, but it shouldn't fail or warn on compilation if the statement hasn't even executed yet.
Does this work?
if (process.env.VUE_APP_USE_COMPILED == 'true') {
import('dist/built.esm.js')
.then(obj => Vue.use(obj))
.catch(err => console.log(err));
}
I managed to figure this out on my own. I used the resolve.alias property in the Webpack configuration to allow a 'soft fail' when the file doesn't exist. I changed my import to use an alias (my-compiled-package-alias), which would conditionally resolve to either the built file or an empty dummy file (dev/import-dummy.js). I had to use resolve.alias rather than resolve.fallback, since Vue2 uses Webpack v4 which doesn't include the latter property.
My updated code:
if (process.env.VUE_APP_USE_COMPILED == 'true') {
const compiledPackage = require('my-compiled-package-alias')
Vue.use(compiledPackage)
}
In my vue.config.js:
module.exports = {
...
configureWebpack: {
resolve: {
alias: {
"my-compiled-package-alias":
process.env.VUE_APP_USE_COMPILED ? "./dist/built.esm.js": "./import-dummy.js"
}
}
},
...
}
but it shouldn't fail or warn on compilation if the statement hasn't even executed yet
Compilation happens before execution. If you get a compile error, that means something went wrong before your code was executed, including any conditionals.
What I believe happens here is that you're using webpack, and it's trying to include dist/built.esm.js in your bundle. Behind the scenes, webpack actually replaces require with some magic. To get around this, use __non_webpack_require__ instead
You could try setting up a compile-time constant using DefinePlugin in your webpack config, maybe something like
plugins: [
new webpack.DefinePlugin({
// this is resolved compile-time
USE_COMPILED: process.env.VUE_APP_USE_COMPILED == 'true'
})
]
Then, in your code
if (USE_COMPILED) require('./dist/built.esm.js')
Here the value of USE_COMPILED should be replaced by webpack compile-time with true if your environment var is set to 'true', and false otherwise.

New to Node.js. Calling function from other file but node is printing whole file content

I have two files basic.js basic1.js. Please find code below :
basic.js :
console.log("My first node statement");
const sum =(a,b)=> a+b;
console.log(sum(1,1));
module.exports.sum =sum;
basic1.js :
const sum1= require('./basic');
const EventE= require('events');
const eventEmitter = new EventE();
eventEmitter.on('firstEvent',(a,b)=> {
console.log(sum1.sum(a, b));
});
eventEmitter.emit('firstEvent',5,6);
on running basic1.js I am getting below output which seems incorrect as It should just called the function.
node basic1.js
My first node statement
2
11
As indicated in the comments, anytime you require a module, it runs all of the top level statements in that module. This is so that any dynamically created/assigned objects, functions, constants, etc actually exist. It's very similar to adding a script to your webpage in a browser. You can either remove the console statements in your required file, or move them into a scope that is not automatically run (a function expression or a method, for instance).
Additionally in the comments, it was requested to be able to simply use the function. The reason this is occuring is because of this line:
module.exports.sum =sum;
Basically you are returning an object with a property named sum. This is because, by default and for simplicity, module.exports is an object with none of its own keys. In code terms, the module results as:
{
sum: sum
}
To fix this, change the line to:
module.exports = sum;
Now, you are simply returning the function and only the function.

Include functions of different files in Node.js

Okay, so... I load several files from a folder and want the functions from the loaded files to be loaded into the file that loads the files. As if they had been in the file from the start.
My current code works fine so far, but I can't use "this" in the loaded function, because it's not the "this" from the file that loaded the function.
Loading all files and include their functions.
return fs.readdirAsync(path.join(__dirname, 'Handlers')).map(file => {
if (file.substr(file.length - 3) === '.js') {
let handlerFile = require(path.join(__dirname, 'Handlers', file))
for (const handlerName of Object.keys(handlerFile)) {
this[handlerName] = handlerFile[handlerName]
}
}
})
This is how the loaded file looks like:
module.exports = {
test: (arguments) => {
console.log(this)
}
}
So, if I call this.test() now in the file that loaded the function, console.log(this) is executed. Everything works so far, but "this" is empty.
Is there a way that the loaded function gets the "this" from the file that loads the functions? (Without passing it to the function)
I hope you understand what I want. Thanks for any help.
The value of this is not automatically passed from your original environment to the loaded module. When a module is loaded with require(), the value of this in that module is set to the value of module.exports and since your test() method is declared using an arrow function, the value of this inside of your .test() method will be the lexical value of this which in the case of the code you show me will be the original value of module.exports (before you reassigned it) since that's what this was when the module was originally loaded.
If you're calling the .test() method with something like this.test(), then a very simple fix is to just stop using an arrow function for your method and use a regular function. Regular functions called as methods as in obj.test() will set the value of this to be obj in the method. If that's what you want, then just stop using an arrow function. In fact, there are very, very, very few cases where you want a method to be declared using an arrow function. Methods should nearly always be normal function definitions. Remember, an arrow function is NOT just a shortcut syntax. It changes the behavior for setting the value of this.
So, you could just change your loaded file to this:
module.exports = {
test: function(args) {
console.log(this)
}
}

RequireJS Dependancies Fail Randomly: "Module has not been loaded yet for context", Puzzling

I've run into a problem with RequireJS that pops up randomly in different areas over and over, after a long period (about a year) of working fine.
I declare my requireJS file like this:
define(['TestController'], function (TestController)
{
return {
oneFunction: function(callback)
{
//When I try to use "TestController" here, I get the
//"Error: Module name "TestController" has not been
//loaded yet for context" error...
TestController.test(); //ERROR
//I had been using the above for years, without changes,
//and it worked great. then out of the blue started not
// working. Ok, let's try something else:
if(typeof TestController == "undefined")
{
var TestController = require('TestController'); //ERROR
}
//The above method worked for a few months, then broke AGAIN
// out of the blue, with the same error. My last resort is one
// that always works, however it makes my code have about 20+
//layers of callbacks:
require(['TestController'], function(TestController){
TestController.test();
//WORKS, but what's the point of declaring it as a
//requirement at the top if it doesn't work and I have to
//wrap my code every time? :(
});
},
anotherFunction: function()
{
console.log("hello");
}
}
});
I am getting the "Error: Module name "TestController" has not been loaded yet for context" error over and over until I re-declare the dependency... My question is, what's the point of declaring 'TestController' at the top as a dependency if I have to keep re-declaring it as if I never listed it? What am I doing wrong here?
I declare 'TestController' in other files and it works great, but every once and a while, ONE of the declarations will fail...and it's always a different file (there are about 200-300)... I never know which one, and the only way to fix it is to re-declare it and wrap it.
Anyone see anything I'm doing wrong that could be causing this? I keep updating RequireJS to see if it fixes it and it doesn't :/
Version
RequireJS 2.1.22
jquery-1.12.1
node 4.2.6
As #Louis pointed out, it was circular dependencies that was causing the problem.
Circular Dependency Solution #1: 'exports'
Here's the solution straight from RequireJS's documentation:
If you define a circular dependency ("a" needs "b" and "b" needs "a"), then in this case when "b"'s module function is called, it will get an undefined value for "a". "b" can fetch "a" later after modules have been defined by using the require() method (be sure to specify require as a dependency so the right context is used to look up "a"):
//Inside b.js:
define(["require", "a"],
function(require, a) {
//"a" in this case will be null if "a" also asked for "b",
//a circular dependency.
return function(title) {
return require("a").doSomething();
}
}
);
If you are familiar with CommonJS modules, you could instead use exports to create an empty object for the module that is available immediately for reference by other modules.
//Inside b.js:
define(function(require, exports, module) {
//If "a" has used exports, then we have a real
//object reference here. However, we cannot use
//any of "a"'s properties until after "b" returns a value.
var a = require("a");
exports.foo = function () {
return a.bar();
};
});
Circular Dependency Solution #2: Visualize with madge
I came accross this npm module that will create a dependency graph for you : https://github.com/pahen/madge
I've decided to analyze my code with madge and remove the circular dependencies.
Here is how I used the tool:
cd <Client-Code-Location>
madge --image dep.png .
This gave me an image of the dependencies, however there were no circular dependencies found. So I decided to try another way:
cd <Client-Code-Location>
madge --image dep.png --format amd .
This way I was able to see where I had the circular dependency. :)

Resources