Weird behavior in Node REPL when pasting text (Windows OS) - Crashes - javascript

I'm sorry if this has already been posted but I have no idea how to search for what I am experiencing.
This be might Windows OS specific I don't know.
I use VS code as my IDE and when testing node code I open the integrated terminal and run node from there. I then copy and paste a lot of my code to run them line by line and do testing etc. I noticed that it would completely lock up node when pasting sometimes. After a painstakingly long time I finally found it only happens when I copied and pasted large amounts of text. IE I could highlight my whole code, copy and paste and it would lock up node. But then if I tried copying only half and executed it then the second half and executed it, it would work.
I thought this was VS code related until recently I did it directly in the node REPL outside of VS code and it crashed there also.
Has anyone else experienced this? I did a google and found some reported bugs ages ago similar to what I'm experiencing but they were meant to be fixed.
To make this even weirder, sometimes I CAN execute the large amount of text under certain conditions. It seems to work if I copy and paste in small batches first, ie split the code into 3 parts and execute them individually, then if I now go back and highlight it all and copy and paste, it executes it fine. But then I load a new node up, copy and paste all code again and it fails. Not really sure what's going on.
EDIT: Here is the code below. If you open the node REPL and paste of this, it will freeze on the first line (so don't worry about the requires not being able to find the modules). NOTE; the code has been changed to take out the IP so IF does execute it will error as I just replaced some keywords with random text. Ignore this, the point of it is to show that it won't copy and paste past the first line, it will freeze. Any help appreciated!
//{"_id":"56aba3108d6d183da42403c2"}
//placeholder
const request = require('request');
var mongoose = require ("mongoose");
var lodash = require ("lodash");
var myFuncs = require("./functions");
var item_urls;
var options = {
json: true
};
var test = [] ;
function updateDB (){
var url = "get stuff";
request(url, options, (error, res, body) =>{
if (error) {
return console.log(error)
};
if (!error && res.statusCode == 200) {
console.log("executing cb1");
item_urls = body.payload.items;
myFuncs.fixItemIDs (item_urls);
var primes = item_urls.filter(item => item.item_name.includes("Strun Wraith Set"));
for (item in primes)
{
let url = `https://get more stuff/v1/items/${primes[item].url_name}`;
// console.log (url);
request(url, options, (error, res, body) =>{
if (error) {
return console.log(error)
};
if (!error && res.statusCode == 200) {
console.log(`Getting item ${url}`);
test.push(body.payload.item);
myFuncs.fixItemIDs (test);
}
});
};
console.log ("done");
};
});
}
updateDB();

I logged it as a Bug on Github and someone else tested and reproduced the issue. It is now a confirmed bug they are going to look into. It is even present in beta/latest version.
https://github.com/nodejs/node/issues/32999

Related

Does anyone know how to define navigator online in main process in electron?

I know you can use navigator onLine inside the renderer process because it's a rendered inside a browser. But what I'm trying to do is something like this in the main process:
if (navigator.onLine){
mainWindow.loadURL("https://google.com")
} else {
mainWindow.loadFile(path.join(__dirname, 'index.html'));
}
So basically if the user is offline, just load a local html file, and if they're online, take them to a webpage. But, like expected, I keep getting the error that 'navigator is not defined'. Does anyone know how can I somehow import the navigate cdn in the main process? Thanks!
TL;DR: The easiest thing to do is to just ask Electron. You can do this via the net module from within the Main Process:
const { net } = require ("electron");
const isInternetAvailable = () => return net.isOnline ();
// To check:
if (isInternetAvailable ()) { /* do something... */ }
See Electron's documentation on the method; specifically, this approach doesn't tell you whether your service is accessible via the internet, but rather that a service can be contacted (or not even this, as the documentation mentions links which would not involve any HTTP request at all).
However, this is not a reliable measurement and you might want to increase its hit rate by manuallly checking whether a certain connection can be made.
In order to check whether an internet connection is available, you'll have to make a connection yourself and see if it fails. This can be done from the Main Process using plain NodeJS:
// HTTP code basically from the NodeJS HTTP tutorial at
// https://nodejs.dev/learn/making-http-requests-with-nodejs/
const https = require('https');
const REMOTE_HOST = "google.com"; // Or your domain
const REMOTE_EP = "/"; // Or your endpoint
const REMOTE_PAGE = "https://" + REMOTE_HOST + REMOTE_EP;
function checkInternetAvailability () {
return new Promise ((resolve, reject) => {
const options = {
hostname: REMOTE_HOST,
port: 443,
path: REMOTE_EP,
method: 'GET',
};
// Try to fetch the given page
const req = https.request (options, res => {
// Yup, that worked. Tell the depending code.
resolve (true);
req.destroy (); // This is no longer needed.
});
req.on ('error', error => {
reject (error);
});
req.on ('timeout', () => {
// No, connection timed out.
resolve (false);
req.destroy ();
});
req.end ();
});
}
// ... Your window initialisation code ...
checkInternetAvailability ().then (
internetAvailable => {
if (internetAvailable) mainWindow.loadURL (REMOTE_PAGE);
else mainWindow.loadFile (path.join (__dirname, 'index.html'));
// Call any code needed to be executed after this here!
}
).catch (error => {
console.error ("Oops, couldn't initialise!", error);
app.quit (1);
});
Please note that this code here might not be the most desirable since it just "crashes" your app with exit code 1 if there is any error other than connection timeout.
This, however, makes your startup asynchronous, which means that you need to pay attention on the execution chain of your app startup. Also, startup may be really slow in case the timeout is reached, it may be worth considering NodeJS' http module documentation.
Also, it makes sense to actually try to retrieve the page you're wanting to load in the BrowserWindow (constant values REMOTE_HOST and REMOTE_EP), because that also gives you an indication whether your server is up or not, although that means that the page will be fetched twice (in the best case, when the connection test succeeds and when Electron loads the page into the window). However, that should not be that big of a problem, since no external assets (images, CSS, JS) will be loaded.
One last note: This is not a good metric of whether any internet connection is available, it just tells you whether your server answered within the timeout window. It might very well be that any other service works or that the connection just is very slow (i.e., expect false negatives). Should be "good enough" for your use-case though.

copyFileSync not copying file and not throwing error

I'm running a function which I've written in JavaScript inside a nodejs/Electron client.
This function is meant to copy a file from the users flash drive to their c:/Windows/System32 (The file is being copied there so that it can be ran from Command Prompt manually next time the computer is touched without having to switch directories)
The problem is, the files are not being copied, and copyFileSync is not throwing an error.
Here is the code I'm specifically having a problem with:
try {
console.log('copying t.bat');
fs.copyFileSync(remote.app.getAppPath() + '\\app\\files\\scripts\\files\\t.bat', 'C:\\Windows\\System32\\t.bat');
} catch(err) {
console.log('could not copy t.bat', err);
$('#mfail_title').text('Could not copy t.bat file');
$('#mfail_data').text(err);
UIkit.modal("#master_fail").show();
return false;
}
As you can see, I have copyFileSync inside a TRY CATCH block. I know this code is running because in the console I get copying t.bat, but nothing else.
How can I get my files to copy, or at least throw an error when it cannot?
This client is running inside OOBE mode on various Windows 10 machines, therefore always has administrator access.
I've tried updating to the async version of copyFile, but I'm having the same issue. Here is my code
var source = remote.app.getAppPath() + '\\app\\files\\scripts\\files\\t.bat';
var destination = 'C:\\Windows\\System32\\t.bat';
fs.copyFile(source, destination, (err) => {
if (err) {
console.log(err);
} else {
source = remote.app.getAppPath() + '\\app\\files\\scripts\\files\\p.bat';
destination = 'C:\\Windows\\System32\\p.bat';
fs.copyFile(source, destination, (err) => {
if (err) {
console.log(err);
} else {
source = remote.app.getAppPath() + '\\app\\files\\scripts\\files\\p.bat';
destination = 'C:\\Windows\\System32\\p.bat';
child = spawn("powershell.exe",['-ExecutionPolicy', 'ByPass', '-File', remote.app.getAppPath() + '\\app\\files\\scripts\\' + type + '.ps1']);
}
});
}
});
This should copy a file, then when it's complete it should copy another file, once that is complete, it should run a powershell script.
Each copyFile checks for an error before moving on, but it never throws an error, and the file is never copied.
I had a similar issue earlier, In which an Antivirus(Comodo) was not allowing electron app to access the hard drive.
Copy and other file operations were successful in that case as well, because electron in such case access the corresponding sandbox
Please check this is not the case with you.
You can actually access 'fs' in console from electron and check other things in the file system.
Looks to me as if you're using fs on then renderer process (client side) which will not work (assuming that your fs is the node.js fs module and (*)). Your first script seems to use jQuery (hints for renderer) and the second one uses remote in the first line.
fs can only (*) be used on the main process and you'll need to create an IRC channel and do something like:
ircRenderer.sendSync('copy-file-sync', {from: '/from/path', to: '/to/path'})
and, of course, implement the handler for that quickly invented 'copy-file' channel on the main process.
(*) Edit: I haven't played around a lot with nodeIntegration = true, so fs may or may not work on the renderer process with that flag set on the BrowserWindow. But the irc messaging should definitely work and if not, the problem is outside electron, probably related to file permissions.

Node render process gone while downloading files

I'm programming a small Electron program, that (currently) is able to download multiple big files from Google Drive. Some files are too big to be scanned so it tricks the server into believing the "Download anyway" button was clicked.
The problem is, that after 3, 7 or 12 files, the Chrome Dev Tools window shows "Render process gone".
3 files:
- download unblocking turned on while trying to download the same blocked file 3 times in a row. The 4th file crashes.
7 files:
- mixture of 5 non-blocked files and 2 blocked ones with download unblocking turned on. The 8th file (non-blocked) request crashes
12 files:
- downloading 9 non-blocked files and 3 blocked ones while download unblocking turned off
Therefore, I came to conclude, that "unblocking" a file takes up 3 of the 12 possible "slots". Then, everything (or at least the numbers) would make sense.
Unblocking works by sending another request with the same cookie char and a ?confirm=xxxx at the same url.
Note that the whole thing doesn't crash after 12 files if I use another file provider with 100mb test files.
It would be extremely helpful if you could point me in the right direction.
Here's a really simplified version of the code that's used. Note that a lot of variable declarations and other stuff is missing, but these parts seem to be the problematic ones:
// downloadmanager.js
function DownloadManager(pack) {
var _this = this;
this.downloadpackages = function (package, data, cb) {
sync.fiber(function () {
...
Object.keys(ht_distinct_urls).forEach(function (url) {
localfile = sync.await(_this.download(remotefile, sync.defer()));
console.log("Downloaded:" + localfile);
});
});
}
this.dl = function (remotefile, cb) {
request(request_options, (err, response, body) => {
// cb() in this location makes it crash at the 13th file
cb(null, "");
});
// cb() in this location doesnt make it crash (but also not download anything)
//cb(null, "");
}
this.download = function (remotefile, cb) {
// Try to download
_this.dl(remotefile, function (err, data) {
if (data.downloaded) { // It worked
cb(err, data);
} else if (data.unblocked) { // It was able to get a code to unblock it
_this.dl(data, cb); // Try again with the new cookie and the code
} else {
// Fck it, just return the data anyway for debugging
cb(err, data);
}
});
};
}
// renderer.js
sync.fiber(function () {
var pack = getPackage();
var dm = new DownloadManager(pack);
var download_result = sync.await(dm.downloadpackages(pack, ht_distinct_urls, sync.defer()));
console.log(download_result);
});
Okay, it seems like I found a solution while posting this question. I'll just post it anyway, maybe it helps someone else...
It seems like google blocks instant downloading. Adding a timeout of 5 seconds between downloads solved my problem. Haven't tested how low the timeout can be, but maybe the problem was solved by the settimeout callback anyway...

Electron - Invalid package on unzip

For around 3 weeks I've been working on an Electron app and finally decided to get around to adding update checking. For my research, the standard way to do this in Electron (using Squirrel) requires the user to physically install the application onto their computer. I would rather not do this, and keep everything as portable as possible. I then decided to try making my own update script by having the program download the update.zip, and extract it to overwrite the existing files. This works well, up until the very end. At the very end of the extraction, I receive a Invalid package error, and the actual app.asar file is missing, rendering the application useless.
I am using this to download and extract the updates:
function downloadFile(url, target, fileName, cb) { // Downloads
var req = request({
method: 'GET',
uri: url
});
var out = fs.createWriteStream(target+'/'+fileName);
req.pipe(out);
req.on('end', function() {
unzip(target+'/'+fileName, target, function() {
if (cb) {
cb();
}
});
});
}
function unzip(file, target, cb) { // Unzips
var out = fs.createReadStream(file);
out.pipe(unzipper.Extract({ path: target })).on('finish', function () {
dialog.showMessageBox({
type: 'question',
message: 'Finished extracting to `'+target+'`'
});
if (cb) {
cb();
}
});
}
And call it with:
downloadFile('http://example.com/update.zip', path.join(__dirname, './'), 'update.zip', function() { // http://example.com/update.zip is not the real source
app.relaunch();
app.quit();
});
And I use the unzipper NPM package (https://www.npmjs.com/package/unzipper).
The code works perfectly for all other zips, but it fails when trying to extract a zip containing an Electron app.
Anything I'm doing wrong, or maybe a different package that properly supports extracting zips with .asar files?
Edit 1
I just found https://www.npmjs.com/package/electron-basic-updater, which does not throw the same JavaScript error however it still does not extract the .asar files correctly, and will throw it's own error. Since the .asar is still missing, the app is still useless after the "update"
Thanks to your link to electron-basic-updater, I have found this issue mentioned there: https://github.com/TamkeenLMS/electron-basic-updater/issues/4.
They refer to the issue in the electron app: https://github.com/electron/electron/issues/9304.
Finally, in the end of the second topic there's a solution:
This is due to the electron fs module treating asar files as directories rather than files. To make the unzip process work you need to do one of two things:
Set process.noAsar = true
Use original-fs instead of fs
I have seen the people working with original-fs. But it looked like a big trouble to me.
So I tried setting process.noAsar = true (and then process.noAsar = false after unzipping) - and that worked like a charm.

How to determine function parameters in Javascript?

I am a Java developer learning Javascript (Node.js).
This is the first piece of code I tried running :
var sys = require("sys"),
my_http = require("http");
my_http.createServer(function(request,response){
response.writeHeader(200, {"Content-Type": "text/plain"});
response.write("Hello World");
response.end();
}).listen(8080);
IF there was no documentation, how would have I known that createServer takes a function which takes request and response as parameter ? I am asking this because I want to prepare myself for all the undocumented code I will start facing soon. Here is the source for createServer function :
function createServer(options) {
var bunyan = require('./bunyan_helper');
var InternalError = require('./errors').InternalError;
var Router = require('./router');
var Server = require('./server');
var opts = shallowCopy(options || {});
var server;
opts.name = opts.name || 'restify';
opts.log = opts.log || bunyan.createLogger(opts.name);
opts.router = opts.router || new Router(opts);
server = new Server(opts);
server.on('uncaughtException', function (req, res, route, e) {
if (this.listeners('uncaughtException').length > 1 ||
res._headerSent) {
return (false);
}
res.send(new InternalError(e, e.message || 'unexpected error'));
return (true);
});
return (server);
}
I understand Javascript is a dynamically typed language, but wondering how do people debug or understand each other's code without knowing types.
Well the nice thing about javascript is it's interpreted meaning you always have access to the actual source code itself. For node, you can look in node_modules/blah to read the source, but the vast majority of what is on npm is also open source on github and you can read the source there, too.
In the browser the developer tools has an auto-format button if you encounter minified code, but in node usually you don't need that as code is published unminified.
That said, some things are documented well, sometimes documentation is wrong or out of date, and sometimes reading the source code is neither quick nor straightforward. But if something is really problematic for you and is both undocumented and hard to read, you can and should switch to something else on npm because "ain't nobody got time for that".
you must be very familiar with the api when using JavaScript.for example, document.getElementById(id). There is no hint in what the id is in the code,but it is well understood.

Categories