GraalVM + Nashorn Cannot extend classes - nashorn

I'm attempting to use graal + nashorn interop to write nodejs that interacts with Java. I'm starting graal with node --jvm --jvm.Xss2m --jvm.Dtruffle.js.NashornJavaInterop=true --jvm.classpath=libs/ --polyglot app.js. I cannot extend a class though. The javascript code is
const GraaljsgrpcServiceImpl = Java.type('com.thing.GraaljsgrpcServiceImpl');
const HelloReply = Java.type('com.thing.HelloReply');
var GrpcImpl = Java.extend(GraaljsgrpcServiceImpl, {
sayHello: function(request, responseObserver) {
responseObserver.onNext(HelloReply.newBuilder().setMessage("Hello " + request.getName()).build());
responseObserver.onCompleted();
}
});
and my error is
TypeError: Could not determine a class loader with access to the JS engine and class com.thing.GraaljsgrpcServiceImpl This seems to point to a classloader issue with the java code I'm referencing and where the javascript is running(i.e. 2 different classloaders). Is there a way to pull this off when using graal/nodejs?

Thanks for reporting this classloader problem. We are looking into that and should be able to fix that with our next release (0.32 expected early March).
Regarding the --jvm.Dtruffle.js.NashornJavaInterop=true flag: we strongly encourage not using that, but depending on the built-in interoperability of GraalVM. However, in this mode Graal.js is not 100% compatible with Nashorn/Rhino; for instance, we are not supporting Java.extend in that mode. Is Java.extend the only reason why you set the NashornJavaInterop flag?
Thanks,
Christian

Related

Whether we should use classes in Typescript for Node or the same way as we are doing in javascript exporting functions development

I have a concern regarding Node development in Typescript.
I have been working with a node developer who is proficient in node with javascript but now we have decided to move from javascript to typescript, which is a good decision.
The problem is as we have started writing code in typescript but as we are facing conflicts to choose should we use modular way in typescript or use class.
Option 1:
ab.ts
export function a () {
will write whole code here for that
}
Option 2:
ab.ts
export class Ab {
constructor(){
}
public a() {
//write code here
}
}
If you use TypeScript and don't use Class / Interface then you are not getting the most out of it. So, I would highly recommend to structure your project in such way that you can make use of class/interface.

WebStorm compatibility with exporting of classes

