Equivalent of Ruby's "require" in Javascript - javascript

How do you "require" another file into the existing file in Javascript? Is there anything similar to Ruby's "require" or "load"?
> Note: I'm using JS in server (Rhino)
Reason: I just need to access the methods in the other JS files.
Update: This works only when executing it from cmd line. When I try to call it programatically it fails. Here's my code: http://pastie.org/1240495

To use the load function in js embedded from Java, you must first expose it in on the scripting context. There's probably a way to do it from Java, but you can do it using js as well.
Disclaimer: this solution uses source code taken from an Apache-licensed project I have been working on. You can see the original source file here.
This js file sets up your global variables, and lives in a file named setupglobals.js:
var shell = org.mozilla.javascript.tools.shell.Main;
var args = ["-e","var a='STRING';"];
shell.exec(args);
var shellGlobal = shell.global;
//grab functions from shell global and place in current global
load=shellGlobal.load;
print=shellGlobal.print;
defineClass=shellGlobal.defineClass;
deserialize=shellGlobal.deserialize;
doctest=shellGlobal.doctest;
gc=shellGlobal.gc;
help=shellGlobal.help;
loadClass=shellGlobal.loadClass;
quit=shellGlobal.quit;
readFile=shellGlobal.readFile;
readUrl=shellGlobal.readUrl;
runCommand=shellGlobal.runCommand;
seal=shellGlobal.seal;
serialize=shellGlobal.serialize;
spawn=shellGlobal.spawn;
sync=shellGlobal.sync;
toint32=shellGlobal.toint32;
version=shellGlobal.version;
environment=shellGlobal.environment;
Here is your original Java host file, now augmented to evaluate setupglobals.js before any other scripts:
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import org.mozilla.javascript.*;
public class RhinoRunner {
public static void main(String args[]) throws IOException
{
BufferedReader script = new BufferedReader(new FileReader("setupglobals.js"));
BufferedReader script2 = new BufferedReader(new FileReader("example.js"));
Context context = Context.enter();
try {
ScriptableObject scope = context.initStandardObjects();
context.evaluateReader(scope, script, "script", 1, null);
context.evaluateReader(scope, script2, "script2", 1, null);
Function fct = (Function)scope.get("abc", scope);
Object result = fct.call(context, scope, scope, new Object[] {2, 3});
System.out.println(Context.jsToJava(result, int.class));
}
finally
{
Context.exit();
}
}
}
Here is your example.js, now augmented to use the global load function to load the file hello.js:
function abc(x,y)
{
return x+y
}
load("hello.js")
And finally, here is hello.js:
print("hello world!")
When executed, RhinoRunner prints the following:
hello world!
5

In Rhino shell, you can should be able to use load(), which is a predefined global method:
load([filename, ...])
Load JavaScript source files named by string arguments. If multiple arguments are given, each file is read in and executed in turn.

Related

allow javascript to control some environmental things

I want to use GraalVM to run user-written javascript code (I am writing a Java 11 project).
Can I give Java objects to the javascript file, in javascript I want to write something like
shrek.shedLayer();
and when my Java program executes this statement it is equivalent to as if it (the java program) had directly run
someLong.pieceOf().Code();
Maybe multipleLines = new Maybe();
someLong.add(multipleLines);
or whatever.
Yes, you can have your Java code evaluate JavaScript. Yes, you can pass Java objects to the JavaScript context. Yes, you can return JavaScript values into Java.
Here's an example of the Java code that instantiates a JavaScript context, evaluates a string of JavaScript code that defines a function, stores this function in a variable, calls it passing Java objects as parameters and prints the return value of this function invocation.
import org.graalvm.polyglot.*;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.stream.Stream;
public class ExtListDir {
public static void main(String[] args) throws java.io.IOException {
final Context context = Context.create("js");
String s = "name + ': ' + size";
if (args.length == 1) {
s = args[0];
}
final Value lambda = context.eval("js",
"(function(name, size) { return " + s + "})");
try (Stream<Path> paths = Files.walk(Paths.get("."))) {
paths.filter(Files::isRegularFile).forEach((Path p) -> {
File f = p.toFile();
Value v = lambda.execute(f.getName(), f.length());
System.out.println(v);
});
}
}
}
If you want to use Java classes from the JS context, you can reference them with Java.type(), for example here's a JS snippet which uses Java's BigInteger:
const BigInteger = Java.type('java.math.BigInteger');
var text = BigInteger.valueOf(10).pow(100)
.add(BigInteger.valueOf(43)).toString();

