Open trusktr opened 5 years ago
Does a return value from a call to a function added with App.exposeFunction
get returned serialized, or by reference? :crossed_fingers:
Yeah, looks like it serializes. The following example results in an error.
example.js:
const carlo = require('carlo');
(async () => {
// Launch the browser.
const app = await carlo.launch();
// Terminate Node.js process on app window closing.
app.on('exit', () => process.exit());
// Tell carlo where your web files are located.
app.serveFolder(__dirname);
class Box {
constructor(x, y) {
this.x = x
this.y = y
}
getSize() {
return [this.x, this.y]
}
}
function makeBox(size) {
return new Box(size[0], size[1])
}
// Expose 'env' function in the web environment.
await app.exposeFunction('makeBox', makeBox);
// Navigate to the main page of your app.
await app.load('example.html');
})();
example.html
<script>
async function run() {
const box = await makeBox([10, 10])
console.log(box.getSize()) // ERROR
}
</script>
<body onload="run()">
Results in
Uncaught (in promise) TypeError: box.getSize is not a function
at run (example.html:4)
I suppose we'd have to re-implement modules like fs
on the browser side so they can send the data to/from with serialization if we go that path.
Is there another way? Seems like this is where Electron wins at the moment, and there's not much incentive to switch over just to save hard disk space from re-using Chrome binaries.
Ah, README says
Node v8 and Chrome v8 engines are decoupled in Carlo,
So obviously it's probably not possible to just pass references, if there's two engines running.
Maybe the opposite is a better idea: implement a DOM interface on the Node side that can proxy to DOM on the browser side? In either case, there will be gotchas and complications.
It'd be nice if somehow Chrome could use Node's v8. Is that possible?
You can use rpc to solve some of your problems.
@pavelfeldman Thanks, that looks like it! Interesting that it is possible to wrap reference across engines like that.
So how do we use it? Where do I get the rpc
module from? Where is example.html
? How do I get the rpc handle in the browser? Where's an example I can run?
Ah, I see
const [app, term] = await carlo.loadParams();
in the terminal
example's index.html
. Nice!
By the way, why is that Terminal example so slow (I mean moving around in vim is really slow, for example)? In Atom text editor terminals, it is much zippier (running in Electron).
Is it the xterm.js's UI rendering in particular, or is it the rpc communication?
Alright, gave it a try, but no luck:
example.js
const carlo = require('carlo')
const { rpc, rpc_process } = require('carlo/rpc')
const requireHandle = rpc.handle(require)
main()
async function main() {
// Launch the browser.
const app = await carlo.launch({
bgcolor: '#2b2e3b',
title: 'Require all the things',
width: 800,
height: 800,
})
app.on('exit', () => process.exit())
app.serveFolder(__dirname)
app.on('window', win => initWindow(win))
initWindow(app.mainWindow())
}
function initWindow(win) {
win.load('example.html', requireHandle)
}
example.html
<script>
async function run() {
const [require] = await carlo.loadParams()
require('fs').then(fs => {
console.log(fs.readFileSync('example.html'))
})
}
</script>
<body onload="run()">
results in
@trusktr I try avoiding rpc, mostly by doing something like below.
import fs from 'fs';
...
await app.exposeFunction('fs', (desired, args) => {
return fs[desired](args.path);
});
...
...
<script>
const run = async () => {
const response = await fs('readFileSync', {path: 'README.md'});
}
</script>
...
I'd like to run existing Node.js code without modification.
Did I do my attempt correctly? Is there a way to do it? (existing code expects require()
to be synchronous)
Does the app.exposeFunction
tool (de)serialize information between the contexts under the hood? If so, that's a no-go then.
Ah, ok, so no. Is there any plan for future Node.js support? Or is the plan to keep the web context purely a web context for always?
Hello, I'm coming from Electron, and would like to be able to import Node.js modules on the front end.
Some questions: