Why might something execute in node but not in the REPL? - javascript

I have the following script:
const lib = require('./lib.js');
const fs = require('fs');
const graph = fs.readFileSync('../js-working-dir/add_graph.pb', 'utf8');
const sess = new lib.Session(graph);
const results = sess.run({"a": 5, "b": 6}, ["o"]);
console.log(results[0]);
(For context lib.js is a compiled emscripten module; it is fairly big, approximately 40MB, otherwise I would upload it.)
When I execute this script in node, it works fine. However when I execute it in the REPL (same working directory and everything) my code hangs on const sess = new lib.Session(graph);.
Any ideas of why this might be the case? Does Emscripten treat the REPL and node execution differently? Is there a way I can debug where it is getting stuck?
Thanks so much,

Problem found, appears to be a bug in urandom...
https://github.com/kripken/emscripten/issues/4905

Related

TypeError: Cannot read property 'readFileSync' of undefined NodeJS dom-parser

Trying to use Dom-Parser with Discord.js. Couldn't find help from any where else.
Error on line 15 fs.readFile
I also had a lot problems getting fs working. First it wasn't defined then it could not be runned before initalization, just got that fixed (I hope)
// Discord stuff.
const Discord = require('discord.js');
const client = new Discord.Client();
const config = require('./config.json');
const token = config.token;
// DomParser
var DomParser = require('dom-parser');
var parser = new DomParser();
var data = fs.readFileSync(filepathHidden);
// Other requirements
var fs = require('fs');
// when getting online.
client.once('ready', () => {
console.log('WAHAHAHA IM ALIVE!');
}),
fs.readFile('https://url.com)', 'utf8', function(err, html){
if (!err){
var dom = parser.parseFromString(html);
console.log(dom.getElementsByClassName('new_solution_box_title').innerHTML);
}
})
client.login(token);
var is hoisted.
So since you have var fs, there is a variable called fs in the function / module / global scope where you have that statement.
It starts out undefined.
When you say fs = require('fs') you assign the file system module to it. At that point it stops being undefined.
On the previous line when you try to read it with fs.readFileSync, you haven't yet defined it so you get an error.
Order matters.
See answer for same error in another stack overflow question.
The link to the answer that helped me is from Arun Kumar Mohan
What he recommended was to import as follows: import * as fs from 'fs'
Please read NodeJS Documentation about URL object support for FS API. It seems that only file: protocol is supported when using URLs.
However, I don't even recommend you to use fs.readFileSync because it is a blocking operation (code execution will stop until it finishes) and there is a network transfer involved.
Try fetching the file first instead using fetch, XMLHttpRequest or your preferred library, and then parse it. Or at least use fs.readFile which will perform its tasks asynchronously (file: protocol limitation still applies).
For the non defined error, you must import/require fs before using it. In other words, var fs = require('fs') must appear before any other use of fs.

Simple node module command line example

I want to make a simple node module that can be run from the command line that I can input files into, then it might change every instance of 'red' to 'blue' for example and then save that as a new file. Is there a simple example out there somewhere that I can edit to fit my purposes? I've tried looking but couldn't find one that was sufficiently simple to understand how to modify it. Can anyone help?
A simple example of replace.js (both old and new files are supposed to be in UTF-8 encoding):
'use strict';
const fs = require('fs');
const oldFilePath = process.argv[2];
const newFilePath = process.argv[3];
const oldFileContent = fs.readFileSync(oldFilePath, 'utf8');
const newFileContent = oldFileContent.replace(/red/g, 'blue');
fs.writeFileSync(newFilePath, newFileContent);
How to call:
node replace.js test.txt new_test.txt
Documentation on used API:
process.argv
fs.readFileSync()
fs.writeFileSync()

Load text as JavaScript object in Node.js