Kotlin Call Javascript function in Android without webView

Is there any way we can call JS function from Kotlin without having WebView in Android?
Let's say as mentioned below I have one JS function helloJS() in test.js file,
test.js:-
function helloJS(){
return "Hello from JS"
}
And now I want to call this function from Kotlin file like
TestClass.kt:-
class TestHello{
fun getHelloFromJS(){
val name = test.helloJS()
}
}
Till now I am using Webview and loading JS file into that and getting result as call back
But, I read that Kotlin is interoperable with JS like Java
So I am curious to know if there is any way we can use that on Android without having webView
This is not possible straight forward but I found one library Execute JavaScript in Android without WebView for achieve this.
Read that blog carefully and follow below step.
Keep your JavaScript file (test.js) in assets folder in android project.
I have converted that code into Kotlin.
CallJavaScript.jks
import org.mozilla.javascript.Context
import org.mozilla.javascript.Function
import java.io.InputStreamReader
object CallJavaScript {
fun callFunction(mContext: android.content.Context): Any? {
var jsResult: Any? = null
val params = arrayOf<Any>("")
// Every Rhino VM begins with the enter()
// This Context is not Android's Context
val rhino = Context.enter()
// Turn off optimization to make Rhino Android compatible
rhino.optimizationLevel = -1
try {
val scope = rhino.initStandardObjects()
// Note the forth argument is 1, which means the JavaScript source has
// been compressed to only one line using something like YUI
val assetManager = mContext.assets
try {
val input = assetManager.open("test.js")
val targetReader = InputStreamReader(input)
rhino.evaluateReader(scope, targetReader, "JavaScript", 1, null)
} catch (e: Exception) {
e.printStackTrace()
}
// Get the functionName defined in JavaScriptCode
val obj = scope.get("helloJS", scope)
if (obj is Function) {
// Call the function with params
jsResult = obj.call(rhino, scope, scope, params)
// Parse the jsResult object to a String
val result = Context.toString(jsResult)
}
} finally {
Context.exit()
}
return jsResult
}
}
Add this line to build.gradle:
implementation 'org.mozilla:rhino:1.7R4'
In your assets folder, create a file called test.js:
function helloJS()
{
return "Hello from JS";
}
Now simply call above function from Activity.
Log.e("JS : ", CallJavaScript.callFunction(this).toString());
Output :
E/JSĀ :: Hello from JS
It's not possible. You must not confuse the language with the platform.
Kotlin is interoperable with JS like Java
means Kotlin/JS can use and be used in a Javascript platform (Node.js or browsers). The Kotlin code compiled (transpiled) into js is able to call other js files. And external Js code can call the js code build from Kotlin. This is the interoperability with JS.
There is no interoperability between Kotlin/JS and Kotlin/JVM.
Kt looks like JS, but it is not. It will be compiled for Android runtime, not for the java script engine.
JS code require a JS runtime, but it is not in Android Runtime.
i.e. you cannot run JS directly in Java / Kt code for Android.
Am not a pro in Kotlin but Java is a pie for me. Anything you can implement in Java can be implemented in Kotlin and To execute Javascript code, I use rhino which does the job pretty easier than using the webview
Implement it:
try {
Scriptable scope = rhino.initStandardObjects();
rhino.evaluateString(scope, javaScriptCode, "JavaScript", 1, null);
Object obj = scope.get(functionNameInJavaScriptCode, scope);
if (obj instanceof Function) {
Function jsFunction = (Function) obj;
// Call the function with params
Object jsResult = jsFunction.call(rhino, scope, scope, params);
// Parse the jsResult object to a String
String result = Context.toString(jsResult);
}
}finally {
Context.exit();
}

