I was able to reduce the problem to the following code:
function getSanitizedHtml(text) { return text.replace(/(a)(?!b)\1/gm, 'c'); }
When called in browser
getSanitizedHtml('aa');
it returns:
c
When called from the Nashorn engine as
String s = String.valueOf(inv.invokeFunction("getSanitizedHtml", "aa"));
it returns:
cc
For me, it looks like backreference \1 , which should point to (a) , instead point to (?!b) , the captured content of which is of zero length and thus matches something.
Equivalent code in Java:
System.out.println(("aa").replaceAll("(a)(?!b)\\1", "c"));
returns the correct result:
c
Conclusion
I am sure this is a bug in the Nashorn engine.
I submitted a bug report and posted it here if it becomes publicly available.
As for your problem, I think your only option is to switch to another JavaScript environment, at least temporarily.
Minimal running examples
JS in browser:
function x(s){return s.replace(/(a)(?!b)\1/gm, 'c');} document.write(x('aa'));
JS in the Nashrhor engine:
[ Ideone ]
Pure Java:
[ Ideone ]
Possible fix
As already mentioned, the only option (at this stage) is to switch to another JavaScript environment.
There are many available and Wikipedia comparison pages . In this example, I chose io.js (I hope you can install it yourself).
If you want to use the pageDown.js file, you will first need to comment on the exports checks and use simple old variables, for example:
/*if (typeof exports === "object" && typeof require === "function") // we're in a CommonJS (eg Node.js) module Markdown = exports; else*/ Markdown = {};
and
/*if (typeof exports === "object" && typeof require === "function") { // we're in a CommonJS (eg Node.js) module output = exports; Converter = require("./Markdown.Converter").Converter; } else {*/ output = Markdown; Converter = output.Converter; //}
(Note that I also changed output = window.Markdown; to output = Markdown; - you should have done the same (Nashorn would have given you an error otherwise), but just forgot to mention this in your question.)
Alternatively, of course, you can use the export system and individual files, but I have no experience with this, so I will do it like this.
Now io.js accepts JavaScript code from stdin, and you can write to stdout via process.stdout.write() , so we can do the following (on the command line):
{ cat pageDown.js; echo 'process.stdout.write(getSanitizedHtml("test `test` test"));'; } | iojs;
And we get the following answer:
<p>test <code>test</code> test</p>
If you need to do this with Java, you can do it like this:
import java.io.*; class Test { public static void main(String[] args) throws Exception { Process p = Runtime.getRuntime().exec("/path/to/iojs"); OutputStream stdin = p.getOutputStream(); InputStream stdout = p.getInputStream(); File file = new File("/path/to/pageDown.js"); byte[] b = new byte[(int)file.length()]; FileInputStream in = new FileInputStream(file); for(int read = 0; read < b.length; read += in.read(b, read, b.length - read));
Pay attention to the semicolon immediately after for (therefore, it only read += in.read(b, read, b.length - read) each time and nothing more), and also note that when calling .close() in a thread is usually optional, since this will be done automatically when the object goes out of scope, stdin.close() must be called stdin.close() , or iojs will continue to wait for input, and p.waitFor() will never return.