I know that the ES6 export/import syntax is not part of Node.JS yet, so when I write a class in Node.JS, it usually goes something like this:
class Foo {
...
}
module.exports = Foo;
However, I frequently see a slightly more compact version of this:
module.exports = class Foo { ... }
When I write this code in WebStorm it will however complain "expression expected" (it doesn't like the class keyword in an assignment). The file seems to work fine when run with Node (~6.10) though.
Is there a compatibility setting in WebStorm to allow this? The only option I found was an inspection for warning about non-ES6 draft features.
WebStorm has issues resolving members of classes exported this way (see WEB-28158), but the syntax itself is correctly accepted (WebStorm 2017.3.2):
What IDE version do you use? Did you set JavaScript Language Version to ECMAScript 6 in Settings | Languages & Frameworks | JavaScript?
If this doesn't help, try invalidating caches

Why is the usage of util.inherits() discouraged?

According to the Node.js documentation :
Note: usage of util.inherits() is discouraged. Please use the ES6 class and extends keywords to get language level inheritance support. Also note that the two styles are semantically incompatible.
https://nodejs.org/api/util.html#util_util_inherits_constructor_superconstructor
The reason why util.inherits is discouraged, is because changing the prototype of an object should be avoided, as most JavaScript engines look for optimisations assuming that the prototype will not change. When it does, this may lead to bad performance.
util.inherits relies on Object.setPrototypeOf to make this change, and the MDN documentation of that native method has this warning:
Warning: Changing the [[Prototype]] of an object is, by the nature of how modern JavaScript engines optimize property accesses, currently a very slow operation in every browser and JavaScript engine. In addition, the effects of altering inheritance are subtle and far-flung, and are not limited to the time spent in the Object.setPrototypeOf(...) statement, but may extend to any code that has access to any object whose [[Prototype]] has been altered.
Because this feature is a part of the language, it is still the burden on engine developers to implement that feature performantly (ideally). Until engine developers address this issue, if you are concerned about performance, you should avoid setting the [[Prototype]] of an object. Instead, create a new object with the desired [[Prototype]] using Object.create().
As the quote says, you should use the ES6 class and extends keywords to get language level inheritance support instead of utils.inherits and that's exactly the reason for which to use it is discouraged: there exist better alternatives that are part of the core language, that's all.
util.inherits comes from the time when those utils were not part of the language and it requires you a lot of boilerplate to define your own inheritance tools.
Nowadays the language offers a valid alternative and it doesn't make sense anymore to use the ones provided with the library itself. Of course, this is true as long as you use plan to use ES6 - otherwise ignore that note and continue to use utils.inherits.
To reply to your comment:
How is util.inherits() more complicated?
It's not a matter of being more or less complicated. To use a core language feature should be ever your preferred way over using a library specific alternative for obvious reasons.
util.inherits() got deprecated in the new version of node so need to use the ES6 class and extends keywords to get language level inheritance support instead of utils.inherits.
below example which I gave below helps you to understand more clearly :
"use strict";
class Person {
constructor(fName, lName) {
this.firstName = fName;
this.lastName = lName;
}
greet() {
console.log("in a class fn..", this.firstName, "+ ", this.lastName);
}
}
class PoliceMan extends Person {
constructor(burgler) {
super("basava", "sk");
this.burgler = burgler;
}
}
let policeObj = new PoliceMan();
policeObj.greet();
Output : in a class fn.. basava + sk
Here we can see Person class is inherited by PoliceMan class, so that PoliceMan obj can access the properties of Person class by calling super(); in a constructor
Hope this will work as util.inherits();
Happy Coding !!!

How do I add functions to LESS in node.js

I used to use less-middleware, but switched to less as I needed to add custom functions/constants. I assume less-middleware uses less behind the scenes.
To define constants I used:
function lessDefine(name, value) {
less.tree.functions[name] = function () {
return new (less.tree.Anonymous)(value);
};
}
and to create a constant:
lessDefine('backgroundImage', config.backgroundImage);
Then to link into Express:
router.use('/stylesheets',
less.middleware(
lessOpts.source, lessOpts.main,
lessOpts.parser, lessOpts.compiler));
This was after crawling through bug reports, feature requests and google results, as the ability to extend LESS is not well documented. This worked last week, but now I see:
TypeError: Object #<Object> has no method 'middleware'
when I try to launch my node app.
What is the "correct" way to add functions/constants to LESS in Node.js?
Note that I use:
var less = require('less');
var lessMiddleware = require('less-middleware');
And my package.json uses the following version limits:
less-middleware: 1.0.3
less: 1.7.x
less.middleware is added by the less-middleware module.
Monkeypatching is frowned upon for a reason; less-middleware had its own less module installed within its folder (by npm), while my app was using a separate instance of less.
Hence, less.middleware was not being set in the instance of less that my app sees. After calling npm dedupe, the duplicate instances were consolidated and my app now works.

Using a global variable in Node.js for dependency injection

I'm starting out a long term project, based on Node.js, and so I'm looking to build upon a solid dependency injection (DI) system.
Although Node.js at its core implies using simple module require()s for wiring components, I find this approach not best suited for a large project (e.g. requiring modules in each file is not that maintainable, testable or dynamic).
Now, I'd done my bits of research before posting this question and I've found out some interesting DI libraries for Node.js (see wire.js and dependable.js).
However, for maximal simplicity and minimal repetition I've come up with my own proposition of implementing DI:
You have a module, di.js, which acts as the container and is initialized by pointing to a JSON file storing a map of dependency names and their respective .js files.
This already provides a dynamic nature to the DI, as you may easily swap test/development dependencies.
The container can return dependencies by using an inject() function, which finds the dependency mapping and calls require() with it.
For simplicity, the module is assigned to a global variable, i.e. global.$di, so that any file in the project may use the container/injector by calling $di.inject().
Here's the gist of the implementation:
File di.js
module.exports = function(path) {
this.deps = require(path);
return {
inject: function(name) {
if (!deps[name])
throw new Error('dependency "' + name + '" isn\'t registered');
return require(deps[name]);
}
};
};
Dependency map JSON file
{
"vehicle": "lib/jetpack",
"fuel": "lib/benzine",
"octane": "lib/octane98"
}
Initialize the $di in the main JavaScript file, according to development/test mode:
var path = 'dep-map-' + process.env.NODE_ENV + '.json;
$di = require('di')(path);
Use it in some file:
var vehicle = $di.inject('vehicle');
vehicle.go();
So far, the only problem I could think of using this approach is the global variable $di.
Supposedly, global variables are a bad practice, but it seems to me like I'm saving a lot of repetition for the cost of a single global variable.
What can be suggested against my proposal?
Overall this approach sounds fine to me.
The way global variables work in Node.js is that when you declare a variable without the var keyword, and it gets added to the global object which is shared between all modules. You can also explicitly use global.varname. Example:
vehicle = "jetpack"
fuel = "benzine"
console.log(vehicle) // "jetpack"
console.log(global.fuel) // "benzine"
Variables declared with var will only be local to the module.
var vehicle = "car"
console.log(vehicle) // "car"
console.log(global.vehicle) // "jetpack"
So in your code if you are doing $di = require('di')(path) (without var), then you should be able to use it in other modules without any issues. Using global.$di might make the code more readable.
Your approach is a clear and simple one which is good. Whether you have a global variable or require your module every time is not important.
Regarding testability it allows you to replace your modules with mocks. For unit testing you should add a function that makes it easy for you to apply different mocks for each test. Something that extends your dependency map temporarily.
For further reading I can recommend a great blog article on dependency injection in Node.js as well as a talk on the future dependency injector of angular.js which is designed by some serious masterminds.
BTW, you might be interested in Fire Up! which is a dependency injection container I implemented.

Resources