I have been successfully using my code with the javascript library in the ANTLR javascript target in a few browsers, but now I want to use Rhino on the server and I am having some trouble. I have some simple java code that references the Rhino 1.7R2 release's js-14.jar file.
Context context = Context.enter();
Scriptable scope = context.initStandardObjects();
context.evaluateReader(scope, new FileReader("C:\\antlr3-all.js"), "antlr", 1, null);
This fails with an EcmaError whose message is:
TypeError: Cannot call property namespace in object [JavaPackage org.antlr].
It is not a function, it is "object". (antlr#259)
The javascript line that it's referring to is:
org.antlr.namespace("org.antlr.runtime.tree");
This org.antlr.namespace was declared as a function earlier in the file, so I am not sure what to think of this. I also don't see that "namespace" is a reserved word in javascript or in Rhino in particular.
Here's the declaration of org.antlr.namespace at line 56:
org.antlr.namespace = function() {
var a=arguments, o=null, i, j, d;
for (i=0; i<a.length; i=i+1) {
d=a[i].split(".");
o=org.antlr.global;
// ANTLR is implied, so it is ignored if it is included
for (j=0; j<d.length; j=j+1) {
o[d[j]]=o[d[j]] || {};
o=o[d[j]];
}
}
return o;
};
The ANTLR javascript target page mentions that Rhino is a tested platform, so I am thinking that I might just be misusing Rhino. Does anyone have any tips?
TypeError: Cannot call property
namespace in object [JavaPackage
org.antlr].
It takes your org.antlr as a java package and tries to make a call to the object namespace. So defining the function like this does not work.
Defining each part of the functions namespace by itself worked for me:
org = new function() {//Define the structure one piece at a time
this.antlr = new function(){
this.namespace = '';
return this;
};
return this;
};
org.antlr.namespace = function() {print('Help'); return 0;}
Sorry that I can't give a more detailed answer, I don't know mutch about javascript^^.
I guess that since org and org.antlr are undefined you can't assign to them.
Related
To the downvoters - this is a legitimate question. Please take the time to examine it before assuming I'm mixing up my languages like some kind of programming newb!
I need to know if it's possible to import a Java object (specifically, an enum class) in a Typescript script.
I've googled but haven't found anything.
The ErrorCodeAuthority is for having custom, standardized errors thrown from our service for each known error with set messages (some parameterized, some not), http status codes, etc defined in one place.
In our javascript code we have
var JavaErrorCodeAuthority = Java.type("com.domain.ErrorCodeAuthority");
Is it possible to do the same in Typescript?
Edit based on answer below
I've declared the following:
declare module Java {
export enum ErrorCodeAuthority {
ENTITY_NOT_FOUND,
HTTP_VERB_NOT_SUPPORTED,
BAD_REQUEST,
//...
}
export function type(arg: "com.domain.ErrorCodeAuthority"): ErrorCodeAuthority;
export function type(arg: string): any;
}
var JavaErrorCodeAuthority = Java.type("com.domain.ErrorCodeAuthority");
and I'm attempting to use the new type as follows:
export class HttpFailResult extends HttpResult {
constructor(public errorCode : Java.ErrorCodeAuthority, public userParams? : UserParam[]) {
super(errorCode.httpStatus.value(), errorCode.toString());
}
}
I'm getting the following error when I try to use grunt to compile to js:
error TS2339: Property 'httpStatus' does not exist on type 'ErrorCodeAuthority'.
(For reference, the super HttpResult is an object that contains a number http code and astringbody. HttpStatus, in the Java enum, is of typeorg.springframework.http.HttpStatus`).
I tried removing the export function type(arg: "com.domain.ErrorCodeAuthority"): ErrorCodeAuthority; line but that didn't change the exception.
EDIT 2
We're running all of this inside a nashorn container if that makes a difference
Is it possible to do the same in Typescript?
Yes. With 1c, you can just write
let JavaErrorCodeAuthority = com.domain.ErrorCodeAuthority
And there will be auto-completion on each level of packages.
Yes, if you already did this in JavaScript you can use the code by creating a definition file for it and port it to TypeScript.
An example might be like this:
declare module Java {
export enum ErrorCodeAuthority {
item1,
item2
}
export function type(arg: "com.domain.ErrorCodeAuthority"): ErrorCodeAuthority;
export function type(arg: string): any;
}
var JavaErrorCodeAuthority = Java.type("com.domain.ErrorCodeAuthority");
The enum and the first type function with the "com.domain.ErrorCodeAuthority" is optional but it gives you better typeinfo when passed in that particular string. Note the declare module part doesn't generate any code and you can add it to a .ts or .d.ts file. More info about creating a definition file can be found here: https://github.com/Microsoft/TypeScript/wiki/Writing%20Definition%20Files
EDIT
after the info from the comments I hope this code below will better suite your need.
This has the downside that it isn't usable in a switch statement but in this case I think it is better to see the java enum as a module (or class was possible to). This might not be 100% correctly modelled but hopefully it gives you some extra idea's. Just a small side note, I find your case very interesting and challenging!
declare module Java {
interface ErrorCodeValue {
toString(): string;
value(): number;
}
module ErrorCodeAuthority {
var ENTITY_NOT_FOUND: IErrorCodeAuthority;
var HTTP_VERB_NOT_SUPPORTED: IErrorCodeAuthority;
var BAD_REQUEST: IErrorCodeAuthority;
}
interface IErrorCodeAuthority {
httpStatus: ErrorCodeValue;
}
export function type(arg: "com.domain.ErrorCodeAuthority"): typeof ErrorCodeAuthority;
export function type(arg: string): any;
}
export class HttpResult {
constructor(code: number, description: string) {
}
}
export class HttpFailResult extends HttpResult {
constructor(public errorCode: Java.IErrorCodeAuthority, public userParams? :any[]) {
super(errorCode.httpStatus.value(), errorCode.toString());
}
}
var JavaErrorCodeAuthority = Java.type("com.domain.ErrorCodeAuthority");
new HttpFailResult(JavaErrorCodeAuthority.BAD_REQUEST, null);
I'm currently using the javax implementation of Rhino. By default Rhino uses a wrapper to return Java objects. Does Nashorn have similar behaviour or does it return JavaScript objects by default?
Thanks
Looks like it tries its best to return sensible objects. Using this code, then changing the XXX:
ScriptEngineManager mgr = new ScriptEngineManager();
ScriptEngine engine = mgr.getEngineByName("nashorn");
engine.eval("function test() { return XXX; };");
Object result = ((Invocable)engine).invokeFunction("test");
System.out.println(result.getClass().getName());
Yields:
return 'hello world' = java.lang.String
return 1 = java.lang.Integer
return { name: 'Hello' } = jdk.nashorn.api.scripting.ScriptObjectMirror
Looks like that, even though the Java objects can be used within the JS code, it still references Java Objects (although they show up as function objects so there must be a wrapper there), we can't treat them as Javascript objects:
//"import"
var StringTokenizer = java.util.StringTokenizer;
print(typeof StringTokenizer);
var st = new StringTokenizer("this is a test");
print(typeof st);
java.util.StringTokenizer.prototype.name = 'myST';
print(st.name);
And here's the result:
testObj.js:9 TypeError: Cannot set property "name" of undefined
Now Javascript objects will be loaded as "jdk.nashorn.internal.scripts.JO" instances.
*If you want to test the above code more easily, just create an alias for your JDK's jjs (Nashorn Interpreter), e.g., if you create a file called test.js, you can run the program with:
$ jjs test.js
Mac OS = alias jjs=’/Library/Java/JavaVirtualMachines/jdk1.8.0.jdk/Contents/Home/jre/bin/jjs’
Windows = Define an environment variable called ‘JAVA8_HOME’ and point to your jdk8 folder, then you can invoke jjs by running this command:
> “%JAVA8_HOME%\jre\bin\jjs” test.js
Maybe my question is simple to solve for you, but I'm sitting here for a few hours with following problem (and I have already searched for it):
I have a Java method which has JavaScript code inside (JSNI from Google's GWT) to set key bindings for the code editor CodeMirror2. When I want to compile with GWT, I'm getting an error from the GWT compiler:
[ERROR] Line 195: invalid label
> "F11": function() {
My code looks like this:
public final native void setExtraKeysCallback() /*-{
this.extraKeys = function(editor) {
"F11": function() {
// do something
},
"Esc": function() {
// do something
}
};
}-*/;
The really strange thing is that in native JS the extra keys are working with this syntax?! I think the problem is the label syntax, how could I change this to work with GWT?
Thanks, leX
You seem to be mixing object literal syntax:
{ "key": value, "key2", value2 }
… with function expression syntax:
function () { }
Decide if you are trying to create a simple object or a function (or a function that returns a simple object) and use the appropriate syntax for that.
So far I only see closure in javascript:
var name=...;
$(..).onclick(function() {
//here I can reference to name
});
Does this feature exist in c/c++/java/PHP?
If exists,one hello world example available?
As for PHP, you can enable access to a specific variable inside a closure method like this:
$xVar = "var";
$closure = function() use ($xVar) {
echo $xVar;
}
$closure();
And it's also possible to alter this variable inside the closure:
$xVar = "var";
$closure = function($newVar) use (&$xVar) {
$xVar = $newVar;
}
$closure("new var content");
C no, as functions aren't first-class objects.
C++ not yet, but it does with the upcoming standard (commonly referred to as C++0x), with so called lambda expressions:
std::string name;
auto mylambda = [&](){ std::cout << name; };
// ^ automatically reference all objects in the enclosing scope.
C++11 has closures, as does PHP. Im not sure about Java.
At one point, closures (Project Lambda) were going to be part of Java 7, but they are currently listed as "Deferred to Java 8 or later".
http://en.wikipedia.org/wiki/Closure_%28computer_science%29#PHP
For PHP
<?php
$greet = function($name)
{
printf("Hello %s\r\n", $name);
};
$greet('World');
$greet('PHP');
?>
PHP has those too, since 5.3. They're not as flexible (in that you can't use $this), but still very useful.
Lisp and its dialects also have closures.
For C, they are available as a non-standard extension called blocks.
I am embedding some javascript in a Java application using Rhino. I am following the example on the Rhino website, executing a script by calling the Context's evaluateString method and passing the actual script in as a String.
I have a whole bunch of existing javascript code that I would like to make use of. I don't want to concatenate it all into an enormous String and pass it in to evaluateString. I would rather be able to load the code in so that I can call it from the code that I do pass into evaluateString (kind of like the AddCode method works in Microsoft's scripting control). I would like to add code like I can currently add variables by using the ScriptableObject.putProperty method.
Is there a way to do this? Can someone provide a code snippet or a link to the documentation. Thanks!
From the documentation and examples it looks like references to previously evaluated objects are controlled by scopes.
Context context = Context.enter();
try {
ScriptableObject scope = context.initStandardObjects();
Object out = Context.javaToJS(System.out, scope);
ScriptableObject.putProperty(scope, "out", out);
context.evaluateString(scope,
"function foo() { out.println('Hello, World!'); }", "<1>", 1, null);
context
.evaluateString(scope, "function bar() { foo(); }", "<2>", 1, null);
context.evaluateString(scope, "bar();", "<3>", 1, null);
} finally {
Context.exit();
}
(Rhino 1.7 release 2)
I know some people use Rhino directly to get the latest version, but the Java 6 implementation can evaluate scripts like this:
ScriptEngine engine = new ScriptEngineManager().getEngineByExtension("js");
engine.eval("function foo() { println('Hello, World!'); }");
engine.eval("function bar() { foo(); }");
engine.eval("bar();");
In my code I had that need (utility scripts and such), and I just simply concatenated them together in a giant StringBuilder and evaled it (Java 6). Its the only way since javascript can't do (without Java wrapper objects) otherJSScript.someUsefulFunction().