Starting the ClojureScript browser REPL - browser

I'm trying to start a ClojureScript REPL in a browser. Ideally I'd like not to use Austin yet: I first want to get the simplest REPL possible working.
I tried following various tutorials and so far I didn't manage to make it work. Basically I don't understand what people mean when they say: "Start the ClojureScript browser REPL".
So far I did:
lein new mies hellow
And:
lein cljsbuild auto hellow
And here's my core.js file:
(ns hellow.core
(:require [clojure.browser.repl :as repl]))
(enable-console-print!)
(println "Hello world!")
(. js/console (log "Hello again"))
(repl/connect "http://localhost:9000/repl")
(. js/console (log "Ah, this prints too"))
When I open my index.html (which calls core.js), I can see in Chrome's developer tools's JavaScript console that everything is correctly logged.
However the (repl/connect ...) obviously fails. Here's what Chrome's developer tools shows;
Failed to load resource http://localhost:9000/repl?xpc=%7B%22cn%22%...
In nearly every forum post / blog entry / tutorial about ClojureScript I read about that subject, I stumble upon a line saying: "Start the browser REPL" or something similar.
How do I start the browser REPL? Is this something that must be done before loading index.html from the browser?
Can I start this browser REPL from Emacs?
How can I test that the browser REPL is working without loading index.html / core.js?
How can I then verify, after index.html / core.js is loaded in the browser, that the (repl/connect ...) inside core.js did work and is actually connected to the REPL?

The simplest and most basic way to start the repl server (you are already including the client code) is doing
$ lein trampoline cljsbuild repl-listen
Running ClojureScript REPL, listening on port 9000.
To quit, type: :cljs/quit
ClojureScript:cljs.user>
At that point, if you try to eval any expression like (+ 1 2) for example, you will see the repl hangs, because it has no environments to eval.
That's when you go to your index.html (remember to serve it from a web server, or the connection will fail, don't use the file:/// urls) and open it on a browser.
The connection to http://localhost:9000/repl?xpc=... should work just fine, and the repl should unblock and print 3. From then on, any commands will be executed in the browser environment.
I like to try (js/alert "hi") to see if the repl is connected, if it works it will alert hi in the browser window.
Remember that the browser window is your execution environment, so if you refresh it, you will lose the runtime values and they won't be accessible from the repl if you don't define them again.
With cljsbuild there is also: (lein cljsbuild help)
repl-listen
Run a REPL that will listen for incoming connections. (the one I used above)
repl-launch
Run a REPL and launch a custom command to connect to it.
repl-rhino
Run a Rhino-based REPL (JVM based JS execution environment, no browser needed).
Also, for the barebones repl, it is useful to use it with rlwrap to get readline shortcuts (Ctrl+a, etc) and repl history among other things:
$ rlwrap lein trampoline cljsbuild repl-listen
I hope all this helps.

Related

Access Electron API from a completely different system process

