laurentj/slimerjs

Reading and accepting input from user during execution

kensoh opened this issue · 7 comments

versions

  • SlimerJS: v0.10.3
  • Firefox: v54.0.1 (64-bit)
  • Operating system: macOS (10.12.6 (16G29))

Steps to reproduce the issue

Run a bare-minimum script to read input using sys.stdin.read() from SlimerJS doc

var casper = require('casper').create();
casper.start('http://casperjs.org/');

casper.then(function() {
    this.echo(this.getTitle());
    var input = ''; var sys = require('system');
    sys.stdout.write('ENTER INPUT: ');
    input = sys.stdin.read();
    this.echo(input);
});

casper.run();

Actual results:

Entered something but nothing happens, if nothing is entered script also exits

Expected results:

The input is read correctly and able to be used later on (echo, used as selector etc)

Additional details:

Posted this 2 months ago to a related SlimerJS issue. But it is a closed issue, so I thought to repost here as a new issue. #188 I'm not sure if other users are facing this and not sure if I used the method in the wrong way that's why it's not working. When run with PhantomJS it is ok using sys.stdin.readLine().

UPDATE - forgot to paste the error message received (same as the error I posted in issue 188). This error happens whether I enter something or do nothing and wait for a few seconds for it to appear.

JavaScript error: resource://slimerjs/addon-sdk/toolkit/loader.js -> resource://slimerjs/addon-sdk/sdk/io/byte-streams.js, line 73: Error: Error reading from stream: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsIBinaryInputStream.readBytes]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: resource://slimerjs/addon-sdk/toolkit/loader.js -> resource://slimerjs/addon-sdk/sdk/io/byte-streams.js :: ByteReader_read :: line 68"  data: no]
2017-08-05T18:46:51.182Z [DEBUG] webpage: close

sys.stdin is not to read user input (from the keyboard), but the content given to the program at startup, on the standard input flow.

Thanks Laurent for your reply! I understand now and appreciate your reply. Please be free to close the issue if there is a technical limitation on Gecko that can't support reading inputs live during run-time.

I don't think gecko supports reading live inputs. Even for reading input, we have to read directly /dev/stdin (so, no support on Windows).

And so I was wrong in my previous comment :-) sys.stdin reads what you send to slimerjs as startup (ex: cat somefile > slimerjs myscript.js), but in theory, it can read also any other input.

Probably a solution is to call input.read() a first time, to empty the buffer before echoing the question, and then call input.read() until you reach a "\n"?

There is however an issue: since SlimerJS open a window, the user has to put the focus on the terminal. But probably with the new headless feature of Firefox, it is not an issue :) (add the --headless option; you should use Firefox 55 or 56)

Thanks Laurent! Got it.. Sounds like it will not be a good idea to implement, because Windows users will experience inconsistency due to the Gecko design. I'll probably not have laptop access for couple of weeks, but will be sure to try out your suggestion when I do and update findings here :)

(adding some notes that execution didn't reach the sys.stdout.write, it could be something mess up when called from CasperJS. will try running a basic script on SlimerJS when I have laptop again)

var casper = require('casper').create();
casper.options.logLevel = 'debug';
casper.start('http://casperjs.org/');

casper.then(function() {
    this.echo(this.getTitle());
    var input = ''; var sys = require('system');
    input = sys.stdin.read();
    sys.stdout.write('ENTER INPUT: ');
    while (input.indexOf('\n') == -1) input = sys.stdin.read();
    this.echo(input);
});

casper.run();
TA:Desktop kensoh$ casperjs readtest.js --engine=slimerjs --verbose
[info] [phantom] Starting... 
[info] [phantom] Running suite: 3 steps 
[debug] [phantom] opening url: http://casperjs.org/, HTTP GET 
[debug] [phantom] Navigation requested: url=http://casperjs.org/, type=Undefined, willNavigate=true, isMainFrame=true 
[debug] [phantom] url changed to "http://casperjs.org/" 
[debug] [phantom] Successfully injected Casper client-side utilities 
[debug] [phantom] start page is loaded 
[info] [phantom] Step anonymous 3/3 http://casperjs.org/ (HTTP 200) 
CasperJS, a navigation scripting and testing utility for PhantomJS and SlimerJS 
[info] [phantom] Done 3 steps in 7306ms 

Hi Laurent, an update that I have tried it to replicate the behaviour.

Below is a minimal SlimerJS script that triggers the error message below.

var page = require("webpage").create();
page.open("http://slimerjs.org", function(status){
    var input = ''; var sys = require('system');
    input = sys.stdin.read();
    sys.stdout.write('ENTER INPUT: ');
    input = sys.stdin.read();
    sys.stdout.write('INPUT IS: ' + input + '\n');
    page.close();
    phantom.exit();
})

It looks like the flow control didn't make it past the first read() -

TA:Desktop kensoh$ slimerjs test.js

Script Error: Error reading from stream: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsIBinaryInputStream.readBytes]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: resource://slimerjs/addon-sdk/toolkit/loader.js -> resource://slimerjs/addon-sdk/sdk/io/byte-streams.js :: ByteReader_read :: line 68"  data: no]
       Stack:
         -> resource://slimerjs/addon-sdk/sdk/io/byte-streams.js: 73
         -> resource://slimerjs/addon-sdk/sdk/io/byte-streams.js: 73 (in function ByteReader_read)
         -> file:///Users/kensoh/Desktop/a.js: 4
         -> resource://slimerjs/slimer-sdk/webpage.js: 710 (in function _create/openUrl/<)
         -> resource://slimerjs/addon-sdk/sdk/core/promise.js: 55 (in function effort)
         -> resource://slimerjs/addon-sdk/sdk/core/promise.js: 117 (in function resolved)
         -> resource://slimerjs/addon-sdk/sdk/core/promise.js: 37 (in function then)
         -> resource://slimerjs/addon-sdk/sdk/core/promise.js: 143 (in function resolve)
         -> resource://slimerjs/slimer-sdk/webpage.js: 262 (in function onLoadFinished)
         -> resource://slimerjs/slimer-sdk/net-log.js: 1113 (in function run)

Hi

Using @kensoh last minimal SlimerJS script to replicate I'm able to enter input, though I must do it in ~300ms (linux & i3wm):

ENTER INPUT: xx
INPUT IS: xx

Can we somehow halt the script at this particular method or is there a workaround for user input interception (2-factor auth)?

Remark:
Here's an (incomplete) approach, serving/polling an input file: https://stackoverflow.com/questions/27005797/how-to-inject-external-input-into-a-slimerjs-script-dynamically