GWT 2.7 JsInterop Handle static JavaScript Functions

2,039 views
Skip to first unread message

confile

unread,
Oct 4, 2014, 11:18:08 AM10/4/14
to google-web-tool...@googlegroups.com
Consider the following static JavaScript function: 

THREE.ImageUtils = {
       loadTexture: function (url) { ... }

}

The way I use to create the static function with JsInterop is to create an interface for ImageUtils and then create an inner abstract class MyStatic which contains the static methods implemented with JSNI.

Here is an example of the above class: 

@JsType
public interface ImageUtils {

public static abstract class MyStatic {
 
public static native Texture create(String url) /*-{
return new $wnd.THREE.ImageUtils.loadTexture(url);
}-*/;
}

}


I don't think this is the best solution. Is there a better way to handle static functions with JsInterop?

Ray Cromwell

unread,
Oct 4, 2014, 2:24:19 PM10/4/14
to google-web-toolkit-contributors
Yes, but it will require Java8, which allows interfaces to contain
static methods. Here's how you'll do it soon when the Java8 stuff
lands:

@JsType
public interface ImageUtils {
public static Texture loadTexture(String url) { return
js("$wnd.THREE.ImageUtils.loadTexture($0)", url); }
}

ImageUtils.loadTexture(url);
> --
> You received this message because you are subscribed to the Google Groups
> "GWT Contributors" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to google-web-toolkit-co...@googlegroups.com.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/google-web-toolkit-contributors/8f6cf42a-2910-4536-a2f7-1ae2d55422ac%40googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
Message has been deleted

Cristian Rinaldi

unread,
Oct 4, 2014, 6:29:16 PM10/4/14
to google-web-tool...@googlegroups.com
+Ray Cromwell:
  Suppose the following definition: 

@JsType(prototype = "jQuery")
public interface JQueryElement {
    
JQueryElement append(JQueryElement element);

    
@JsProperty
    
JQueryElement html();

    
void data(String key, String value);
    
    
Object val();
    
    
void on(String event, com.workingflows.js.jscore.client.api.Function<?,?> fn);
    
    
void attr(String attr, Object value);
}

Now suppose that there is an element called SwitchElement, the item is a JQueryElement but has a particual implementation of a method, for example: 

 public class SwitchElement extends JavaScriptObject {

    
protected SwitchElement() {
    
}

    
public final native boolean getState()/*-{
     return this.bootstrapSwitch("state");
     }-*/
;

    
public final native void setState(boolean state)/*-{
     this.bootstrapSwitch("state", state);
     }-*/
;
}

The problem is, if the JQueryElement interface is implemented, all methods must be implemented. In fact, the implementation of JQueryElement is performed by the compiler, and I have no access to that implentación.

1) The solution can be: define an Java8 interface with methods implemented by default? 

2) It is possible to access a Prototype implementation of JQueryElement, by example:

public class SwitchElement extends JQueryElement.Prototype{
 
protected SwitchElement() {
 
}

 
public final native boolean getState()/*-{
 return this.bootstrapSwitch("state");
 }-*/
;

 
public final native void setState(boolean state)/*-{
 this.bootstrapSwitch("state", state);
 }-*/
;

}

But for this, it is necessary to use APT or the JsType generation process, is performed by APT. 
I'm right, or very far from reality. 

:)

Ray Cromwell

