sun.org.mozilla.javascript.internal.NativeObject vs org.mozilla.javascript.NativeObject - rhino

I am really stuck at this now..
Essentially I have a Java Map, which I would like to pass it to a Javascript Code, so that in my JS code I can use dot notation to refer the keys in this Map. ( I know I can serialize the map into JSON and deserialize it back and pass it into JS, but I don't like that ) I have this piece of the unit code
#Test
public void mapToJsTest() throws Exception{
Map m = Maps.newHashMap();
m.put("name", "john");
NativeObject nobj = new NativeObject();
for (Object k : m.keySet()) {
nobj.defineProperty((String)k, m.get(k), NativeObject.READONLY);
}
engine.eval("function test(obj){ return obj.name;}");
Object obj = ((Invocable)engine).invokeFunction("test", nobj);
Assert.assertEquals(obj, "john");
}
If I am using
org.mozilla.javascript.NativeObject
then the test won't pass,
However, if I am using
sun.org.mozilla.javascript.internal.NativeObject
then the test will pass.
However, we all know that we shouldn't rely on these internal classes, and when I deploy my code on the server side, trying to access
this internal class will cause other problems.
So how do I achieve this with just "org.mozilla.javascript.NativeObject"?
BTW, I am using Rhino
ScriptEngine engine = new ScriptEngineManager().getEngineByName("JavaScript");
For Nashorn, it is much easier, I can pass Map directly into JS code.

Unless you're stuck with older JDK (jdk7 or below) for some reason, I'd recommend moving to jdk8u. You've ES 5.1 compliant JS implementation (Nashorn) that is bundled with JDK8+.

Related

Possible to create Graal native function callable from C without isolate?

I'd like to create a library, written in Java, callable from C, with simple method signatures:
int addThree(int in) {
return in + 3;
}
I know it's possible to do this with GraalVM if you do a little dance and create an Isolate in your C program and pass it in as the first parameter in every function call. There is good sample code here.
The problem is that the system I'm writing for, Postgres, can load C libraries and call functions in them, but I would have to create a wrapper function in C that would wrap every function I wanted to expose. This really limits the value of being able to slap something together in Java and use it in Postgres directly. I'd have to do something like this:
int myPublicAddThreeFunction(int in) {
graal_isolatethread_t *thread = NULL;
if (graal_create_isolate(NULL, NULL, &thread) != 0) {
fprintf(stderr, "error on isolate creation or attach\n");
return 1;
}
return SomeClassName_addThree_big_random_string_here(thread, in);
}
Is there a way, in Java alone, to expose a simple C function? I'm thinking I could create the isolate in a static method that gets loaded once on startup, somehow set it as the current isolate, and have the Java method just use it. Haven't been able to figure it out, though.
Also, it would be real nice not to have to append a big random string to every function name.

Switching from Rhino to Nashorn

I have a Java 7 project which makes a lot of use of Javascript for scripting various features. Until now I was using Rhino as script engine. I would now like to move to Java 8, which also means that I will replace Rhino by Nashorn.
How compatible is Nashorn to Rhino? Can I use it as a drop-in replacement, or can I expect that some of my scripts will not work anymore and will need to be ported to the new engine? Are there any commonly-used features of Rhino which are not supported by Nashorn?
One problem is that Nashorn can no longer by default import whole Java packages into the global scope by using importPackage(com.organization.project.package);
There is, however, a simple workaround: By adding this line to your script, you can enable the old behavior of Rhino:
load("nashorn:mozilla_compat.js");
Another problem I ran into is that certain type-conversions when passing data between java and javascript work differently. For example, the object which arrives when you pass a Javascript array to Java can no longer be cast to List, but it can be cast to a Map<String, Object>. As a workaround you can convert the Javascript array to a Java List in the Javascript code using Java.to(array, Java.type("java.util.List"))
To use the importClass method on JDK 8, we need to add the following command:
load("nashorn:mozilla_compat.js");
However, this change affect the execution on JDK 7 (JDK does not gives support to load method).
To maintain the compatibility for both SDKs, I solved this problem adding try/catch clause:
try{
load("nashorn:mozilla_compat.js");
}catch(e){
}
Nashorn can not access an inner class when that inner class is declared private, which Rhino was able to do:
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
public class Test {
public static void main(String[] args) {
Test test = new Test();
test.run();
}
public void run() {
ScriptEngineManager factory = new ScriptEngineManager();
ScriptEngine engine = factory.getEngineByName("JavaScript");
Inner inner = new Inner();
engine.put("inner", inner);
try {
engine.eval("function run(inner){inner.foo(\"test\");} run(inner);");
} catch (ScriptException e) {
e.printStackTrace();
}
}
private class Inner {
public void foo(String msg) {
System.out.println(msg);
}
}
}
Under Java8 this code throws following exception:
javax.script.ScriptException: TypeError: kz.test.Test$Inner#117cd4b has no such function "foo" in <eval> at line number 1
at jdk.nashorn.api.scripting.NashornScriptEngine.throwAsScriptException(NashornScriptEngine.java:564)
at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:548)
I noticed that Rhino didn't have a problem with a function called 'in()' (although 'in' is a reserved JavaScript keyword).
Nashorn however raise an error.
Nashorn cannot call static methods on instances! Rhino did this, therefore we had to backport Rhino to Java 8 (Here's a short summary: http://andreas.haufler.info/2015/04/using-rhino-with-java-8.html)
Nashorn on Java8 does not support AST. So if you have Java code that inspects the JS source tree using Rhino's AST mechanism , you may have to rewrite it (using regex maybe) once you port your code to use Nashorn.
I am talking about this API https://mozilla.github.io/rhino/javadoc/org/mozilla/javascript/ast/AstNode.html
Nashorn on Java9 supports AST though.
One feature that is in Rhino and not Nashorn: exposing static members through instances.
From http://nashorn-dev.openjdk.java.narkive.com/n0jtdHc9/bug-report-can-t-call-static-methods-on-a-java-class-instance : "
My conviction is that exposing static members through instances is a
sloppy mashing together of otherwise separate namespaces, hence I
chose not to enable it.
I think this is deeply wrong. As long as we have to use two different constructs to access the same java object and use package declarations unnecessarily in javascript, code becomes harder to read and write because cognitive load increases. I will rather stick to Rhino then.
I have not found a workaround for this obvious "design bug" yet.

Conditional imports / code for Dart packages

Is there any way to conditionally import libraries / code based on environment flags or target platforms in Dart? I'm trying to switch out between dart:io's ZLibDecoder / ZLibEncoder classes and zlib.js based on the target platform.
There is an article that describes how to create a unified interface, but I'm unable to visualize that technique not creating duplicate code and redundant tests to test that duplicate code. game_loop employs this technique, but uses separate classes (GameLoopHtml and GameLoopIsolate) that don't seem to share anything.
My code looks a bit like this:
class Parser {
Layer parse(String data) {
List<int> rawBytes = /* ... */;
/* stuff you don't care about */
return new Layer(_inflateBytes(rawBytes));
}
String _inflateBytes(List<int> bytes) {
// Uses ZLibEncoder on dartvm, zlib.js in browser
}
}
I'd like to avoid duplicating code by having two separate classes -- ParserHtml and ParserServer -- that implement everything identically except for _inflateBytes.
EDIT: concrete example here: https://github.com/radicaled/citadel/blob/master/lib/tilemap/parser.dart. It's a TMX (Tile Map XML) parser.
You could use mirrors (reflection) to solve this problem. The pub package path is using reflection to access dart:io on the standalone VM or dart:html in the browser.
The source is located here. The good thing is, that they use #MirrorsUsed, so only the required classes are included for the mirrors api. In my opinion the code is documented very good, it should be easy to adopt the solution for your code.
Start at the getters _io and _html (stating at line 72), they show that you can load a library without that they are available on your type of the VM. Loading just returns false if the library it isn't available.
/// If we're running in the server-side Dart VM, this will return a
/// [LibraryMirror] that gives access to the `dart:io` library.
///
/// If `dart:io` is not available, this returns null.
LibraryMirror get _io => currentMirrorSystem().libraries[Uri.parse('dart:io')];
// TODO(nweiz): when issue 6490 or 6943 are fixed, make this work under dart2js.
/// If we're running in Dartium, this will return a [LibraryMirror] that gives
/// access to the `dart:html` library.
///
/// If `dart:html` is not available, this returns null.
LibraryMirror get _html =>
currentMirrorSystem().libraries[Uri.parse('dart:html')];
Later you can use mirrors to invoke methods or getters. See the getter current (starting at line 86) for an example implementation.
/// Gets the path to the current working directory.
///
/// In the browser, this means the current URL. When using dart2js, this
/// currently returns `.` due to technical constraints. In the future, it will
/// return the current URL.
String get current {
if (_io != null) {
return _io.classes[#Directory].getField(#current).reflectee.path;
} else if (_html != null) {
return _html.getField(#window).reflectee.location.href;
} else {
return '.';
}
}
As you see in the comments, this only works in the Dart VM at the moment. After issue 6490 is solved, it should work in Dart2Js, too. This may means that this solution isn't applicable for you at the moment, but would be a solution later.
The issue 6943 could also be helpful, but describes another solution that is not implemented yet.
Conditional imports are possible based on the presence of dart:html or dart:io, see for example the import statements of resource_loader.dart in package:resource.
I'm not yet sure how to do an import conditional on being on the Flutter platform.

Is there anything like "CheckSum" in Dart (on Objects)?

For Testing purposes I'm trying to design a way to verify that the results of statistical tests are identical across versions, platforms and such. There are a lot things that go on that include ints, nums, dates, Strings and more inside our collections of Objects.
In the end I want to 'know' that the whole set of instantiated objects sum to the same value (by just doing something like adding the checkSum of all internal properties).
I can write low level code for each internal value to return a checkSum but I was thinking that perhaps something like this already exists.
Thanks!
_swarmii
This sounds like you should be using the serialization library (install via Pub).
Here's a simple example to get you started:
import 'dart:io';
import 'package:serialization/serialization.dart';
class Address {
String street;
int number;
}
main() {
var address = new Address()
..number = 5
..street = 'Luumut';
var serialization = new Serialization()
..addRuleFor(address);
Map output = serialization.write(address, new SimpleJsonFormat());
print(output);
}
Then depending on what you want to do exactly, I'm sure you can fine tune the code for your purpose.

Common Language Runtime detected an invalid program error in unit testing

I have the following code
this.SafeUpdate(rate, Guid.Parse(import.myGuid), c => c.myGuid);
SafeUpdate basically takes the parsed guid value and applies it to the myGuid property on the rate object. This works fine from my front end, but throws the "CLR detected..." error when run in a unit test. What's odd is the same statement for DateTime.Parse and int.Parse works fine. It just fails for Guid and decimals. I don't believe the error is with the parsing (it has the correct parsed value when extracted into a separate variable). I don't believe it's the mocking either as the statement works fine for all other types other than guid and decimal. Any ideas?
We experienced a similar error yesterday on our build server. Our exception was thrown by the ReadObject() method of a DataContractSerializer.
System.InvalidProgramException: Common Language Runtime detected an invalid program.
at System.Xml.EncodingStreamWrapper..ctor(Stream stream, Encoding encoding)
at System.Xml.XmlUTF8TextReader.SetInput(Stream stream, Encoding encoding, XmlDictionaryReaderQuotas quotas, OnXmlDictionaryReaderClose onClose)
at System.Xml.XmlDictionaryReader.CreateTextReader(Stream stream, Encoding encoding, XmlDictionaryReaderQuotas quotas, OnXmlDictionaryReaderClose onClose)
at System.Xml.XmlDictionaryReader.CreateTextReader(Stream stream, XmlDictionaryReaderQuotas quotas)
at System.Runtime.Serialization.XmlObjectSerializer.ReadObject(Stream stream)
We've written a console app that does just this one thing. It runs without error, but fails in a simple unit test. We are using Gallio/MbUnit 3.4.11.0 for our test framework with a target of .net 4.0.
using System;
using System.IO;
using System.Runtime.Serialization;
using MbUnit.Framework;
namespace TestApp
{
[TestFixture]
class Program
{
static void Main()
{
FooBar();
Console.ReadKey();
}
public static void FooBar()
{
var type = typeof(string);
var foo = "foo";
using (var stream = new MemoryStream())
{
var serializer = new DataContractSerializer(type);
serializer.WriteObject(stream, foo);
stream.Seek(0, SeekOrigin.Begin);
var deserializer = new DataContractSerializer(type);
var bar = deserializer.ReadObject(stream);
Console.WriteLine(bar);
}
}
[Test]
public void Test()
{
FooBar();
}
}
}
The application runs fine, but the test throws. Strangely, this test passes on my dev box but fails on our build server as well as the dev box of a coworker. Clearly, there is something different about my dev box that allows the test to pass, but I have not located that difference yet.
Update 1
The version of System.dll on my dev box is 4.0.30319.296 but on the build server and the dev box of my coworker it is 4.0.30319.1001. System.Xml.dll and System.Runtime.Serialization.dll are identical at 4.0.30319.1, however.
Update 2
A quick google search for "4.0.30319.1001" returns this security update, http://support.microsoft.com/kb/2742595, which was applied to both our build server and the dev box of my coworker, but not my dev box. I uninstalled the update on the build server, rebooted, and the issue went away! I guess Microsoft doesn't have a unit test for this one yet. :-)

Resources