I have a javascript file for node.js:
module.exports = {
someString: 'blblalb'
}
I want to able to read the file as a javascript object, using fs.readFileSync. I can't use require because I am using a variable that may be modified in runtime to load the file.
Is that possible?
You can use eval('JavaScript string') but is highly recommended not to. It is a serious security risk if you cannot 100% trust the source of the text. If a malicious user figures out a way to modify the text they have complete control of your system. It is not a path I would take or recommend.
const text = 'console.log("Hello")';
eval(text);
If I saw that code when I was doing a code review we would definitely be having some words.
it's possible to evaluate a file or string variable as child module in hacky yet valid way.
The problem is that Node.js module environment should be unaware of these operations. Child module may load other modules and contain require(...), it will fail if there is no require function (there is none if it is evaluated with vm) or it uses wrong module relative path (this will happen with eval), also there will be no dedicated module.exports for a module. This can be fixed by wrapping module source with Node.js module wrapper that was rewired to match child module location.
const fs = require('fs');
const Module = require('module');
const path = require('path');
const childModuleAbsPath = path.resolve('./foo/bar.js');
const childModuleBody = fs.readFileSync(childModuleAbsPath);
const childModuleObj = { exports: {} };
const { dir: childModuleDirname, base: childModuleFilename } = path.parse(childModuleAbsPath);
const childRequire = modulePath => module.require(childModuleAbsPath);
require('vm').runInThisContext(Module.wrap(childModuleBody))(
childModuleObj.exports,
childRequire,
childModuleObj,
childModuleDirname,
childModuleFilename
);
In this case childModuleObj.exports.someString === 'blblalb' after bar child module was evaluated.
This is XY problem that should be addressed in another way.
If the intention is to reevaluate a module with new variables, this can be done by invalidating Node module cache by modifying require.cache, e.g. with decache:
decache('./foo/bar');
const reloadedBar = require('./foo/bar');

A way to call execl, execle, execlp, execv, execvP or execvp from Node.js

POSIX systems expose family of exec functions, that allow one to load something maybe different into current process, keeping open file descriptors, process identifier and so on.
This can be done for variety of reasons, and in my case this is bootstrapping — I want to change command line options of my own process, and then reload it over existing process, so there would be no child process.
Unfortunately, to much of my surprise, I could not find the way to call any of exec* functions in Node.js. So, what is the correct way to replace currently running Node.js process with other image?
I have created a module to invoke execvp function from NodeJS: https://github.com/OrKoN/native-exec
It works like this:
var exec = require('native-exec');
exec('ls', {
newEnvKey: newEnvValue,
}, '-lsa'); // => the process is replaced with ls, which runs and exits
Since it's a native node addon it requires a C++ compiler installed. Works fine in Docker, on Mac OS and Linux. Probably, does not work on Windows. Tested with node 6, 7 and 8.
Here is an example using node-ffi that works with node v10. (alas, not v12)
#!/usr/bin/node
"use strict";
const ffi = require('ffi');
const ref = require('ref');
const ArrayType = require('ref-array');
const stringAry = ArrayType('string');
const readline = require("readline");
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
rl.question('Login: ', (username) => {
username = username.replace(/[^a-z0-9_]/g, "");
rl.close();
execvp("/usr/bin/ssh", "-e", "none", username+'#localhost');
});
function execvp() {
var current = ffi.Library(null,
{ execvp: ['int', ['string',
stringAry]],
dup2: ['int', ['int', 'int']]});
current.dup2(process.stdin._handle.fd, 0);
current.dup2(process.stdout._handle.fd, 1);
current.dup2(process.stderr._handle.fd, 2);
var ret = current.execvp(arguments[0], Array.prototype.slice.call(arguments).concat([ref.NULL]));
}
I ended up using ffi module, and exported execvp from libc.

Node.js fs.createWriteStream undefined function

I am trying to write data to a text file in Node.js. When initializing the write stream I get the following error message:
Be sure you have included at the top of your node program
var fs = require('fs');
Also It looks like you spelled 'Stream' incorrectly
fs.createWriteSteam > fs.createWriteStream
Another issue that may come up is trying to get createWriteStream from 'fs/promises'.
It doesn't exist on 'fs/promises'. (At least on NodeJS version 14);
My solution was to import both:
var fs = require('fs');
var fsPromises = require('fs/promises');

Categories