unread,
Oct 5, 2014, 2:32:26 AM10/5/14
to google-web-toolkit-contributors
Using default methods in Java8 is exactly how we plan to allow
specifying method bodies without using JSOs. We are also going to
introduce a new annotation, @JsFinal to declare these methods final
(which you can't do on interfaces) to make it a compile time error for
subclasses to override them.

Why? One of the reasons why JSOs are efficient is that they are not
polymorphic, and essentially turn into static method calls, e.g.

getState() is rewritten as getState(SwitchElement this$static) /*-{
return this$static.bootstrapSwitch("state"); }-*/; which is
inlineable by the compiler.

Polymorphic methods are not inlineable and if there is a concrete
implementor, it forces the compiler to insert a trampoline, e.g
.

@JsType
interface JsArray<T> {
default <T> get(int x) { return js("this[$0]", x); }
}

If we didn't have @JsFinal, and someone did class Blah implements
JsArray { ... }, it would slow down every single JsArray call in the
entire program, because the compiler has to emit code like this:

jsArray.get ? jsArray.get(i) : this[i];

That is, it has to check to see if the method is implemented and call
it, otherwise fall back to the default.


This is why the full JsInterop will require Java8, because it makes
syntax so much better, and without it, things get verbose and
boilerplatey.

Java8 support is very close to landing. After that, a bunch of
JsInterop changes will go in. Then Elemental 2.0 will follow on top of
that which implements all of the code browser APIs you see at
html5index.org
>> > email to google-web-toolkit-co...@googlegroups.com.
> --
> You received this message because you are subscribed to the Google Groups
> "GWT Contributors" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to google-web-toolkit-co...@googlegroups.com.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/google-web-toolkit-contributors/51be727d-0003-425b-9040-bd3c8529ddd1%40googlegroups.com.

confile

unread,
Oct 8, 2014, 1:31:49 PM10/8/14
to google-web-tool...@googlegroups.com
@Ray Cromwell will the @Entry annotation for JSInterop be included in GWT 2.7? I think this is essential to handle errors raised by JavaScript.


>> > To view this discussion on the web visit
>> >
>> > https://groups.google.com/d/msgid/google-web-toolkit-contributors/8f6cf42a-2910-4536-a2f7-1ae2d55422ac%40googlegroups.com.
>> > For more options, visit https://groups.google.com/d/optout.
>
> --
> You received this message because you are subscribed to the Google Groups
> "GWT Contributors" group.
> To unsubscribe from this group and stop receiving emails from it, send an

Goktug Gokdogan

unread,
Oct 8, 2014, 2:47:07 PM10/8/14
to google-web-toolkit-contributors
We are not really making a release for JsInterop for 2.7 and it is not meant to be used in production and missing a lot of stuff.
The released stuff is just something that people can play with and give some feedback.

To unsubscribe from this group and stop receiving emails from it, send an email to google-web-toolkit-co...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/google-web-toolkit-contributors/83bedee9-2b9c-46ec-a20b-c1c68d7f55f9%40googlegroups.com.

confile

unread,
Oct 28, 2014, 11:33:16 AM10/28/14
to google-web-tool...@googlegroups.com
What is the difference in using the following?

@JsType(prototype="Window") and @JsType 

It does not become very clear from the documentation. 

Here is the interface I implemented: 

@JsType(prototype="Window")

public interface MyWindow {


public static abstract class Statics {

public static native MyWindow create() /*-{

var w = $wnd;

return w;

}-*/;

}

void alert(String msg);

}


When I want to use the interface I have to do: MyWindow w = MyWindow.Statics.create();

I also would expect that the following should work too: MyWindow w = GWT.create(MyWindow.class);

The compiler throws an error in the later case: 

 [ERROR] Line 46: Rebind result 'test.client.MyWindow' must be a class

         Unification traversed 735 fields and methods and 538 types. 7 are considered part of the current module and 7 had all of their fields and methods traversed.

      [ERROR] Compiler returned false


Two questions: 

1. When do I use or do I not use the prototype and isNative attribute of @JsType?

2. Do I use the correct way to instantiate a JSInterop Interface?





Am Sonntag, 5. Oktober 2014 08:32:26 UTC+2 schrieb Ray Cromwell:
>> > To view this discussion on the web visit
>> >
>> > https://groups.google.com/d/msgid/google-web-toolkit-contributors/8f6cf42a-2910-4536-a2f7-1ae2d55422ac%40googlegroups.com.
>> > For more options, visit https://groups.google.com/d/optout.
>
> --
> You received this message because you are subscribed to the Google Groups
> "GWT Contributors" group.
> To unsubscribe from this group and stop receiving emails from it, send an

Ray Cromwell

unread,
Oct 28, 2014, 12:06:47 PM10/28/14
to google-web-toolkit-contributors
GWT.create() doesn't work to create Js interfaces. It's part of the
GWT deferred binding system and can only be bound to concrete Java
subtypes. (GWT.create uses the 'new' operator)

JsInterop is going to move towards Java8 syntax for the use case you
describe, e.g

@JsType
interface Window {
static Window get() { return js("window"); }
>> >> > google-web-toolkit-co...@googlegroups.com.
>> >> > To view this discussion on the web visit
>> >> >
>> >> >
>> >> > https://groups.google.com/d/msgid/google-web-toolkit-contributors/8f6cf42a-2910-4536-a2f7-1ae2d55422ac%40googlegroups.com.
>> >> > For more options, visit https://groups.google.com/d/optout.
>> >
>> > --
>> > You received this message because you are subscribed to the Google
>> > Groups
>> > "GWT Contributors" group.
>> > To unsubscribe from this group and stop receiving emails from it, send
>> > an
>> > email to google-web-toolkit-co...@googlegroups.com.
> --
> You received this message because you are subscribed to the Google Groups
> "GWT Contributors" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to google-web-toolkit-co...@googlegroups.com.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/google-web-toolkit-contributors/e40493a9-b890-47b0-ad31-5cd4e9c28a46%40googlegroups.com.

confile

unread,
Oct 28, 2014, 12:17:54 PM10/28/14
to google-web-tool...@googlegroups.com
Okay great. But what is the difference between the following?

@JsType(prototype="Window") and @JsType 

Also could you please explain when to use isNative = true?


>> >> > To view this discussion on the web visit
>> >> >
>> >> >
>> >> > https://groups.google.com/d/msgid/google-web-toolkit-contributors/8f6cf42a-2910-4536-a2f7-1ae2d55422ac%40googlegroups.com.
>> >> > For more options, visit https://groups.google.com/d/optout.
>> >
>> > --
>> > You received this message because you are subscribed to the Google
>> > Groups
>> > "GWT Contributors" group.
>> > To unsubscribe from this group and stop receiving emails from it, send
>> > an
>> > To view this discussion on the web visit
>> >
>> > https://groups.google.com/d/msgid/google-web-toolkit-contributors/51be727d-0003-425b-9040-bd3c8529ddd1%40googlegroups.com.
>> >
>> > For more options, visit https://groups.google.com/d/optout.
>
> --
> You received this message because you are subscribed to the Google Groups
> "GWT Contributors" group.
> To unsubscribe from this group and stop receiving emails from it, send an

Ray Cromwell

unread,
Oct 28, 2014, 2:37:15 PM10/28/14
to google-web-tool...@googlegroups.com
@JsType(prototype="Window") means that "x instanceof Window" will return false if the underlying object isn't a Window. That is, the GWT compiler generates a JS instanceof operator with the specified prototype.

Otherwise, @JsType interfaces are treated like JavaScriptObject overlay types as far as castability/instanceof is concerned.

isNative is just documentation for now, but says that the underlying prototype is a browser built-in as opposed to a hand written user supplied JS prototype. Native prototypes have restrictions that pure-JS ones don't.

@JsType(prototype="...") will also trigger an annotation processor in the future that generates a stub _Prototype for extending, e.g.

@JsType(prototype="HTMLDivElement")
interface HTMLDivElement extends HTMLElement { ... }

will generate a 

@PrototypeOfJsType(HTMLDivElement.class)
class HtmlDivElement_Prototype extends HTMLElement_Prototype { ... }

This makes it possible to subclass JS objects, e.g.

class MyDivElement extends HTMLDivElement_Prototype { ... }


To unsubscribe from this group and stop receiving emails from it, send an email to google-web-toolkit-co...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/google-web-toolkit-contributors/94cce332-a8c7-4790-98a8-e752a5fd3dd8%40googlegroups.com.

Goktug Gokdogan

unread,
Oct 28, 2014, 9:06:37 PM10/28/14
to google-web-toolkit-contributors
Today finally I had some free time to think about the rest of the issues (extending, constructors, static functions etc). I'm going to make another attempt to make those pieces work better and less boilerplatey. Will update the thread if I find something that is worth sharing.

confile

unread,
Oct 29, 2014, 9:20:48 AM10/29/14
to google-web-tool...@googlegroups.com
@Ray Cromwell thank you for your answer. One last question regarding the creation of JSInterop objects. 

Is it @JsType(prototype="SomeJsObject") or  @JsType(prototype="$wnd.SomeJsObject") ?

Consider an interface

@JsType
interface Test {
  void do();
}

How do I instantiate such an interface? The only way I see is be using a static inner class on the interface which contains a static JSNI method that returns a new instance. This seems to be a little bit complicated. Is this the correct way to do?
 

Jens

unread,
Oct 29, 2014, 9:45:33 AM10/29/14
to google-web-tool...@googlegroups.com
Consider an interface

@JsType
interface Test {
  void do();
}

How do I instantiate such an interface? 

For now you need to use a JSNI factory method. May it be in a static inner class or a dedicated factory class for all your JsTypes.

With GWT 3.0 (and Java8 support) you can use a static factory method on the interface which uses GWT.jsni() or GWT.js() or whatever name that special GWT method will have. So in GWT 3.0 it will probably look like:

@JsType 
interface Test {
   static Test create() { return GWT.js("new Test()"); } 
   void do();



-- J. 

confile

unread,
Oct 29, 2014, 10:04:05 AM10/29/14
to google-web-tool...@googlegroups.com
thank oyu Jens. What about my first question: 

Is it @JsType(prototype="SomeJsObject") or  @JsType(prototype="$wnd.SomeJsObject") ? 

Best
Michael

Ray Cromwell

unread,
Oct 29, 2014, 11:44:42 AM10/29/14
to google-web-toolkit-contributors
Whether you use $wnd.SomeJsObject or SomeJsObject depends on the following:
1) whether you want 'instanceof' to only work on objects that come
from the host page
2) whether or not you're going to extend/subtype JS objects

In most cases, you want "$wnd.SomeJsObject", however there are cases
where you don't

1) if you loaded some hand written JS into 'window' instead of $wnd
2) if you are referring to inbuilt native JS objects like Window or
HTMLDivElement

