Use V8 JavaScript engine to execute JS lib without web view - javascript

I am developing a JavaScript component which is responsible for making requests to the server and dispatching results to the UI. By doing this in JavaScript, I am able to use my component in several types of UI: Android app, iOS app, desktop app (QT), web app...
All these UI have instantiated a web view, so my component is started when the UI loads the dedicated URL (webview.load("file://myfirstWebPage.html")).
This first web page loads all the JavaScript components, and when it's done, the UI is able to make some requests to the JavaScript component, which makes a request to the server and when it has the response, it dispatches it back to the client (UI Android, UI iOS ...)
This architecture works fine, but I would like to know if there is another way to load the JavaScript component without using a web view on each client?
Can the V8 engine help me?

If I'm understanding your question, you're looking for a way to execute JavaScript across many platforms (iOS, Android, etc.) without the use of a WebView. The solution will be platform-specific, since even the underlying WebView implementations are different for each platform.
For Android, so long as the device ships with V8, you can create a new V8 Context via its API and use that to execute your JavaScript. The device must actually ship with V8. This answer may help you further.
For iOS, which uses JavaScriptCore, recent developments in iOS7 have been made to allow you load and run arbitrary JavaScript code. Read more here.

For the Android part. I used J2V8 JavaScript library. It is a Java wrapper of Google's V8 JavaScript engine. See here for more details.

I don't know how to use V8, but you can use Rhino library instead. There is no WebView involved too.
Download Rhino first, unzip it, put the js.jar file under libs folder. It is very small, so you don't need to worry your apk file will be ridiculously large because of this one external jar.
Here is some simple code to execute JavaScript code.
Object[] params = new Object[] { "javaScriptParam" };
// Every Rhino VM begins with the enter()
// This Context is not Android's Context
Context rhino = Context.enter();
// Turn off optimization to make Rhino Android compatible
rhino.setOptimizationLevel(-1);
try {
Scriptable 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
rhino.evaluateString(scope, javaScriptCode, "JavaScript", 1, null);
// Get the functionName defined in JavaScriptCode
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();
}
You can see more details at my post.

I found this really nifty open source ECMAScript compliant JS Engine completely written in C called duktape
Duktape is an embeddable Javascript engine, with a focus on portability and compact footprint.
You'd still have to go through the ndk-jni business, but it's pretty straight forward. Just include the duktape.c and duktape.h from the distributable source here(If you don't want to go through the build process yourself) into the jni folder, update the Android.mk and all that stuff.
Here's a sample C snippet to get you started.
#include "duktape.h"
JNIEXPORT jstring JNICALL
Java_com_ndktest_MainActivity_evalJS
(JNIEnv * env, jobject obj, jstring input){
duk_context *ctx = duk_create_heap_default();
const char *nativeString = (*env)->GetStringUTFChars(env, input, 0);
duk_push_string(ctx, nativeString);
duk_eval(ctx);
(*env)->ReleaseStringUTFChars(env, input, nativeString);
jstring result = (*env)->NewStringUTF(env, duk_to_string(ctx, -1));
duk_destroy_heap(ctx);
return result;
}
Good luck!

Related

Calling swift Code From Javascript

Is it possible to call Swift functions/callbacks from Javascript ?
In Android it is possible to use JavaVoidCallbacks, is there anything similar in Swift? Right now Im using JavaScriptCore,where i can call javascript functions from Swift.
Yes you can.
Please refer to this Tutorial: https://www.raywenderlich.com/124075/javascriptcore-tutorial
You are interested in the paragraph "Exposing Native Code"
In obj-c is very simple. You can do it just by using your jsContext as a normal dictionary.
context[#"functionName"] = ^ <#returnType#> (<#parameters#>) {
<#Your code#>
}
Hope it helped.
In Swift, the easiest way I found was to create a gateway object in Javascript, using e.g. evaluateScript(), and then adding functions to that object:
// x is JSContext
let gateway = x.objectForKeyedSubscript("gateway" as NSString)
let p: #convention(block) (Int, Double) -> () = { h, ms in
return self.swift_method(h, ms)
}
gateway!.setObject(p, forKeyedSubscript: "swift_method" as NSString)
After that you can call gateway.swift_method() in Javascript.
Most type conversions are automatic. I have used types Int, Double, String and [Int] as parameter and/or return types in the lambda.
I have the same question. When I saw the answers to this Q. I tried to use JavaScriptCore to call Swift methods from the JS side. I could inject Swift or JS methods into JSContext. However, the methods injected into JSContext are not accessible in my case.
I use WKWebView as an HTML viewer in the ViewController in my iOS native app. I use this kind of view controller to present some help information in my app. After several days of struggling, I finally found an alternative way to make Swift and JS interaction happen. The strategy is to use WKScriptMessageHandler as a gateway between Swift and JS. Refer to this good blog on how to do it in detail. Another blog, Using WebKit to call WKWebView JavaScript from Swift and Swift from JavaScript, provides another example case, which is very useful.
From my experience, WKScriptMessageHandler is based on a very elegant structure. Through WKUserContentController, you set up a message gateway between JS and Swift. There is This will allow a JS callback to Swift with messages. A delegate of WKWebViewConfiguration has to be implemented, my view controller with web view, or my custom class, to receive JS message calls with data. The message can take a JSON string as a parameter to pass data. On the Swift side, by using a similar JSContext syntax like evaluateJavaScript to specify JS a function with data.
By the way, I was told that in my case, JavaScriptCore is based on Java virtue machine. There may be performance issue and may pose a security risk. Apple has disabled the feature of JavaScriptCore in WKWebView.
The Xcode in my case is Version 13.4, and Swift is 5.
I have written a blog on this: Build a Bridge between Swift and JS

