11
votes

How to clean SSJS (Server Side Javascript) in Domino server after someone used javascript prototype in a nsf?

Mark Roden discovered a huge weakness in XPages SSJS: (thanks to David Leedy for tell me about this and show me the article).

If you have the following SSJS code:

var dummyObj = {}
dummyObj.prototype.NAME = "Johann"

XPages SSJS doesn't care that you uses var (var means the variable must be local) and it makes dummyObj.NAME visible in the whole server with the value Johann. So if another nsf in the same server uses a var with the same name it inherits the whole prototype:

var dummyObj = {}
println(dummyObj.NAME) /*prints "Johann" */ 

This is a huge bug (one that makes unreliable XPages SSJS IMO). Even if you don't use prototype at all, if someone else in his application do something like this:

String.prototype.split = function(){ return "I broke this method" }

It will broke all applications in the same server that uses the innocent split().

So, the question is: if someone "by mistake" writes the following SSJS (XPages Server Side Javascript) in a NSF:

String.prototype.split = function(){ return "I broke this method" }

How can I fix String.prototype.split() to his original value?

As Mark Roden said, restarting HTTP task doesn't fix it.

///////////////////////////////////////////////////////////

Edit 1: Why I think this is a huge bug:

I'm a Javascript fan but IMHO @MarkyRoden has discovered a huge bug in SSJS. Shims and polyfills aren't really the main problem. Eval is known to be a bad practice but the prototype object is a fundamental element of basic Javascript. It's the standard and preferred way to add methods to Javascript classes, it's also needed for inheritance and all kind of OOP stuff. So you will need some kind of namespace at server level in order to avoid collisions. All this is really bad but the huge problem is that just a line of code in one application can broke all applications in a server. Yes, you can trust in your developers but one of them can write a bad line by mistake and also a Domino server can have hundreds of applications from different software vendors. Set the responsability in code reviews is not a reliable enought procedure. Maybe it's time to have a real javascript engine in SSJS, like V8, Spidermonkey, Chakra or Rhino. As a workaround, I'm thinking in something like Tommy Valand's idea with Rhino in SSJS.

Edit 2: It's even worse. You can do things like:

prototype.importPackage = null

or

prototype.Array = null

As you can see in @SvenHasselbach's article: http://hasselba.ch/blog/?p=1371

Edit 3: IBM: you told me I could use SSJS. COME ONE! PLEASE FIX THIS, it's AWFUL. Please let's officially report this issue to IBM.

2
Regarding your EDIT comments. I think the key takeaway is that SSJS is NOT "true JavaScript". So you need to manage your expectations of SSJS accordingly. Especially with OOP. You can't really do objects in SSJS. If you put code in your functions then they're not Serializable. Honestly I believe that the real workaround is to use Java rather then SSJS.David Leedy
It's one more reason to you use as much as possible Java and EL in XPages development instead of SSJS.Knut Herrmann
I agree with Knut and David. Consider also what Jesse Gallagher did some years ago to enable you to code Ruby in XPages: XPages is a JSF-based platform, running in a Java Virtual Machine, so to enable people to code Ruby, Jesse had to write a parsing engine to allow Java to parse Ruby. The Rhino parser is doing the same thing - it's using a Java class to tell Java how to parse Rhino. So unless I'm misunderstanding things, you can't have a real javascript engine in SSJS, because you'll be using a Java parser for that javascript engine. Debugging may also be a challenge.Paul Stephen Withers
I would strongly discourage anyone trying to use String.prototype to fix deficiencies in the core APIs (JavaScript or Java). There are a myriad of Java classes designed to add missing functionality in Java (and so SSJS). com.ibm.commons.util.StringUtil is in-built with XPages. With some workarounds you can add in org.apache.commons.lang.StringUtils intec.co.uk/two-java-libraries-to-know-for-xpages-development. importPackage() allows you to use any Java class in SSJS as long as it's accessible to the server.Paul Stephen Withers

2 Answers

8
votes

You can reset the SSJS interpreter with the following Java code:

FacesContextExImpl fc = (FacesContextExImpl) FacesContextExImpl.getCurrentInstance();
UIViewRootEx2 uiRoot = (UIViewRootEx2) fc.getViewRoot();
JSContext jsContext = uiRoot.getJSInterpreter().getJSContext();
jsContext.getRegistry().init(jsContext);

This reinitializes the registry and all prototype functions.

EDIT: Changed the declaration of fc to the correct type.

EDIT 2: Here is the SSJS version:

var uiRoot = facesContext.getViewRoot();
var jsContext = uiRoot.getJSInterpreter().getJSContext();
var reg = jsContext.getRegistry();
reg.init( jsContext );

Does I understand you correctly, that you want to clean up the SSJS interpreter to avoid a collision with your own prototype extension? Just to clarify the answer above: This reinitializes the SSJS interpreter once. And only once. You have to do this over and over again, because directly after reinitializing, another application on the server can overwrite the prototype functionality again. That's why this is not a real solution, it is an answer to your initial question.

It will have interessting consequences if another application will do the same while your code tries to use your extension...

3
votes

try to do a Restart Task Http instead tell http restart will not do a full restart of the http task