I am looking for a way to capture a screenshot of a VS Code extension host window. This window is opened when my extension's tests are being run (this is coming from the default Yeoman template for VS Code extensions).
I cannot use my extension's context as the extension only has access to the VS Code API and VS Code runs extensions in a different Node process from the Electron one (main or renderer). IPC is used through the API instead of running extensions in-process.
I can run this code in an Electron renderer process (using DevTools or as a part of the Electron application's script) to capture the Electron window:
const electron = require('electron');
electron.remote.getCurrentWindow().capturePage(image => {
//electron.clipboard.writeImage(image);
electron.clipboard.writeText(image.toDataURL());
console.log('Data URL is in clipboard.');
});
I have verified that placing this in VS Code window DevTools will produce the correct Data URI.
In order to be able to do this from a different Node process, knowing only the Code window PID, I figured I would attach a debugger to the VS Code extension host Electron window and using CDP I would issue a Runtime.evaluate call to run the above code as if it was entered into the DevTools.
However, I am struggling with attaching the debugger. There are generally two ways to do it:
kill -s SIGUSR1 <node-pid> for Unix/macOS
process._debugProcess(proc.pid); for Windows
I am interested in Windows right now, so I issue the Windows line from a new Node process. What should happen upon successful debugger attachment is the target process should print out something like this:
Debugger listening on ws://127.0.0.1:9229/cf49bcfe-d922-4f89-b438-57755d254198
For help see https://nodejs.org/en/docs/inspector
However in my case, this only works if I start the barebones Electron app with --inspect and then issue process._debugProcess(proc.pid);, without --inspect it doesn't throw an error, but doesn't attach the debugger either.
process._debugProcess now works for me with Electron 5.

Using command line arguments with ReactJS

I'm wondering if it's possible to use command line arguments with ReactJS (not react-native). For example, is it possible to input a simple string and have it be saved as a variable so it can be displayed? The npm yargs module is the kind of thing I'm looking for, but I couldn't get that to work because the child process it spawns apparently doesn't work in a browser.
Edit: I've also tried something like including {process.argv[0]} in say an h1 tag, but nothing shows up.
React doesn't have anything special for command line arguments. In fact, it is primarily designed as a DOM library. You could use yargs and then pass the values to a React component.
For example you run this command in terminal or cmd
npm start -- foo
foo is your argument.
You can print your like this
// print process.argv
process.argv.forEach(function (val, index, array) {
console.log(index + ': ' + val);
});
in your script.
React runs is client-side
React is a client-side library. It runs in a web page, on a browser. The end-user doesn't use the command-line to "run" React, therefore command-line arguments are not available to the end-user.
For developers
As a developer, you do use tools to start a development server and launch a browser that is running React. Most likely, you're using Create React App. You can use environment variables to pass variables/arguments to React. Specifically, the documentation offers these examples:
# on Linux and macOS
REACT_APP_NOT_SECRET_CODE=abcdef npm start
# on Windows (cmd.exe)
set "REACT_APP_NOT_SECRET_CODE=abcdef" && npm start
Note that these variables are embedded into React at build time, when Create React App bundles and builds your app (kind of like compiling). This means that if you build your React project and then transfer the output files to another server and try to pass new variables, nothing will change.
For servers
If your React build files are on a server and you want to be able to pass command-line arguments to the server and have React change, this is also possible, but largely depends on what software you are using to serve. Broadly, the server would take the runtime argument and pass it into the template which renders your React app. Then any Javascript that runs on that page can access the arguments.

How to inject script using node.js code?

You all know open npm package: https://www.npmjs.com/package/open
Using this package, one can write the following code:
var open = require('./node_modules/open/lib/open.js')
open('http://www.cnn.com')
and activating it by:
$ node app.js
will open a browser window of cnn.com.
I want my script to open this site and inject some code to the console. I mean that the browser will behave like I clicked F12, went to 'console' tab and typed in console the code:
alert('Hello World')
Do you know how to do it?
The open module is used to "Open a file or url in the user's preferred application."
It can open the preferred application (a browser in this case) but it cannot control it. In fact, it doesn't even know what browser will that be (or even if that will be a browser).
What you are asking for can be achieved with tools like PhantomJS ("PhantomJS is a headless WebKit scriptable with a JavaScript API."), Nightmare.js ("A high-level browser automation library.") or CasperJS ("Navigation scripting & testing for PhantomJS and SlimerJS"), see:
http://phantomjs.org/
http://www.nightmarejs.org/
http://casperjs.org/

How to disable the debug remote port in node-webkit desktop app

I wan't to protect the code of my node-webkit desktop application packaged in an exe file.
The problem is not on the file directly but with the dedicated port for remote debugging.
Perhaps I haven't understood something but, on Windows, if I execute a "netstat -a -o" command, I see an open port associated to the application and if I open this port on my browser, I have a page with "Inspectable WebContents" and a link to the webkit application.
With this debug window, it's possible to access to all the sources of the app and I don't know how to disable this feature.
For now, I think there is no actual way to disable remote debugging in nw.js.
Even so, according to the wiki, remote debugging seems to only be executed through the command line switches. Therefore you can block the chromium command line switches (or only --remote-debugging-port) to prevent arbitrary remote debugging by user until nw.js supports disabling functionality of remote debugging.
For instance:
const gui = require('nw.gui');
const app = gui.App;
for (let element of app.fullArgv) {
// app.argv has only user's switches except for the chromium args
if (app.argv.indexOf(element) < 0) {
app.quit(1); // invalid args!
}
}
However, I am not quite sure the above code could protect your application code, because the nw.js is using Chromium internally. So that, the application code would be extracted in temporary folder on initialization. Whereas above solution isn't really protect your nw.js application. See more details: https://github.com/nwjs/nw.js/issues/269
Note: node-webkit has changed name to nw.js

Output to Chrome console from Node.js

I'm looking for a way to output Node variables directly into the google chrome browser console. The same way a console.log() works on the client side. Something like this for php. This would greatly speed up development.
NOTE:
Since the old answer (written in september 2014) refers to an older version of node-inspector, my instructions are not relevant anymore in 2017. Also, the documentation has gotten a lot better, so I have updated my original answer:
node-inspector is what you need.
It opens up an instance of Chrome with its developer tools for debugging.
It's also easy to use:
1. Install
$ npm install -g node-inspector
2. Start
$ node-debug app.js
Source: https://github.com/node-inspector/node-inspector
You might want to try NodeMonkey - https://github.com/jwarkentin/node-monkey
I know it's an old question but came on top of my Google search so maybe somebody will find my answer useful.
So you can use node --inspect-brk index.js
Now, all you have to do is basically just type chrome://inspect in your Chrome address bar and click Open dedicated DevTools for Node
In DevTools, now connected to Node, you’ll have all the Chrome DevTools features you’re used to:
Complete breakpoint debugging, stepping w/ blackboxing
Source maps for transpiled code
LiveEdit: JavaScript hot-swap evaluation w/ V8
Console evaluation with ES6 feature/object support and custom object formatting
Sampling JavaScript profiler w/ flamechart
Heap snapshot inspection, heap allocation timeline, allocation profiling
Asynchronous stacks for native promises
Hope that helped.
The closest thing to this I've seen is Node JS console object debug inspector
See this post for usage and potential issues: http://thomashunter.name/blog/nodejs-console-object-debug-inspector/
For users with nodejs on linux via ssh-shell (putty):
Problem with nodejs on linux-ssh-shell is, that you have no browser connected.
I tried all this solutions, but didnt get it to work.
So i worked out a solution with firebase (https://firebase.google.com), because my project uses firebase.
If you are familiar with firebase, than this is a great way. If not, firebase is worth using in combination with nodejs - and its free!
In the server-side-script (started with node) use a own function log():
// server-side:
// using new firebase v3 !
var fbRootRef = firebase.database();
var fbConsoleRef = fbRootRef.ref("/console");
var log = function(args) {
fbConsoleRef.set({'obj': args});
}
// inside your server-code:
log({'key':'value'});
On client-side you create a firebase-reference on this console-object:
// client side:
fbRootRef.child('/console').on('value', function(d) {
var v = d.val();
console.log(v);
});
Now everything logged on server-side with the log() - function is transferred in realtime to the firebase-database and from there triggering the client-console-reference and logged into the browsers console.
If anyone needs help, i will explain in more detail and could give a more extended version of this logging with types (console./log/warn/info), grouping with title-info (i.e. server says: (filename + line).
Setting up firebase for your project is done in max 30 minutes, inserting the console-function in 30 minutes. I think its worth the time!
You can use bonsole, a simple way to log something in browser. Even in Linux, you can go to the LAN's ip to check it.
The most simple way with least dependencies is using a WebSocket connection to send the messages to the browser. Any WebSocket example you can find on the internet will suffice to accomplish this. Everything else requires to be heavily integrated into the host system and wouldn't work if you want to actually run this on a remote server. You can also send commands to the server directly from the browser console this way.
Links:
https://www.npmjs.com/package/websocket
https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_client_applications

Resources