dirty Object.prototype - solution proposal

11 views
Skip to first unread message

sgurin

unread,
Aug 9, 2009, 4:11:22 PM8/9/09
to Java2Script
Hello all. I have done a little research about native javascript
objects manipulation in java code.

First let me describe the situation.

For one side, java.util classes rely on a java.lang.Object prototype.
For example, HashMap can be used only with objects that implement
hashCode(), equals(), etc methods. If we remove these methods from
java.lang.Object prototype then the java toolkit (like java.util) will
not work.

In the other side it is often necessary to work with native javascript
objects. (Mainly when working with javascript native toolkits, but
also when we want to use a javascript native object instead of
java.util.HashMap for performance reason).

My principal problem with java2script is that, since j2slib
"contaminates" Object.prototype with those methods in
java.lang.Object, there is no way in a java2script program of
instantiating a pure "non-contaminated" javascript Object (not even
natively). (please correct me about this if I'm wrong)

Well, my approach for resolving this was to modify j2slib.z (java/lang/
Object.js and java/lang/ClassExt.js) so java.lang.Object extends not
from Object but from a subclass. I named this Object subclass,
J2sObject. I also make a little modification in the compiler so "new
Object()" java statement is translated into "new J2sObject()".
This way, Object.prototype is clean, all java Objects extends from
J2sObject (which prototype has java.lang.Object required methods). Now
a javascript statement like "var obj = {}" will create a truly empty
javascript object. A java statement like new Object() will keep
creating "dirty" objects.

What I exactly have done is:

in j2slib.z : define J2sObject class and replace each occurrence of
Object with J2sObject

in net.sf.j2s.core.astvisitors.ASTTypeVisitor: about line 224, A
little hack so "new Object()" java expression is being translated to
"new J2sObject()" javascript expression

I have uploaded nativeObject.zip in this group files (http://
groups.google.com/group/java2script/files) containing mentioned files
and also a test case that reflect the differences. The .java file has
a "//cancerbero_sgx" comment in the changed line. I'm testing this
with java2script sources for eclipse 3.3 (I didn't have the time for
trying eclipse 3.5). All my java2script programs seems to work as
spected with this change, but nevertheless I'm not sure about all the
consequences... I would like to hear what's your opinion about this
proposed solution that will allow:

* instantiate and manipulate non-contaminated native javascript
objects in j2s programs.
* since Object.prototype is not touched, interoperability bugs between
java2script and other javascript toolkits will be reduced (IMHO this
is one of java2script weakest aspects)


Well, I think that was all. Let me think what's your opinion.

Greetings from Uruguay!

Sebastian Gurin

unread,
Aug 10, 2009, 9:30:14 AM8/10/09
to java2...@googlegroups.com
I'm testing a little more the changes a I send in my last post.

* They worked fine with java2script for eclipse 3.5

* No side effects detected yet.

* I successfully integrate various javascript toolkits in java2script programs without any hacks. Toolkits tested where jquery, ext and prototype. They worked fine in a j2s application without any hack. (without my proposed fix, these toolkits report interoperability problems with java2script. In fact it was imposible for me to get prototype or ext working with j2s).

I included toolkit sources with a <script> element in java2script application launcher, section "tail of header", so toolkit sources are loaded *after* j2slib. This seems to be the only requeriment, at least, for prototype.

My following work in this direction will be to integrate a j2s swt application (with my fix) in a portal web application (like www.liferay.com). This is the perfect scenario for detecting j2s interoperability issues because a portal web site often use *many* independent toolkits in the same DOM.

I'm waiting for comments about the proposed solution. If no problems are detected It sould be nice this chance to be included in later j2s release. Please let me know your opinion.

Cheers
--
Sebastian Gurin <sgu...@softpoint.org>

Zhou Renjian

unread,
Aug 10, 2009, 10:13:26 AM8/10/09
to java2...@googlegroups.com
What about String and Number objects, like "hello world", 1234.34

I think we should make a list of Object's methods that breaks other libraries.

In Java2Script, we modified about 10 methods as the following. Can we identify which method breaks which libraries?

/*
 * Invade the Object prototype!
 * TODO: make sure that invading Object prototype does not affect other
 * existed library, such as Dojo, YUI, Prototype, ...
 */
java.lang.Object = Object;

//Clazz.decorateAsType (java.lang.Object, "Object");
//Object.__CLASS_NAME__ = "Object";

Object.getName = Clazz.innerFunctions.getName;

Object.prototype.equal$ = Object.prototype.equals;
Object.prototype.equals = function (obj) {
    if (Object.prototype.equal$ != null) {
        return this.equal$ (obj);
    }
    return this == obj;
};

Object.prototype.ha$hCode = Object.prototype.hashCode;
Object.prototype.hashCode = function () {
    if (Object.prototype.ha$hCode != null) {
        return this.ha$hCode ();
    }
    try {
        return this.toString ().hashCode ();
    } catch (e) {
        var str = ":";
        for (var s in this) {
            str += s + ":"
        }
        return str.hashCode ();
    }
};

Object.prototype.getClass = function () {
    return Clazz.getClass (this);
};

Object.prototype.$clone$ = Object.prototype.clone;
Object.prototype.clone = function () {
    if (Object.prototype.$clone$ != null) {
        return this.$clone$ ();
    }
    var o = new this.constructor ();
    for (var i in this) {
        o[i] = this[i];
    }
    return o;
    //return this;
};

/*
 * Methods for thread in Object
 */
Object.prototype.finalize = function () {};
Object.prototype.notify = function () {};
Object.prototype.notifyAll = function () {};
Object.prototype.wait = function () {};

Object.prototype.to$tring = Object.prototype.toString;
Object.prototype.toString = function () {
    if (this.__CLASS_NAME__ != null) {
        return "[" + this.__CLASS_NAME__ + " object]";
    } else {
        return this.to$tring ();
    }
};


Regards,
Zhou Renjian

--
http://webuzz.im/ Web IMs (G/A/M/Y)
http://j2s.sourceforge.net/ Java2Script

Sebastian Gurin

unread,
Aug 10, 2009, 11:38:57 AM8/10/09
to java2...@googlegroups.com
On Mon, 10 Aug 2009 22:13:26 +0800
Zhou Renjian <zhour...@gmail.com> wrote:

> What about String and Number objects, like "hello world", 1234.34
>

Hello Zhou Renjian. The following is a table of java statements and their corresponding translated javascript statements.

java statement javascript translated statement
Object o = new Object(); var o = new J2sObject(); <-- fixed
Number n = new Integer(5); var n = new Integer (5);
Number n = 5; var n = new Integer (5);
Double d = 3.22 var d = new Double (3.22);
Byte b = 1; var b = new Integer (1);

String s = "hello"; var s = "hello";
Character c = 'c'; var c = ('c').charCodeAt (0);

Also, when passing a primitive type (int) to a method accepting an Object type (Integer) the value is always wrapped into an object in the method call (methodCall(new Integer(2))).

As you can see, the potential problems are with String and Character objects because they are not wrapped into a java object. Nevertheless, this is the current behaviour of java2script and has nothing to do with my fix.

In the case of strings, native javascript String class is used to represent java strings. In core/java/lang/String.js, String.prototype is populated with methods equals, hash, hashCode, etc.

The same seems to occurs with Character representation. It seems that a character is represented with native javascript Number class (var c = ('c').charCodeAt (0) is a javascript number). In core/java/lang/Number.js javascript native Number class ' prototype is populated with methods needed by java.lang.Character and others, (like shortValue,byteValue,intValue,longValue, etc)

So, since Character and String representations are nor java.lang.Object subclasses, this behaviour is not modified by my fix (i hope). In conclusion, I don't see (new) problems with native java objects.

> I think we should make a list of Object's methods that breaks other
> libraries.
>
> In Java2Script, we modified about 10 methods as the following. Can we
> identify which method breaks which libraries?

I will try to make a listing based on my expierience.

Nevertheless, as I said in my original post, the problem with j2s dirty Object.prototype is not only with toolkit integration but also when needing to use "non contaminated" native javascript objects for dialogating with native toolkits. A concrete example. Many tookits accepts a javascript config object for working. For example, the following native javascript code:

function setAttributes(el, attrs) {
for(var i in attrs) {
el.setAttribute(i, attrs[i])
}
}
//call example
setAttributes(document.getElementById("foo"),
{id: "foo2", class: "cl1", type: "checkbox"})

since in java2script programs, Object.prototype contains other fields (like "equals", "hashCode", "toString", etc) a browser exeption will occurs when for example, executing the statement el.setAttribute("toString", function{..})

We can work on fixing each toolkit incompatibility issues, but if we cannot proper dialog with javascript toolkits because of this problem, why we would bother fixing the incompatibilties? That is my point...

I hope I have explained myself well. As always, excuse me for my bad english...
--
Sebastian Gurin <sgu...@softpoint.org>

Sebastian Gurin

unread,
Aug 10, 2009, 1:44:39 PM8/10/09
to java2...@googlegroups.com
new artifact (id=2835043) created for "issue" on https://sourceforge.net/tracker/?func=detail&aid=2835043&group_id=155436&atid=795800 . Patches for eclipse version 3.5 have been submited.
--
Sebastian Gurin <sgu...@softpoint.org>

Zhou Renjian

unread,
Aug 13, 2009, 9:21:50 AM8/13/09
to java2...@googlegroups.com
Java2Script in SVN supports native Object mode now. But it is not enabled by default. You need to add the following line of script before loading "j2slib.z.js":

window["j2s.object.native"] = true;

Some details:
1. new Object(); in Java will be compiled into JavaScript as "new JavaObject();"
2. If there is no window["j2s.object.native"] = true; line, JavaObject === Object, and everything is the same as before.
3. In native Object mode, Function, DOM class, Object's prototype are not modified. But String, Array, Number, Boolean's prototype are modified.

I made some tests on a web messenger application, it seems everything is working OK. I also made some tests for the native Object mode like the following:
                System.out.println (new Object ());
                System.out.println (new Object ().getClass ());
                System.out.println (new Object ().getClass ().getName ());
                System.out.println (Object.class.getName ());

If you want more technical details, please compare SVN history on net.sf.j2s.java.core/src/java/lang/ on revision 1048.


Regards,
Zhou Renjian

--
http://webuzz.im/ Web IMs (G/A/M/Y)
http://j2s.sourceforge.net/ Java2Script


Sebastian Gurin

unread,
Aug 13, 2009, 1:27:39 PM8/13/09
to java2...@googlegroups.com, Zhou Renjian
Thank you very much!! This will really help me to keep integrating java2script with some native javascript toolkits

about the point :

> 3. In native Object mode, Function, DOM class, Object's prototype are not
> modified. But String, Array, Number, Boolean's prototype are modified.

I think the main problem when working with native toolkits is with Object.prototype. SO I think this will solve the problem..

Thanks again!

On Thu, 13 Aug 2009 21:21:50 +0800
--
Sebastian Gurin <sgu...@softpoint.org>
Reply all
Reply to author
Forward
0 new messages