Providing stdin to an emscripten HTML program? - javascript

I have a C program that takes one argument (a char array / string) via command line and also reads from stdin. I've compiled it to JavaScript using emscripten. This was successful and I can run it just like the normal C program using node.js:
emcc -O2 translate.c
node translate.js "foo" < bar.txt
As you can see, I'm providing the string "foo" as an argument and the contents of bar.txt as stdin. Now I want this to be a self-contained HTML file.
By changing the output to HTML:
emcc -O2 translate.c -o trans.html
I provide the argument by adding arguments: ['foo'], to the definitions in var Module. This works as expected, the program receives the argument correctly.
Now, how do I provide the stdin input to this program? I don't need to do this dynamically. It would be fine to just declare a string somewhere in the HTML with the required stdin content.

A way would be to use the Emscripten Filesystem API, for example by calling FS.init in the Module preRun function, passing custom functions to be used for standard input, output and error.
var Module = {
preRun: function() {
function stdin() {
// Return ASCII code of character, or null if no input
}
function stdout(asciiCode) {
// Do something with the asciiCode
}
function stderr(asciiCode) {
// Do something with the asciiCode
}
FS.init(stdin, stdout, stderr);
}
};
The functions are quite low-level: they each deal with one character at a time as an ASCII code. If you have strings you want to pass in, you would have to iterate over the characters of the string yourself. I suspect charCodeAt would be helpful. To output strings from stdout or stderr, then I suspect fromCharCode would be helpful.
Example (not very well tested!) implementations using each are below.
var input = "This is from the standard input\n";
var i = 0;
var Module = {
preRun: function() {
function stdin() {
if (i < res.length) {
var code = input.charCodeAt(i);
++i;
return code;
} else {
return null;
}
}
var stdoutBuffer = "";
function stdout(code) {
if (code === "\n".charCodeAt(0) && stdoutBuffer !== "") {
console.log(stdoutBuffer);
stdoutBuffer = "";
} else {
stdoutBuffer += String.fromCharCode(code);
}
}
var stderrBuffer = "";
function stderr(code) {
if (code === "\n".charCodeAt(0) && stderrBuffer !== "") {
console.log(stderrBuffer);
stderrBuffer = "";
} else {
stderrBuffer += String.fromCharCode(code);
}
}
FS.init(stdin, stdout, stderr);
}
};

Rather than editing the output of Emscripten, you could monkey patch the Window object
window.prompt = function() {
return 'This will appear to come from standard input';
};
Not wonderful, but I would deem this less of a hack than editing the Emscripten-generated Javascript.

According the question "Edit" , I made my function , thx a lot.
Just hope the code below can help someone else.
comment run(); in the end of emscript
// in my emscript
// shouldRunNow refers to calling main(), not run().
var shouldRunNow = true;
if (Module['noInitialRun']) {
shouldRunNow = false;
}
//run(); // << here
// {{POST_RUN_ADDITIONS}}
result = areaInput(); // As the question mentioned
add the code below in your html file to activate run() in emscript
<script>
var message;
var point = -1;
function getArea(){
message = document.getElementById('input').value.split('\n');
}
function areaInput(){
if(point >= message.length - 1){
return null;
}
point += 1;
return message[point];
}
function execEmscript(){
window.console = {
log: function(str){
document.getElementById("output").value += "\n" + str;
}
}
getArea();
run();
}
</script>
remember io textareas in your html
<textarea id="input" cols="80" rows="30"></textarea>
<textarea id="output" cols="80" rows="30"></textarea>
and a button
<button onclick="execEmscript();">run</button>

Related

Console.log not working when testing regex

Can someone explain why my console log is not working?
Every time I select the file for verification to see if anything shows in the console nothing happens
document.addEventListener("DOMContentLoaded", function() {
document.getElementById('file').onchange = function() {
var extPermitidas = ['txt'];
var extArquivo = this.value.split('.').pop();
if (typeof extPermitidas.find(function(ext) {
return extArquivo == ext;
}) == 'undefined') {
alert('The file cannot be used because its extension is not allowed!');
return;
} else {
var file = this.files[0];
var reader = new FileReader();
reader.onload = function(progressEvent) {
// By lines
var lines = this.result.split('\n');
let N = /^(N1\d{14}.{78}|N9\d{14}.{14}\d{6})$/;
for (var line = 0; line < lines.length; line++) {
if (N.test(lines[line]) == N) {
console.log("valid file");
} else {
console.log("invalid file");
}
}
};
reader.readAsText(file);
}
alert('file successfully validated!');
}
});
<input type="file" id="file" />
EDIT
Could it be a problem in the conditional if (N.test(lines[line]) == N)?
This appears to be a function context issue. Try changing var file = this.files[0]; to var file = document.getElementById("file").files[0];.
this can sometimes be tricky since its value is determined by how a function is called (runtime binding). See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this
Edit:
The conditional if (N.test(lines[line]) == N) is strange. The test() method executes a search for a match between a regular expression and a specified string and returns true or false. So, you don't need to compare the return of test to == N. Plus, you almost always want to use triple equals (===).
Have you already check your conditions or try to place the console.log in various parts of your code? Maybe it's an issue with event firing. I've tried to run you regex with my console I guess it works smoothly.
regex result

