Syntax check for JavaScript using command - javascript

Are there equivalent to perl -c syntax check for JavaScript from command? Given that I have NodeJS installed?
JSLint is not considered as it is not a real parser. I think YUI compressor is possible but I don't want to install Java on production machines, so I am checking if Node.JS already provided this syntax check mechanism.

If you want to perform a syntax check like that way we do in perl ( another scripting language) you can simply use node -c <js file-name>
e.g. a JS file as test.js has:
let x = 30
if ( x == 30 ) {
console.log("hello");
else {
console.log( "world");
}
now type in node -c test.js
it will show you
test.js:5
else {
^^^^
SyntaxError: Unexpected token else
at startup (bootstrap_node.js:144:11)
at bootstrap_node.js:509:3
Now after fixing the syntax issue as
let x = 30
if ( x == 30 ) {
console.log("hello");
} else {
console.log( "world");
}
check syntax - node -c test.js will show no syntax error!!
Note - we can even use it to check syntax for all files in a dir. - node -c *.js

Try uglify. You can install it via npm.
Edit: The package name has changed. It is uglify-js.

nodejs --help
explains the -p switch: it evaluates the supplied code and prints the results. So using nodejs -p < /path/to/file.js would be a disastrous way to check the validity of node.js code on your server. One possible solution is the one indicated in this SO thread. The one thing not so good about it - the syntax error messages it reports are not terribly helpful. For instance, it tell you something is wrong but without telling you where it is wrong.

Related

"ReferenceError: $jscomp is not defined" when changing output language spec by google-closure-compiler jar

I've downloaded the most recent version of compiler and i've tried to optimize js code with these flags:
java -jar closure-compiler-v20211006.jar -W VERBOSE -O WHITESPACE_ONLY
--language_out ECMASCRIPT5 $script_path_in --js_output_file $script_path_tmp
closure compiler has optimized this lines of code:
for(var extraProperty of extraProperties){
option.setAttribute(extraProperty,initialOption[extraProperty]);
}
into
for (var $jscomp$iter$0 = $jscomp.makeIterator(extraProperties), $jscomp$key$extraProperty = $jscomp$iter$0.next(); !$jscomp$key$extraProperty.done; $jscomp$key$extraProperty = $jscomp$iter$0.next()) {
var extraProperty = $jscomp$key$extraProperty.value;
{
option.setAttribute(extraProperty, initialOption[extraProperty])
}
}
And as a result i receive such error in browser:
all_compressed.js Uncaught ReferenceError: $jscomp is not defined
Is there a way to change language spec with this compiler without adding side dependencies into the project, or maybe it's a bug?
Git bug tracker
The best option for white space only mode is to set the language out to the latest ECMASCRIPT version used by the source code (or later) to avoid runtime dependencies.

Command not working inside execSync in nodejs

I have one shell command which is working fine from terminal but when I try to run from nodejs it is giving me the error
Orignal Command
awk -v RS='"[^"]*"' '{n+=gsub(/\n/, "&")} END{print n}' <(sed '$s/$//' file.txt)
Node Js Code
execSync("awk -v RS='\"[^\"]*\"' '{n+=gsub(/\\n/, \"&\")} END{print n}' <(sed '$s/$//' "+ filePath+')')
The exesync is giving the same output but it is showing me the error Syntax error: "(" unexpected
<() is a bash-specific process substitution syntax. execSync defaults to using /bin/sh, usually a narrowly POSIX-compliant shell, which means it doesn't support the syntax. Explicitly use bash instead:
execSync("command goes here", {
shell: "/bin/bash"
});

detect whether ES Module is run from command line in Node

When using CommonJS modules in Node, you can detect whether a script is being run from the command line using require.main === module.
What is an equivalent way to detect whether a script is being run from the command line when using ES Modules in Node (with the --experimental-modules flag)?
Use
if (import.meta.url === `file://${process.argv[1]}`) {
// module was not imported but called directly
}
See the MDN docs on import.meta for details.
Update Sep 27, 2021
Perhaps more robust, but involving an extra import (via Rich Harris)
import {pathToFileURL} from 'url'
if (import.meta.url === pathToFileURL(process.argv[1]).href) {
// module was not imported but called directly
}
There is none - yet (it's still experimental!). Although the prevailing opinion is that such a check is a bad practice anyway and you should just provide separate scripts for the library and the executable, there is an idea to provide a boolean import.meta.main property for this purpose.
The other answers get close, but will miss the mark for a pretty typical usecase - cli scripts exposed by the bin property in package.json files.
These scripts will be symlinked in the node_modules/.bin folder. These can be invoked through npx or as scripts defined in the scripts-object in package.json. process.argv[1] will in that case be the symlink and not the actual file referenced by import.meta.url
Furthermore, we need to convert the file path to an actual file://-url otherwise it will not work correctly on different platforms.
import { realpathSync } from "fs";
import { pathToFileURL } from "url";
function wasCalledAsScript() {
// We use realpathSync to resolve symlinks, as cli scripts will often
// be executed from symlinks in the `node_modules/.bin`-folder
const realPath = realpathSync(process.argv[1]);
// Convert the file-path to a file-url before comparing it
const realPathAsUrl = pathToFileURL(realPath).href;
return import.meta.url === realPathAsUrl;
}
if (wasCalledAsScript()) {
// module was executed and not imported by another file.
}
I would have posted this as a comment on the accepted answer, but apparently I'm not allowed to comment with a fresh account.
The module global variable will be defined in CommonJS, but won’t exist at
all in an ES module. Yes, there is an inconsistency there, that ES modules are
the things that don’t have module variables.
You can check for an undefined variable by seeing if typeof v is the string
(not value!) 'undefined'.
That turns into:
const inCommonJs = typeof module !== 'undefined';
console.log(`inCommonJs = ${inCommonJs}`);
If we put that exact code into both .cjs and .mjs files, we get the correct answers:
$ node foo.mjs
inCommonJs = false
$ cp foo.mjs foo.cjs
$ node foo.cjs
inCommonJs = true
I like import.meta.url === `file://${process.argv[1]}` , but it does not work in Windows inside bash shell. This is the alternative that is only checking the basename:
const runningAsScript = import.meta.url.endsWith(path.basename(process.argv[1]));
It looks like there is a documented way to do this now:
if (require.main === module) {
console.log('executed directly');
. . .
}

How can my grunt task see if --verbose flag is on?

I have a Grunt task and if the --verbose command line flag is on, I want to echo some more info to the console.
Finding out if that flag is on isn't possible with grunt.option('verbose'). It also doesn't appear to be anywhere in grunt.package.
How can I see, from within a task, if the user has the verbose flag set?
That is imho because grunt.option works only for a grunt used flags, it doesnt take every shell argument you provide.
The esiest module-free solution is to parse your flag from process.argv, that returns an array.
Your flags would start at position 2, so if --verbose is the first argument, you would claim it by process.argv[2] How do I pass command line arguments?
You can easily test it by creating a javascript file
var args = process.argv;
process.argv.forEach( (val, index, array) => {
var flag = val.replace(new RegExp('-', 'g'), '');
console.log(flag);
});
and calling it in your shell
node testParams.js --argument1 -t.
The outcome will look like this
hakim#cortana:~/Sites/DOODLINGS $ node testParams.js --verbose -t
/usr/local/Cellar/node/7.5.0/bin/node
/Users/hakim/Sites/DOODLINGS/testParams.js
verbose
t
With some googling, you can find module to extract params for you. I dont use grunt so cant help you much there.

node.js: suppress require()'s echoing of parse errors to stderr

node.js 10.26 will rightfully throw an error when you try to require a file that is not valid javascript (or JSON).
My problem is that it also outputs to stderr:
borken.js - know to be broken javascript file
,,>Z>badfile!=-csa&asd;'asdl ds]=}{ADS}DAS:LMFSV'
test.js
try {
var borken = require('./borken');
} catch (e) {} finally {
console.log('finally!');
}
Expected
$ node test.js
finally!
Actual
$ node test.js
/path/to/borken.js:1
(function (exports, require, module, __filename, __dirname) { asd;'asdl
^^^^^
finally!
The first three lines are output to stderr (running as node test.js 2> /dev/null suppresses them).
Is there any way to get rid of them?
What I've done so far:
I debugged while following the source and narrowed down the culprit to:
lib/module.js:439
var compiledWrapper = runInThisContext(wrapper, filename, true);
runInThisContext is defined in lib/vm.js, which unfortunately is a C++ wrapper, so I couldn't really follow what is going on through there.
I guess I'm looking for a magic "don't spam stderr" flag or any knowledge of this being fixed in any latest versions.
Apparently this has been fixed in the dev branch (0.11.x) but not in the latest stable (0.10.29)
Github issue: Syntax errors are printed to stderr, even when wrapped with try/catch #6920

Categories