If you do the following

@JsType(prototype="$wnd.Window")
interface Window {
...
}

Window w = someIframe.window();

Then w instanceof Window => false. Why? Because the GWT compiler will
emit "w instanceof $wnd.Window", but your checking for Window objects
from ANY location.


So you see, a prefix of $wnd leads to an ABSOLUTE instanceof operator.
If you don't specify $wnd, then the instanceof check is relative. So
for example, it will just check if your constructor is 'Window', no
matter which context where it came from.

In general, native DOM elements == no $wnd prefix, JS libraries loaded
in host page == $wnd prefix
> --
> You received this message because you are subscribed to the Google Groups
> "GWT Contributors" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to google-web-toolkit-co...@googlegroups.com.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/google-web-toolkit-contributors/a8612613-de28-4413-926f-ed97086436fa%40googlegroups.com.

confile

unread,
Oct 29, 2014, 1:01:29 PM10/29/14
to google-web-tool...@googlegroups.com
Thank you Ray. This is a good explanation. It should be added to the docs.

Best
Michael

Goktug Gokdogan

unread,
Oct 29, 2014, 1:37:58 PM10/29/14
to google-web-toolkit-contributors
Just FYI, we were planning to drop the $wnd and isNative last time we discussed about it..

To unsubscribe from this group and stop receiving emails from it, send an email to google-web-toolkit-co...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/google-web-toolkit-contributors/89359bef-175d-4a96-9362-787fed32888d%40googlegroups.com.