How to read a Javascript file

I have a file a /path/to/my_js_functions.js that contains a Javascript function my_js_functions(), amongst other functions.
How can I go about reading the function myJsFunction as a String in C++?
I am looking for a way to get the whole function and only that function, and then contain it in a char *jsFunction.
function myJsFunction(stringParam) {
return stringParam // The function returns a stringParam from the parameter
}
function anotherJsFunction(stringParam) {
return stringParam // Another function
}
Thank you all in advance.
Using fstream, I would read line by line and check whether each line contains the sequence myJsFunction. If a line does contain this sequence, then you begin aggregating to a string until you reach the next function (stopping after you reach the next keyword "function" or something of that sort). Note that using } as a keyword may not work as functions are likely to have multiple closing braces.
Another possible solution could include identifying the end of the function by noticing that when a newline is immediately followed by non-whitespace a new function is beginning, assuming the code in your file is formatted where anything lower in scope is tabbed over correctly.
To do this you need to read your javascript code file and parse it. It is highly to use some parser library to do that like cashew,esprima-cpp. I never used that before I never used any of this before, So I can't comment on that.
But here is some quick code for parser. You can start with this build on this to make it more robust.
main.cpp
#include <fstream>
#include <iostream>
#include <streambuf>
#include <string>
#include <vector>
std::string getFunction(const std::string &fileData, const std::string &name) {
std::string ret;
std::size_t start = 0;
while (true) {
const auto fNameStart = fileData.find(name, start);
if (fNameStart != std::string::npos) {
auto fStart = fileData.find_last_not_of(" ",fNameStart-1);
if(fStart == std::string::npos){
ret = "No Function Defination";
break;
}
else {
fStart = fStart-7;
if(fileData.substr(fStart,8) == "function"){
int openBraceCount = 0, closeBraceCount = 0;
std::size_t fEnd = fNameStart + name.size();
fEnd = fileData.find_first_of("{}", fEnd);
while (fEnd != std::string::npos) {
if (fileData.at(fEnd) == '{') {
openBraceCount++;
} else {
closeBraceCount++;
}
if (openBraceCount == closeBraceCount) {
ret = fileData.substr(fStart, fEnd - fStart+1);
break;
}
fEnd++;
fEnd = fileData.find_first_of("{}", fEnd);
}
if(!ret.empty()){
break;
}
else if(openBraceCount != closeBraceCount){
ret = "Function Parse Error";
break;
}
}
else{
start = fNameStart + name.size();
}
}
} else {
ret = "No Function Defination";
break;
}
}
return ret;
}
int main(int argc, char **argv) {
const std::string jsPath = "module.js";
const std::vector<std::string> vecFuncNames{"funcA", "funcB", "funcC",
"funcD", "funcE"};
std::ifstream fs(jsPath);
if (fs.is_open()) {
std::string fileData((std::istreambuf_iterator<char>(fs)),
std::istreambuf_iterator<char>());
for (auto &name : vecFuncNames) {
std::cout << name << "\n" << getFunction(fileData, name) << std::endl;
}
}
return 0;
}
module.js
function funcA ( ){
funcC(); console.log(" Hello");funcB();
}function funcC(){funcB();console.log("Hello");funcA();}
function funcB(a, b, c){
funcA(); setTimeout(function(){ alert("Hello"); }, 3000);funcC();
}
funcD();
function funcE(){{{{}}}
You can simply doing this
For example /path/code.js is the path your code stored
Your code.js
function myJsFunction(stringParam) {
return stringParam // The function returns a stringParam from the parameter
}
function anotherJsFunction(stringParam) {
return stringParam // Another function
}
module.exports = {
myJsFunction,
anotherJsFunction
}
And this is the file that you use to read the function you write
index.js
const code = require('/path/code.js');
console.log(code), it will be showing your whole code in your code.js file
If you want to make it string, you can use syntax like this. Add this in code below on your index.js file and it will make string version of your code.
String(code.myJsFunction)

node.js wait for a callback/response if i use process.send()

I got a main process and this fork a child. This child do some calculations. At some point of the code in the child I want to ask the parent for some data. This request is highly dynamic and at this point i want to wait for a answer/response of this request. But how do I wait for process.send() or is it possible to add a Callback function to .send()?
I tried to break down my Problem to a simple example.
The highly dynamic value is in my example the randomval in the worker.
And i know that the assignment
var c = process.send({msg:'get_c',randomval:Math.floor((Math.random()*10)+1)});
can't work. But i no other idea how to describe the Problem.
main.js
var childProcessCalc = require('child_process').fork(__dirname + '/worker');
childProcessCalc.send({msgtype:'docalc'});
childProcessCalc.on('message',function(msg){
if(msg.msg === 'pi')
{
console.log("Pi"+msg.pi+" by c="+msg.c);
}
else if(msg.msg === 'get_c')
{
console.log('child wants c');
childProcessCalc.send({msgtype:'your_c',c:1000000*msg.randomval});
}
});
childProcessCalc.on('exit',function(){
console.log('main:the childProzess has exit!')
});
worker.js
process.on('message', function(msg){
if(msg.msgtype == 'docalc') {
//Here is my Problem, how to wait for the message thats the response for
//exactly this send / randomval, or how to add a callback to send
var c = process.send({msg:'get_c',randomval:Math.floor((Math.random()*10)+1)});
var Pi=0;
var n=1;
for (var i=0;i<=c;i++)
{
Pi=Pi+(4/n)-(4/(n+2))
n=n+4
}
process.send({msg:'pi',pi:Pi,c:c})
}
else if(msg.msgtype === 'your_c')
{
console.log('parent hase sendc='+msg.c);
}
});
I have a solution to my problem and it works well for me, but because im very new at nodejs i still not now if this is the best way. Its feel like a overhead.
In a few words what i have done:
I added a object that stores a random callback identifier with the callback function that has to be called if we got a response for the given callback identifier.
When i now call send() from worker i send the identifier to the main process and the main process send this identifier back when he has finished. So i can lookup in my callback var (dynamicMassages ) for the callbackfnc to call and execute it.
main2.js
var childProcessCalc = require('child_process').fork(__dirname + '/worker2');
childProcessCalc.send({msgtype:'docalc'});
childProcessCalc.send({msgtype:'docalc'});
childProcessCalc.on('message',function(msg){
if(msg.msg === 'pi')
{
console.log("Pi"+msg.pi+" by c="+msg.c);
}
else if(msg.msg === 'get_c')
{
console.log('child wants c');
childProcessCalc.send({msgtype:'your_c',callbackid:msg.callbackid, c:1000000*msg.randomval});
}
});
childProcessCalc.on('exit',function(){
console.log('main:the childProzess has exit!')
});
worker2.js
var dynamicMassages = {};
process.on('message', function(msg){
var getRandomId = function(){
var text = "";
var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
for( var i=0; i < 5; i++ )
{
text += possible.charAt(Math.floor(Math.random() * possible.length));
}
if(dynamicMassages[text] === undefined)
{
return text;
}
else
{
return getRandomId();
}
};
if(msg.msgtype == 'docalc') {
var randomId = getRandomId();
var callbackFnc = function(c){
var Pi=0;
var n=1;
for (var i=0;i<=c;i++)
{
Pi=Pi+(4/n)-(4/(n+2))
n=n+4
}
console.log("callbackFnc For:"+randomId);
process.send({msg:'pi',pi:Pi,c:c})
delete dynamicMassages[randomId];
};
dynamicMassages[randomId] = callbackFnc;//callbackFnc;
process.send({msg:'get_c',callbackid: randomId, randomval:Math.floor((Math.random()*10)+1)});
}
else if(msg.msgtype === 'your_c')
{
console.log('parent hase sendc='+msg.c+' for callbackId '+msg.callbackid);
if(msg.callbackid !== undefined)
{
dynamicMassages[msg.callbackid](msg.c);
}
}
});
Please leave a comment if you would to it the same way.
I'd suggest that you go with a message bus, either a full-blown advanced solution such as RabbitMQ, or a little smaller solution, such as axon.
Basically, what you want to do is inter-process communication, and I'd try to stick to established protocols and standards as much as possible, and avoid rolling your very own solution. As RabbitMQ builds on top of AMQP, I guess you can call it standard.

Uglify JS - compressing unused variables

Uglify has a "compression" option that can remove unused variables...
However, if I stored some functions in an object like this....
helpers = {
doSomething: function () { ... },
doSomethingElese: function () { ... }
}
... is there a way to remove helpers.doSomething() if it's never accessed?
Guess I want to give the compressor permission to change my object.
Any ideas if it's possible? Or any other tools that can help?
Using a static analyzer like Uglify2 or Esprima to accomplish this task is somewhat nontrivial, because there are lots of situations that will call a function that are difficult to determine. To show the complexity, there's this website:
http://sevinf.github.io/blog/2012/09/29/esprima-tutorial/
Which attempts to at least identify unused functions. However the code as provided on that website will not work against your example because it is looking for FunctionDeclarations and not FunctionExpressions. It is also looking for CallExpression's as Identifiers while ignoring CallExpression's that are MemberExpression's as your example uses. There's also a problem of scope there, it doesn't take into account functions in different scopes with the same name - perfectly legal Javascript, but you lose fidelity using that code as it'll miss some unused functions thinking they were called when they were not.
To handle the scope problem, you might be able to employ ESTR (https://github.com/clausreinke/estr), to help figure out the scope of the variables and from there the unused functions. Then you'll need to use something like escodegen to remove the unused functions.
As a starting point for you I've adapted the code on that website to work for your very specific situation provided, but be forwarned, it will have scope issue.
This is written for Node.js, so you'll need to get esprima with npm to use the example as provided, and of course execute it with node.
var fs = require('fs');
var esprima = require('esprima');
if (process.argv.length < 3) {
console.log('Usage: node ' + process.argv[1] + ' <filename>');
process.exit(1);
}
notifydeadcode = function(data){
function traverse(node, func) {
func(node);
for (var key in node) {
if (node.hasOwnProperty(key)) {
var child = node[key];
if (typeof child === 'object' && child !== null) {
if (Array.isArray(child)) {
child.forEach(function(node) {
traverse(node, func);
});
} else {
traverse(child, func);
}
}
}
}
}
function analyzeCode(code) {
var ast = esprima.parse(code);
var functionsStats = {};
var addStatsEntry = function(funcName) {
if (!functionsStats[funcName]) {
functionsStats[funcName] = {calls: 0, declarations:0};
}
};
var pnode = null;
traverse(ast, function(node) {
if (node.type === 'FunctionExpression') {
if(pnode.type == 'Identifier'){
var expr = pnode.name;
addStatsEntry(expr);
functionsStats[expr].declarations++;
}
} else if (node.type === 'FunctionDeclaration') {
addStatsEntry(node.id.name);
functionsStats[node.id.name].declarations++;
} else if (node.type === 'CallExpression' && node.callee.type === 'Identifier') {
addStatsEntry(node.callee.name);
functionsStats[node.callee.name].calls++;
}else if (node.type === 'CallExpression' && node.callee.type === 'MemberExpression'){
var lexpr = node.callee.property.name;
addStatsEntry(lexpr);
functionsStats[lexpr].calls++;
}
pnode = node;
});
processResults(functionsStats);
}
function processResults(results) {
//console.log(JSON.stringify(results));
for (var name in results) {
if (results.hasOwnProperty(name)) {
var stats = results[name];
if (stats.declarations === 0) {
console.log('Function', name, 'undeclared');
} else if (stats.declarations > 1) {
console.log('Function', name, 'decalred multiple times');
} else if (stats.calls === 0) {
console.log('Function', name, 'declared but not called');
}
}
}
}
analyzeCode(data);
}
// Read the file and print its contents.
var filename = process.argv[2];
fs.readFile(filename, 'utf8', function(err, data) {
if (err) throw err;
console.log('OK: ' + filename);
notifydeadcode(data);
});
So if you plop that in a file like deadfunc.js and then call it like so:
node deadfunc.js test.js
where test.js contains:
helpers = {
doSomething:function(){ },
doSomethingElse:function(){ }
};
helpers.doSomethingElse();
You will get the output:
OK: test.js
Function doSomething declared but not called
One last thing to note: attempting to find unused variables and functions might be a rabbit hole because you have situations like eval and Functions created from strings. You also have to think about apply and call etc, etc. Which is why, I assume, we don't have this capability in the static analyzers today.

Windows Scripting to call other commands?

I was trying my hand at Windows shell scripting using cscript and Javascript. The idea was to take a really long Python command that I was tired of typing into the command line over and over. What I wanted to do was write a script that is much shorter to write the whole Python command into a Windows script and just call the Windows script, which would be a lot less to type. I just don't know how I would go about calling a "command within a command" if that makes sense.
This is probably an easy thing, but I'm an newbie at this so please bear with me!
The idea:
Example original command: python do <something really complicated with a long filepath>
Windows Script: cscript easycommand
<package id = "easycommand">
<job id = "main" >
<script type="text/javascript">
// WHAT GOES HERE TO CALL python do <something really complicated>
WScript.Echo("Success!");
</script>
</job>
</package>
Thanks for all your help!
Here's what I use
function logMessage(msg) {
if (typeof wantLogging != "undefined" && wantLogging) {
WScript.Echo(msg);
}
}
// http://msdn.microsoft.com/en-us/library/d5fk67ky(VS.85).aspx
var windowStyle = {
hidden : 0,
minimized : 1,
maximized : 2
};
// http://msdn.microsoft.com/en-us/library/a72y2t1c(v=VS.85).aspx
var specialFolders = {
windowsFolder : 0,
systemFolder : 1,
temporaryFolder : 2
};
function runShellCmd(command, deleteOutput) {
deleteOutput = deleteOutput || false;
logMessage("RunAppCmd("+command+") ENTER");
var shell = new ActiveXObject("WScript.Shell"),
fso = new ActiveXObject("Scripting.FileSystemObject"),
tmpdir = fso.GetSpecialFolder(specialFolders.temporaryFolder),
tmpFileName = fso.BuildPath(tmpdir, fso.GetTempName()),
rc;
logMessage("shell.Run("+command+")");
// use cmd.exe to redirect the output
rc = shell.Run("%comspec% /c " + command + "> " + tmpFileName,
windowStyle.Hidden, true);
logMessage("shell.Run rc = " + rc);
if (deleteOutput) {
fso.DeleteFile(tmpFileName);
}
return {
rc : rc,
outputfile : (deleteOutput) ? null : tmpFileName
};
}
Here's an example of how to use the above to list the Sites defined in IIS with Appcmd.exe:
var
fso = new ActiveXObject("Scripting.FileSystemObject"),
windir = fso.GetSpecialFolder(specialFolders.WindowsFolder),
r = runShellCmd("%windir%\\system32\\inetsrv\\appcmd.exe list sites");
if (r.rc !== 0) {
// 0x80004005 == E_FAIL
throw {error: "ApplicationException",
message: "shell.run returned nonzero rc ("+r.rc+")",
code: 0x80004005};
}
// results are in r.outputfile
var
textStream = fso.OpenTextFile(r.outputfile, OpenMode.ForReading),
sites = [], item,
re = new RegExp('^SITE "([^"]+)" \\((.+)\\) *$'),
parseOneLine = function(oneLine) {
// each line is like this: APP "kjsksj" (dkjsdkjd)
var tokens = re.exec(oneLine), parts;
if (tokens === null) {
return null;
}
// return the object describing the website
return {
name : tokens[1]
};
};
// Read from the file and parse the results.
while (!textStream.AtEndOfStream) {
item = parseOneLine(textStream.ReadLine()); // you create this...
logMessage(" site: " + item.name);
sites.push(item);
}
textStream.Close();
fso.DeleteFile(r.outputfile);
Well, basically:
Obtain a handle to the shell so you can execute your script
Create the command you want to execute (parameters and all) as a string
Call the Run method on the shell handle, and figure out which window mode you want and also whether you want to wait until the spawned process finishes (probably) or not.
Error handling because Run throws exceptions
At this point it's worth writing a lot of utility functions if ever you need to do it more than once:
// run a command, call: run('C:\Python27\python.exe', 'path/to/script.py', 'arg1', 'arg2') etc.
function run() {
try {
var cmd = "\"" + arguments[0] + "\"";
var arg;
for(var i=1; i< arguments.length; ++i) {
arg = "" + arguments[i];
if(arg.length > 0) {
cmd += arg.charAt(0) == "/" ? (" " + arg) : (" \"" + arg + "\"");
}
}
return getShell().Run(cmd, 1, true); // show window, wait until done
}
catch(oops) {
WScript.Echo("Error: unable to execute shell command:\n"+cmd+
"\nInside directory:\n" + pwd()+
"\nReason:\n"+err_message(oops)+
"\nThis script will exit.");
exit(121);
}
}
// utility which makes an attempt at retrieving error messages from JScript exceptions
function err_message(err_object) {
if(typeof(err_object.message) != 'undefined') {
return err_object.message;
}
if(typeof(err_object.description) != 'undefined') {
return err_object.description;
}
return err_object.name;
}
// don't create new Shell objects each time you call run()
function getShell() {
var sh = WScript.CreateObject("WScript.Shell");
getShell = function() {
return sh;
};
return getShell();
}
For your use case this may be sufficient, but you might want to extend this with routines to change working directory and so on.

Categories

Resources