Extend Android class with generic parameters in NativeScript

I am using NativeScript 2.0 and I would like to create an extension of an Android class like AsyncTask which contains generic parameters.
I know that I can use the extend() method to create an own implementation of a class or interface:
var myRunnable = java.lang.Runnable.extend({
action: null,
run: function() {
this.action();
}
});
But how can I do this for generic classes / interfaces in "pure" JavaScript?
You should be able to extend any interface/class using the same technique. At worst case you can extend Object. To my knowledge at this moment you can't create a interface/class from straight JS as the Java side needs something to base it off of so that the signatures are correct.
However, based on your example; if you are attempting to create a thread or runable in JavaScript; the result will currently fail horribly. NativeScript is currently a single thread, and if you attempt to cause android to attempt to jump back into JS while it is running JS, well lets just say it won't be your friend. :-)
There is a feature request and apparently this is the next big project now that 2.00 has been released. So we should see threads in the near future. There is also a plugin (disclaimer, I'm the author) called NativeScript-webworkers which can give you access to additional JS threads, but the JS threads DO NOT have the ability to interact with the OS like NS does, they are pure JS threads.

Win8 App Html/Js getting the version number (equivalent of PackageVersion)

I have a c#\XAML Win8 Modern app that I have been tasked with turning into HTML\JS.
In c# I could use:
PackageVersion currentVersion = new PackageVersion();
Is there an equivalent in js (I would guess it would be under something in WinJS)
Generally speaking, if it's an API that comes out of the Windows.* namespace, then it's usually available in JavaScript as well (with the exception of Windows.UI.Xaml.* and a smattering of others that aren't needed because JS has intrinsic APIs, as with JSON).
In this case, PackageVersion comes from Windows.ApplcationModel. The trick in JS is that you have to use fully qualified identifiers because there's not a using statement (so often we assign a local variable to the namespace and reference off that to save typing). So in your case, you'd be doing something like
var currentVersion = Windows.ApplicationModel.Package.current.id.version.
Or you can assign a namespace variable if you'll use it a lot:
var am = Windows.ApplicationModel;
var currentVersion = am.Package.current.id.version;
For anything in WinRT, just go to the docs page, e.g. http://msdn.microsoft.com/en-us/library/windows/apps/windows.applicationmodel.package.current.aspx, and click on the JavaScript tab under Syntax to see the specifics. If you don't get a syntax representation for JS, then that particular API isn't projected into JS.
Also, understand that WinJS is primarily a set of helper APIs and controls. You'll typically be using both WinRT APIs and WinJS APIs (though technically the latter are optional). They aren't mutually exclusive except for the WinJS UI parts that take the place of the XAML APIs in WinRT.
If you're getting into the JavaScript option, my free ebook from MSPress, Programming Windows Store Apps, in HTML, CSS, and JavaScript should help ramp you up, especially on the WinJS side of things.

What is the reason behind the use of Javascript in Wikitude SDK for Android?

I've been comparing several SDKs in order to add some location-based AR in one of my Android Apps. So far I've really liked the overall simplicity of Wikitude, however there are things like them asking you to put some of the logic of the AR part in javascript files that confuse me.
What are you supposed to do with the javascript, what role does it serves in the overall flow between an Android Activity and the AR?
Also, as a side question, what sense is there to make out of this line in the Android documentation of Wikitude:
architectView.callJavascript(newData('" + poiDataAsJson +")')
at http://developer.wikitude.com/documentation/android. I assume there is a typo or mistake somewhere as newData is not defined anywhere in the Android code.
Thank you!
In order to enable cross platform augmented reality experiences, web technologies were chosen. The application flow is usually that the ArchtiectView is initialised and displayed by the native application. An AR experience is loaded which consists of an html file that executes javascript functions to create the objects in AR.
callJavascript method is used natively to communicate with the loaded AR exprience. It executes the passed javascript in the context of the loaded AR experience. Therefore it can be used to pass POI data as json to a function declared in the Javascript part.
There is an error in the posted java code
architectView.callJavascript(newData('" + poiDataAsJson +")')
should include 2 more double quotes
architectView.callJavascript("newData('" + poiDataAsJson +")'")
This executes the function newData declared globally in javascript and passes 1 parameter, the json encoded poi data.
Disclaimer: I work for Wikitude

Most performant way to execute JS within a webpage in Ruby (HtmlUnit, Celerity, PhantomJS, CasperJS ...)

What's the most performant way to execute JS directly after a HTTP request in JRuby? I know about all the test frameworks like HtmlUnit, Celerity, Capybara + PhantomJS == Poltergeist, CasperJS etc. but they're still test frameworks.
What I need is a simple way to execute all JS code which is included in HTML after fetching the URL e.g. by Net::Http.
First of all, it goes with out saying: DON'T DO THIS IN PRODUCTION!
Executing some script that's been pulled from somewhere on the internet is a recipe for disaster. If you're using it as part of your testing infrastructure, it may be of some use but I'd guess that there's a simpler way to solve your problem.
To answer the more general question, here's how you'd initialize a JavaScript engine bundled with JDK 1.6+ (effectively a cut down version of Rhino, although this will change in Java 8 probably):
import javax.script.ScriptEngineManager
import javax.script.SimpleBindings
manager = ScriptEngineManager.new
engine = manager.getEngineByName("JavaScript")
bindings = SimpleBindings.new
bindings['x'] = 1
engine.eval("print(x)", bindings)
Getting your engine to evaluate any dependencies like jQuery is left as an exercise to the user. Have a look at the javax.script JavaDoc.
If you need more control over the evaluation environment you'll have to use Rhino directly, or wait for Nashorn...

Categories

Resources