Cristian Rinaldi

unread,
Oct 30, 2014, 11:27:17 AM10/30/14
to google-web-tool...@googlegroups.com
I have been testing JsInterop for a while, and is very promising ... 
The issue of static functions is something I have asked, and we have to wait Java support 8 and the new JSNI too. 
@confile, if you want to look at a couple of projects on which I am working:


 probably when Elemental 2.0 has been implemented, gwt-jscore will not be necessary. 
 
 gwt-used-playgroud use jscore and a simple implementation of gwt-jquery, with suport of Event and Promise...

 For create object I use for the moment a Factory Class, and for emulate static method, by example, Object.observe, I have a two interface, see: JS Factory Class and Browser Factory Class, if not the best solution, but until this all implemented works for me.

Hope you helps.

confile

unread,
Oct 30, 2014, 5:32:35 PM10/30/14
to google-web-tool...@googlegroups.com
@Christian: 

1. What does gwt-jscore do?

2. as Ray Cromwell suggested in this post "In general, native DOM elements == no $wnd prefix, JS libraries loaded in host page == $wnd prefix "

   This means your JQueryElement should be: 

@JsType(prototype = "$wnd.jQuery")
public interface JQueryElement { ... }

What do you think?

confile

unread,
Oct 31, 2014, 2:41:35 AM10/31/14
to google-web-tool...@googlegroups.com
The documentation said that you should not use JSInterop in production. Could you specify what can be used in production and what part cannot?


Thank you
Michael

Am Mittwoch, 29. Oktober 2014 16:44:42 UTC+1 schrieb Ray Cromwell:

Cristian Rinaldi

unread,
Oct 31, 2014, 7:15:48 AM10/31/14
to google-web-tool...@googlegroups.com
1) gwt-jscore is a small Implementation of DOM Element and JS functionality standard, this is a test, This project will not be Necessary When is Implemented Elements 2.0, but for the moment I need this. 

Many things about this project can change as conforming JsInterop. 

For example: 
   The callback functions are complex (syntactically) to create, with the lambda sintaxys will be much simpler. 
   The factories disappear, thanks to static methods on interfaces. 
   They may have particular implementations based on the prototypes generated by APT (hopefully :)) 
   They can have default methods on interfaces .. 
   All thanks to java 8. 

   If I'm wrong about something please: @Ray Cromwell or/and @Goktug, correct me. 

2) as saying "ray" you're right on the gwt-jquery project.

Thanks!


El sábado, 4 de octubre de 2014 12:18:08 UTC-3, confile escribió:
Reply all
Reply to author
Forward
0 new messages