"clone" already loaded Scripts without rerunning them in java ScriptEngine

So, my problem is the following:
Lets say, i have a base of js modules which need to be preloaded.
I have now several scripts which need to be able to be run without interfereing into others.
The scripts look like this:
function A(){
}
function B(){
}
What i want to do is call Function A from Script 1 and Function A from Script 2. But only the last Script is executed correctly since it is the same ScriptEngine I am calling.
I tried an attempt like this:
public static ScriptEngine eval(BufferedReader file) throws ScriptException {
SimpleScriptContext context = new SimpleScriptContext();
context.getBindings(ScriptContext.ENGINE_SCOPE).putAll(engine.getBindings(ScriptContext.ENGINE_SCOPE));
ScriptEngine dengine = new NashornScriptEngineFactory().getScriptEngine("-strict");
dengine.eval(file,context);
ClassLoader cl = MyClass.getInstance().getClass().getClassLoader();
Thread.currentThread().setContextClassLoader(cl);
return dengine;
}
to create multiple ScriptEngines. But that failed. So what is the right attempt, to "clone" already loaded Scripts without rerunning them?

Is it possible to import javascript files to a java ScriptEngine

I am using nashorn java ScriptEngine. I would like to evaluate a script which includes other scripts. I know I can use the load directive directly in the javascript itself, but I would prefer to import or load it directly from the java code instanciating the scriptEngine.
Is there a way to do this ? Something like :
void evaluateScript(String scriptName, String dependency) {
ScriptEngineManager factory = new ScriptEngineManager();
ScriptEngine jsEngine = factory.getEngineByName("nashorn");
jsEngine.load(depency); // does not exist.
jsEngine.eval();
}
I see the "load" function does not exist. How could I achieve this?
Thanks
Actually I found the answer myself: as mentioned in the comment, it is possible to call several eval with different scripts, same engine, and the engine will keep the evaluated scripts in its context. So here is my code:
public void executeScript(String scriptName, String[] dependencies) {
try {
FileReader script = new FileReader(scriptName);
ScriptEngineManager factory = new ScriptEngineManager();
ScriptEngine jsEngine = factory.getEngineByName("nashorn");
if(dependencies != null) {
for (String dependency : dependencies) {
FileReader dependencyFile = new FileReader(dependency);
jsEngine.eval(dependencyFile);
}
}
jsEngine.eval(script);
}
}
I can define functions in my dependencies and use them in the script of name scriptName.
javax.script.ScriptEngine has many "eval" methods - there are java.io.Reader accepting eval methods like this -> eval
You can pass a java.io.FileReader or a jdk.nashorn.api.scripting.URLReader to load script from a file or a URL.

How to call a JS function from Java Rhino

So I've been looking and I found some other questions in stackoverflow but they weren't explained and I didn't understand much. I'm trying to execute functions from a .js file. One of the functions is:
function getRSAKey(mod, exp, pass) {
pubKey = RSA.getPublicKey(mod,exp);
encrypted = RSA.encrypt(pass, pubKey);
return encrypted;
}
As you see this function calls other functions, this is quite a big file and there's no way I can "translate" it to Java, so I have to call the .js file within it. So far I think I need to create an String with the .js file, so that's what I have in my .java file:
BufferedReader script = new BufferedReader(new FileReader("rsa.js"));
Context context = Context.enter();
ScriptableObject scope = context.initStandardObjects();
How can I do to call the function getRSAKey with some given paramaters? Also I should handle the return in the .java file!
Thanks
Edit: I forgot to say that the script uses http://silentmatt.com/biginteger/ the class provided in the link. I was able to execute a script, but it says that 'ReferenceError: "BigInteger" is not defined.'

Categories

Resources