How do you actually run scalajs code in nodejs? - node.js

I'm developing a backend chat server. It's currently written in messy callback javascript so I'm considering porting it to scalajs.
I've been looking through the beginner's guides, but I can't find how to actually compile the project to a single javascript file that I can run with node (e.g. node ./target/scala_2.11/my-project.js).
How do you compile a single file that you can run directly as a node program, and not in the browser?
My code couldn't be simpler:
package example
import scala.scalajs.js
import js.Dynamic.{ global => g }
object ScalaJSExample extends js.JSApp {
def main(): Unit = {
g.console.log("*** Did something ***")
println("Trying to print something...")
}
}
sbt run correctly prints:
*** Did something ***
Trying to print something...
But when I run sbt fullOptJS and then node ./target/scala-2.11/example-opt.js nothing is printed to the console.

The example-opt.js does not contain the one line of JavaScript used to actually launch the code. It only defines example.ScalaJSExample().main() as a function, but it doesn't call it.
An easy way to make it call that function automatically is to instruct sbt to add the call at the end of the .js file with this sbt setting:
scalaJSOutputWrapper := ("", "example.ScalaJSExample().main();")
This will allow you to just invoke
node ./target/scala-2.11/example-opt.js

Related

How do I use this monaco library in an electron app?

How can I use monaco in my electron app? out this example: What's the proper way to do that? i'm open to new suggestions. I throughout into building a micro frontends but it's not that nice in react/electron and in the end i would have to include the final index output file using iframe. I wish I could use something we do with dlls in desktop application. note: i'm new to react and electron, perdon mystakes that seems so simple.
Well, I tried to "merge" as needed both webpack configs. Is this the way to go? so far i couldn't make it. I added:
resolve: {
alias: {
'vscode': require.resolve('#codingame/monaco-languageclient/lib/vscode-compatibility')
}
but it cannot find the vscode module, i'm getting the error:
Module not found: Can't resolve 'vscode' in 'C:\Users\jjj\Desktop\merge\Newton\node_modules\vscode-languageclient\lib\common' even tho the package is installed.
I also tried to add "editor.worker": 'monaco-editor/esm/vs/editor/editor.worker.js' in the entry section but I got the error:
An unhandled error has occurred inside Forge:
Conflict: Multiple chunks emit assets to the same filename index.js (chunks 179 and 915)
Error: Conflict: Multiple chunks emit assets to the same filename index.js (chunks 179 and 915)
I did plan to -- assuming it's the proper way to go ---, once managed to fix this webpackes merge, I'd include the main file with the contents:
require('monaco-editor');
(self as any).MonacoEnvironment = {
getWorkerUrl: () => './editor.worker.bundle.js'
}
require('./client');
then have
<div id="container" style="width:800px;height:600px;border:1px solid grey"></div>
somewhere to show the editor and the <script src="main.bundle.js"></script> wouldn't be needed due to the fact it would be included in the webscript's output javascript bundle file, used elsewhere by the entire application.
Various errors may occur depending on the bundler configuration, so I made it simple example by referring to codes monaco-editor and monaco-languageclient. Both repositories work after build, so I separated the main process and renderer process folders to avoid overlapping outputs. Maybe this is related to Forge's error.
I created an Electron renderer code using monaco-languageclient's client code, and in the main process, run monaco-languageclient's server. Therefore, both processes must share the same web socket port. You can also erase the following lines and run LanguageServer externally.
Here is an example without the iframe.

How do the core modules in node.js work? (https://github.com/nodejs/node/blob/master/lib)

Does the node interpreter look for core modules (let's say "fs") within the node binary? If yes, are these modules packaged as js files. Are the core modules that are referenced within our code converted to c/c++ code first and then executed? For example, I see a method in the _tls_common.js (https://github.com/nodejs/node/blob/master/lib/_tls_common.js) file called "loadPKCS12" and the only place that I see this method being referenced/defined is within the "node_crypto.cc" file (https://github.com/nodejs/node/blob/master/src/node_crypto.cc). So how does node link a method in javascript with the one defined in the c/c++ file?
here is the extract from the _tls_common.js file that makes use of the "loadPKCS12" method:
if (passphrase) {
c.context.loadPKCS12(buf, toBuf(passphrase));
} else {
c.context.loadPKCS12(buf);
}
}
} else {
const buf = toBuf(options.pfx);
const passphrase = options.passphrase;
if (passphrase) {
c.context.loadPKCS12(buf, toBuf(passphrase));
} else {
c.context.loadPKCS12(buf);
There are two different (but seemingly related) questions asked here. The first one is: "How the core modules work?". Second one being "How does NodeJS let c++ code get referenced and executed in JavaScript?". Let's take them one by one.
How the core modules work?
The core modules are packaged with NodeJS binary. And, while they are packaged with the binary, they are not converted to c++ code before packaging. The internal modules are loaded into memory during bootstrap of the node process. When a program executes, lets say require('fs'), the require function simply returns the already loaded module from cache. The actual loading of the internal module obviously happens in c++ code.
How does NodeJS let c++ code get referenced in JS?
This ability comes partly from V8 engine which exposes the ability to create and manage JS constructs in C++, and partly from NodeJS / LibUV which create a wrapper on top of V8 to provide the execution environment. The documentation about such node modules can be accessed here. As the documentation states, these c++ modules can be used in JS file by requiring them, like any other ordinary JS module.
Your example for use of c++ function in JS (loadPKCS12), however, is more special case of internal c++ functionality of NodeJS. loadPKCS12 is called on a object of SecureContext imported from crypto c++ module. If you follow the link to SecureContext import in _tls_common.js above, you will see that the crypto is not loaded using require(), instead a special (global) method internalBinding is used to obtain the reference. At the last line in node_crypto.cc file, initializer for internal module crypto is registered. Following the chain of initialization, node::crypto::Initialize calls node::crypto::SecureContext::Initialize which creates a function template, assigns the appropriate prototype methods and exports it on target. Eventually these exported functionalities from C++ world are imported and used in JS-World using internalBinding.

Use Visual Studio Code to debug Node.js dependency which is "require"d

I want to use VSC to develop some extensions to an existing project. In particular UglifyJS3.
So I create a test script, in which I call into the module to test and debug my changes. The code there is simply:
var UglifyJS = require("../tools/node");
var result = UglifyJS.minify(code, ...)
This works while debugging/single-stepping. However VSC already fails to resolve the minify function which is exported by UglifyJS.
I am also not able to simply set breakpoints in the UglifyJS files and have them triggered. VSC shows an error on startup about not being able to resolve the breakpoint.
Looking at ../tools/node.js I see code like:
var UglifyJS = exports;
require.resolve("../lib/utils.js")
...
require.resolve("../lib/minify.js")
require.resolve("./exports.js")
with exports.js containing exports["minify"] = minify;.
Is there anything I have missed? How can I make debugging (and optionally IntelliSense) work?
I found the reason:
First clue was that the code showed up in the debugger as <eval> and in a VM<some number> tab. So somehow the code was not actually read from file but dynamically evaluated.
What happens is (to a reduced example):
var fn = require.resolve("<file>"); // Resolve the filename
var code = fs.readFileSync(fn, "utf8");; // Read the file contents
new Function("exports", code)(exports); // Create a new function containing the files code and execute it
The last bit is a bit more cryptic in code and the new Function was new to me (no pun intended). It essentially boils down to an optimized eval with strict-mode compatibility: https://whereswalden.com/2011/01/10/new-es5-strict-mode-support-new-vars-created-by-strict-mode-eval-code-are-local-to-that-code-only/
Hence: The code executed is actually eval'd code and not the files itself.
Solution: Either live with it or change it upstream to "clean" modules.

How to use multiple compiled ts files in a node module?

Currently I am trying to use TypeScript to create JavaScript-Files which are then required in a index.js file. I am using VS 2015 Update 3 with node.js tools 1.2 RC. Sadly it is not working like I thought it would.
To begin with here is my initial idea:
I have a node module (to be precise, it is a deployd module http://docs.deployd.com/docs/using-modules/). This module is handling payment providers like paypal or stripe. Now I want to use TypeScript to write interfaces, classes and use types to make it easier to add new payment providers. The old .js files should still be there and used. I want to migrate step by step and use the self-written and compiled .js files together. So I thought I can create .ts files, write my code, save, let VS compile to js and require the compiled js file in another js file. Okay, that is my idea... Now the problem
I have a PaymentProvider.ts file which looks like this
import IPaymentProvider = require("./IPaymentProvider.ts"); // Interface, can't be realized in JavaScript, just TypeScript
export abstract class PaymentProvider implements IPaymentProvider.IPaymentProvider
{
providerName: string;
productInternalId: number;
constructor(providerName : string)
{
this.providerName = providerName;
}
//... some methods
};
The other file is PaypalPaymentProvider.ts
import PaymentProvider = require("./PaymentProvider.ts");
export class PaypalPaymentProvider extends PaymentProvider.PaymentProvider
{
constructor()
{
super("paypal");
}
// more methods
}
VS 2015 doesn't show any errors. The js and .js.map files are generated. Now I thought I could require the files and that's it. I tried to use the PaypalPaymentProvider.js like this const PaypalPaymentProvider = require("./lib/payment-provider/PaypalPaymentProvider.js"); (yes, it is located there) but it's not working. When starting the index.js via node I get the following error:
...\Path\PaymentProvider.ts:1 (function (exports, require, module, __filename, __dirname) { import IPaymentProvider = require("./IPaymentProvider.ts"); Unexpected token import....
I find it strange that this is the error, because JavaScript doesnt't have Interfaces. The compiled IPaymentProvider.js is empty.
Also I thought that TypeScript is mainly for development and the compiled JavaScript for production. So why it is requiring a ts-file? I thought imports in typescript will be converted to require of the compiled js-file?
Do I need to require all compiled js files and not only the one I currently try to use? (I don't think so...)
To be honest, I think the main problem is that I am new to TypeScript and make something wrong from the very beginning.
Any help/advice? Thanks!
I have the solution... Thanks to Paelo's links I was able to see that I need to omit the file ending! So the really simple solution was to write
import IPaymentProvider = require("./IPaymentProvider");
instead of
import IPaymentProvider = require("./IPaymentProvider.ts");
When I changed that in every ts file it worked perfectly!

Cannot set breakpoint inside function when using require inside closure

Using node-inspector, I'm unable to set breakpoint in the following node.js code. (Content of main.js)
(function() {
require('underscore');
var doSomething = function(callback) {
callback('doSomething Finished');
}
doSomething(function(x) {
console.log(x);
});
}).call(this);
I can easily set a breakpoint on line 2, line 4 or line 8, however no matter how hard I try the debugger won't let me set a break point on line 5 or line 9. To be clear, I'm using the following commands to run node-inspector
node --debug-brk main.js
node-inspector
I also tried to debug in web storm, however the issue persists. If I remove the line require('underscore');, then the problem immediately goes away and I'm able to set break point inside function body again. The problem also goes away if I remove the outermost closure function. It seems that the interaction between require and file level closure is screwing up the node debugging functionality. Has anyone experienced this problem themselves and / or knows any workarounds to be able to break inside function body?
EDIT: My node js version
Tony:~ $ node --version
v0.10.12
Tony:~ $
I ran exactly into the same issue with the same setup.
I've added a breakpoint after the definition of the target-function (that was the only place i could actually add a breakpoint). When the debugger reached that breakpoint and the function was actually defined, i was able to add breakpoints to the actual target-function...
This may not be the answer that you want to hear as it doesn't explain why you can't set any breakpoints, but I would simply remove your require statement from the closure and place it top-level. I would go even further and recommend that you don't use a closure like the one above at all.
The reason is that node uses its own module system, and unlike Javascript in the browser, declaring variables top-level does not pollute the global namespace. This is where require(...) comes in. So, you gain nothing by wrapping your code in an immediately invoked function (unless of course you want your module to be able to run both client side and server side).
I would guess that the reason that you are not able to set any breakpoints is that the V8 runtime is recognizing an unnecessary closure and then optimizing your code for you. The rewritten code may not have the correct source mapping and so breakpoints cannot be set.
So, two suggestions:
require calls are not like regular statements. They are more similar to import statements in Java and are handled specially by the compiler. They should always be top-level in a node file.
No need to wrap your code in an anonymous function when in Node.

Resources