How to call a JS function from Java Rhino - javascript

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.'

Related

Is it possible to only convert a dart function to javascript

I am currently using the following package where the readme illustrates the following
final bool loaded = await JsIsolatedWorker().importScripts(['test.js']);
I am using the isolate worker package so my code can work on web and outside of web. I would like to generate javascript code from my dart code. I have one file with a top level function and I use
dart compile js -O0 -o test.js test.dart
which I found here
https://dart.dev/tools/dart2js
this is my dart file
void main(List<String> args) {
doComputation('');
}
String doComputation(String input) {
return 'output';
}
I can generate javascript only if I have a main function but this generates a javascript file where the doComutation is not a top level function, so I am not sure if the package can call the function. It looks like it generates an entire program instead of just generating one function.
The generated file is too long to post
So what my question comes down to is this. Is there a way to generate javascript from dart for 1 function with its dependencies included instead of having to generate the entire program? So that I can call this function from dart.
I am not an expert but I also had this problem. Here's what worked for me:
In web_worker.dart:
import 'package:js/js.dart';
main(){
allowInterop(doComputation);
}
#JS('doComputation')
String doComputation(String computationInput) {
// Replace this with your actual computation.
final String computationOutput = "output";
return computationOutput;
}
Compile it using:
$ dart compile js web_worker.dart -o webWorker.js
Manually edit webWorker.js, the JS file generated by the compiler:
Delete this line at the top of the file:
(function dartProgram() {
and the line at the bottom of the file with the corresponding closing brace:
})();
I don't understand what's going on here but I found the Javascript version of the function doComputation() defined in webWorker.js as a property of the object "A".
I defined a wrapper at the top of the file like this:
function doComputation(computationInput) {
return A.doComputation(computationInput)
}
and then I was able to use the file with JsIsolatedWorker like this:
final bool loaded =
await JsIsolatedWorker().importScripts(['../web/webWorker.js']);
if (loaded) {
final String computationResult = await JsIsolatedWorker()
.run(functionName: 'doComputation', arguments: computationInput);
} else {
debugPrint('Web worker is not available');
}
If someone who understands this better can elaborate or improve on this solution, that would be great. I don't really have any idea what I'm doing. I'm just posting this to hopefully help other people save time in the future by sharing what worked for me.
You can use js package to call JavaScript APIs from Dart code, or vice versa. To make a Dart function callable from JavaScript by name, use a setter annotated with #JS().
#JS()
library callable_function;
import 'package:js/js.dart';
/// Allows assigning a function to be callable from `window.functionName()`
#JS('functionName')
external set _functionName(void Function() f);
/// Allows calling the assigned function from Dart as well.
#JS()
external void functionName();
void _someDartFunction() {
print('Hello from Dart!');
}
void main() {
_functionName = allowInterop(_someDartFunction);
}
JavaScript code may now call functionName() or window.functionName().
Check google chartjs https://github.com/google/chartjs.dart/tree/master/example for a complete example.
From dart2js "Helping dart2js generate better code" there is a tip :
Don’t worry about the size of your app’s included libraries. The dart2js compiler performs tree shaking to omit unused classes, functions, methods, and so on. Just import the libraries you need, and let dart2js get rid of what you don’t need.
Related to this post https://stackoverflow.com/a/21124252/3733730.
You can do this instead by using the package dart2js
one make a program for your main.dart dart2js where the function or command you wanted to make is there, then create a separate dart file what function you wanted to call, and it will fix your problem, it is a separate file but will only execute one function that you needed to do so and that is the separate file

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?

JavaScript reference in TypeScript file

I have a JavaScript file from:
http://javascriptsoapclient.codeplex.com/
I need to write my program in TypeScript.
My problem is now that I don't know how to integrate this .js file in my .ts file.
I want to use SOAPClient from the .js file to invoke methods from the Service.
Some code from the .js:
function SOAPClient() {}
SOAPClient.invoke = function(url, method, parameters, async, callback)
{
if(async)
SOAPClient._loadWsdl(url, method, parameters, async, callback);
else
return SOAPClient._loadWsdl(url, method, parameters, async, callback);
}
I tried it this way: /// <reference path="soapclient.js" /> but it doesn't work.
Please help me!
Thanks in advance.
You need to build a definition for the external JavaScript. The best way to start with this is to look at your usage. For example, I have taken the "Hello World" example from the documentation:
function HelloWorld() {
var url = 'http://localhost/';
var pl = new SOAPClientParameters();
SOAPClient.invoke(url, "HelloWorld", pl, true, HelloWorld_callBack);
}
function HelloWorld_callBack(r) {
alert(r);
}
In order to get auto-completion and type checking for the features used, you would need to put the following code inside a file named SoapClient.d.ts.
declare class SOAPClientParameters {
}
interface SOAPClient {
invoke(url: string, method: string, parameters: SOAPClientParameters, async: boolean, callback?: (response: any) => any);
}
declare var SOAPClient: SOAPClient;
In Visual Studio, this will give you the auto-completion and type checking. In some IDEs you need to add a reference comment to the TypeScript file that calls SOAPClient:
///<reference path="SoapClient.d.ts"/>
You still need to remember to add the actual SOAPClient JavaScript file to your page so it is available at runtime.
There are full instructions on creating your own type definitions here: Complex Type Definitions Made Easy.
declare var SOAPClient: any;
Should get you started :)

Equivalent of Ruby's "require" in 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.

Categories

Resources