Controlling Inling in GWT compiler

2017-10-17 Thread Peter Donald
Hi,

So I am trying to figure out a way to control inlining in GWT compiler and
potentially if it will be compatible with J2CL. My motivation is that I
want to build type-safe builders that are compiled away at runtime. The
idea is to compile something like

new InputBuilder().type( InputType.checkbox ).className( "foo"
).child( "Hello" ).build()

to

React.createElement('input', { className: 'foo' }, 'Hello')

And browsing the code I thought I could make use of @ForceInline and
@HasNoSideEffects in appropriate places to control the inlining. The goal
would essentially be to move most of the building code into caller which
allow the data flow analyzer to zap it into a nice compact form. But I can
not seem to get it to work.

It is unclear whether I am using it wrong or it just won't work and reading
through the compiler source code is proving to be slow way to understand
the problem.

@ForceInline does not seem to force inlining but instead raises an error if
code is not inlined? Am I understanding this correctly? Certainly adding
the annotation to all the places that I wanted that occur causes a error
like "Function X is marked as @ForceInline but it could not be inlined".
Reading through the JsInliner source code has not enlightened me why.

So more code less talk. Here is the example I have been working with

https://gist.github.com/realityforge/5c9c04cd86dc6ada80f05558d609a3ae

Next question is around optimisation of the new jsinterop code. It seems
that GWT compiler does not work particularly well and something like

final JsPropertyMapOfAny prop = JsPropertyMap.of();
prop.set( "a", 1 );
prop.set( "b", 2 );
prop.set( "c", 3 );

will not produce an object literal.

So do you think this is an achievable goal with GWT2, what about in
J2CL? Any suggestions on how I could achieve this?

BTW I know using things like @ForceInline and @HasNoSideEffects is
"dangerous" and unsupported but I am comfortable with the impact I would
have on compile size/time. (Once worked on JikesRVM which is a JVM written
in Java which has similar annotations and similar tradeoffs - see
http://www.jikesrvm.org/JavaDoc/org/vmmagic/pragma/package-summary.html)

-- 
Cheers,

Peter Donald

-- 
You received this message because you are subscribed to the Google Groups "GWT 
Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to google-web-toolkit+unsubscr...@googlegroups.com.
To post to this group, send email to google-web-toolkit@googlegroups.com.
Visit this group at https://groups.google.com/group/google-web-toolkit.
For more options, visit https://groups.google.com/d/optout.


Re: Custom Events and Elements with Elemental 2

2017-10-17 Thread James Nelson
It is possible to create web components with "fake" ES2015 classes built 
out of raw javascript.

https://github.com/WeTheInternet/xapi/blob/master/gwt/components/src/main/java/xapi/components/impl/WebComponentBuilder.java#L108

Note that the library above depends on a custom fork of Gwt that is not 
being released until after 2.8.2 goes out, however, the code for assembling 
custom web components does not actually depend on any of the magic I've 
added to the Gwt compiler (official release will not be dependent on my 
fork; I hope to deprecate / upstream everything I've had to do to it over 
the years). 

I also intend to remove all the ugly jsni to make it compatible with j2cl / 
gwt3... But, that bit I've linked to is the secret sauce for assembling a 
correct "extension" of HTMLElement.  In theory, you can define your custom 
element using a builder that attaches your lifecycle callbacks (created / 
attached / detached / attributeChanged), plus any extra methods / fields 
you want, and then the rest of your code can use a @JsType(isNative=true, 
name="MyCustomElement", namespace = JsPackage.GLOBAL) interface that 
defines how you want to access the custom element and/or cast directly to 
an Element.  This work is very imperative and copy-pasta, so I've also 
created a nice DSL for defining custom elements using... an xml-like, 
json-like, css-like extension of the java language (totally optional 
though; you can still use the builder directly).

The end goal (very near to completion) is that you can define your custom 
component with a bit of xml-like syntax, plugging in java methods wherever 
you please, and it will generate all the builder-y boilerplate and Element 
interface for you.  It is likely that I can actually make it extend 
HTMLElement directly as a class, and just define trampoline methods in the 
builder to call into the java code, but I have not had time to explore this 
option yet.

I have not "officially" released this library, but it will be making an 
official debut soon.  You should be able to use it earlier, if you are 
interested in some beta testing :-) (message me @ ja...@vertispan.com so I 
can add you to my beta testers label).

The result is a custom element that has widget-like lifecycle callbacks (we 
are toying with the idea of actually making widget use something like this 
under the hood to survive in Gwt 3).  The one *big* gotcha is how the 
createdCallback works.  Per the web component spec, you may *not* write or 
*read* any elements attributes or children to a custom element in its 
constructor.  I have worked up a...  slightly scary "RunSoon" 
implementation which will ensure that the callback is fired as soon as 
possible after construction (but this can be hard, since setting innerHTML 
from plain javascript is an important part of interopability with JS/HTML). 
 I won't go into many details here, but, in practice, this ugliness can be 
hidden behind some cleverly generated code (which will lazy-init either at 
your command, whenever attached, or at the end of the current javascript 
event loop).

The very first iteration of these custom components actually took a js type 
interface, directly bound all default methods to the custom element 
definition (via code generator), and allowed you to use that interface in 
both java and javascript.  It actually worked quite well, but, 
unfortunately, that was for V0 of web component spec, and the ES2015 class 
syntax requirement (and other, imho, design mistakes) made it untenable for 
V1 (current version of web components).



To use web components with GWT, you do have to install a polyfill 
(webcomponentjs, with only a couple slight mods I had to make) for older 
browsers / browsers that do not have web components enabled by default. 
 The fact GWT runs in an iframe makes instanceof fail spectacularly, so I 
had to change usage of it to typeofs.


Shameless plug: Myself, Colin Alworth and Justin Hickman have started a 
company based on selling GWT support contracts called Vertispan.  While I 
am happy to share open source code and some pointers with you for free at 
any time, if you are interested in hiring any expertise to help you 
directly, you should email my aforementioned work account. :-)


Final note: Shadow DOM is completely optional, and you should likely avoid 
it unless you really need it (for encapsulation and css barriers mostly). 
 It... gets a bit hinky especially with polyfills and sane event bubbling, 
so if you are new to web components, only move on to shadow DOM if you've 
tried something without it, and actually need it (for example, to isolate 
component internals, or to avoid re-rendering piles of layout logic when 
all you want is your server to send elements with semantic significance).  


On Friday, October 13, 2017 at 6:25:00 AM UTC-7, Thomas Broyer wrote:
>
> Web Components require using ES2015 class syntax, so you would need some 
> trickery make them work from GWT (see 
> 

Re: Custom Events and Elements with Elemental 2

2017-10-17 Thread James Nelson
Also, feel free to ignore the bit of insanity around virtual shadow roots. 
 That's just something I built because an older version of webcomponentjs 
was severely borked, and I needed to...  make my own virtual shadow DOM 
implementation.  I have allowed it to survive after upstream bug was fixed 
because I also added V0-like behavior for slotting elements in shadow DOM 
that was (wrongly, imho) replaced in V1 spec with ugly manual slotting.

To make a long story short, in V0, you can do this (note, #shadow-root is 
not a real tag name, it's just there to say there is a shadow root with 
elements in it):


  <#shadow-root>

  
   I am rendered in shadow root because I match 
selector
  I am not rendered because I do not match selector


In V1, you have to do this:


  <#shadow-root>

  
   I am rendered in shadow root because my slot 
attribute matches slot name
  I am not rendered because I do not match slot
  I am also not rendered



In both cases, a content without a select attribute and a slot without a 
name will render all unslotted elements, but even that gets... hairy with 
the polyfill, when you are nesting components inside each other.


Anyway, once again: I would strongly recommend avoiding all use of shadow 
root unless you really enjoy debugging bleeding edge bugs. :D

On Tuesday, October 17, 2017 at 7:48:25 PM UTC-7, James Nelson wrote:
>
> It is possible to create web components with "fake" ES2015 classes built 
> out of raw javascript.
>
>
> https://github.com/WeTheInternet/xapi/blob/master/gwt/components/src/main/java/xapi/components/impl/WebComponentBuilder.java#L108
>
> Note that the library above depends on a custom fork of Gwt that is not 
> being released until after 2.8.2 goes out, however, the code for assembling 
> custom web components does not actually depend on any of the magic I've 
> added to the Gwt compiler (official release will not be dependent on my 
> fork; I hope to deprecate / upstream everything I've had to do to it over 
> the years). 
>
> I also intend to remove all the ugly jsni to make it compatible with j2cl 
> / gwt3... But, that bit I've linked to is the secret sauce for assembling a 
> correct "extension" of HTMLElement.  In theory, you can define your custom 
> element using a builder that attaches your lifecycle callbacks (created / 
> attached / detached / attributeChanged), plus any extra methods / fields 
> you want, and then the rest of your code can use a @JsType(isNative=true, 
> name="MyCustomElement", namespace = JsPackage.GLOBAL) interface that 
> defines how you want to access the custom element and/or cast directly to 
> an Element.  This work is very imperative and copy-pasta, so I've also 
> created a nice DSL for defining custom elements using... an xml-like, 
> json-like, css-like extension of the java language (totally optional 
> though; you can still use the builder directly).
>
> The end goal (very near to completion) is that you can define your custom 
> component with a bit of xml-like syntax, plugging in java methods wherever 
> you please, and it will generate all the builder-y boilerplate and Element 
> interface for you.  It is likely that I can actually make it extend 
> HTMLElement directly as a class, and just define trampoline methods in the 
> builder to call into the java code, but I have not had time to explore this 
> option yet.
>
> I have not "officially" released this library, but it will be making an 
> official debut soon.  You should be able to use it earlier, if you are 
> interested in some beta testing :-) (message me @ ja...@vertispan.com so 
> I can add you to my beta testers label).
>
> The result is a custom element that has widget-like lifecycle callbacks 
> (we are toying with the idea of actually making widget use something like 
> this under the hood to survive in Gwt 3).  The one *big* gotcha is how 
> the createdCallback works.  Per the web component spec, you may *not* write 
> or *read* any elements attributes or children to a custom element in its 
> constructor.  I have worked up a...  slightly scary "RunSoon" 
> implementation which will ensure that the callback is fired as soon as 
> possible after construction (but this can be hard, since setting innerHTML 
> from plain javascript is an important part of interopability with JS/HTML). 
>  I won't go into many details here, but, in practice, this ugliness can be 
> hidden behind some cleverly generated code (which will lazy-init either at 
> your command, whenever attached, or at the end of the current javascript 
> event loop).
>
> The very first iteration of these custom components actually took a js 
> type interface, directly bound all default methods to the custom element 
> definition (via code generator), and allowed you to use that interface in 
> both java and javascript.  It actually worked quite well, but, 
> unfortunately, that was for V0 of web component spec, and the ES2015 class 
> syntax requirement (and other, imho, design 

Re: Controlling Inling in GWT compiler

2017-10-17 Thread Peter Donald
On Wed, Oct 18, 2017 at 1:14 PM, Colin Alworth  wrote:

> For the first one, chaining methods has the unfortunate detail that each
> method has a return value, which the next object is called on. To my
> knowledge, there is no optimization in the compiler which currently can
> undo the presence of the return value, and recognize that the method
> returns "this" (or a param, some other easily aliased value) as a special
> case.
>

Ok. I think I have been spoilt by working on the JVM for so long. I just
assumed that GWT and/or Closure could do escape analysis and inline
non-escaping objects into the current scope. I assume this is not the case
then? It would explain the resulting code.

Lets assume that "str" was only one char, since we are compiling after all,
> 40 chars for the "idiomatic" js version, 37 chars for staticified version,
> 50 for the "inlined" version.
>

Hmm ... I guess I was too down in the trenches to think high level enough.
I like this idea. In my context the following is the lay of the land

*Current Java Input: *
new InputBuilder().type( "checkbox" ).className( "foo" ).child( "Hello"
).build()

*Naive Javascript output (71 chars)*
React.createElement('input',{type:'checkbox',className:'foo'},'Hello')

*Current GWT output: (lots)*
function up(a){var b,c;c=a.b;b=a.a;return
$wnd.React.createElement.apply(null,[hw,c].concat(b))}
function vp(a,b){a.a.concat(b);return a}
function wp(a){a.b['className']='foo';return a}
function xp(a){a.b['type']='checkbox';return a}
a=up(vp(wp(xp(new yp)),'Hello'))

*Non-reusable GWT output: (82 chars)*
function wp(a){a.b['className']='foo';return a}
a=up(vp(wp(xp(new yp)),'Hello'))

*Hypothetical Less Naive ES3 Javascript output (45 chars)*
ab(dc,{'type':xs,'className':'foo'},'Hello')

*Hypothetical Less Naive ES6 Javascript output (36 chars)*
ab(dc,{[eg]:xs,[gg]:'foo'},'Hello')

So even if you strip the potentially reusable code out of the current GWT
output the non reusable chunk is still 82 characters which is 9 characters
more than the most naive javascript implementation. However a more
optimized javascript implementation that aliases the methods and constants
comes in at 36 chars. However I think that uses some ES6 features ([gg] as
key).

I still suspect (having not experimented with it) that the "return this"
> aliasing will still confuse matters, at least without deliberate code in
> closure to handle it. At least with strings, it isn't smart enough:
>

Right.


> I played with a similar optimization in GWT a few years ago, but ended up
> not finishing it. It mostly dealt with trying to deal with compile-time
> strings and avoiding runtime regular expressions on them, but I abandoned
> it. If there is enough interest in this, I think I at least have the
> working knowledge to give it a shot... but lets be sure that we get
> something out of it.
>

To be perfectly honest I have no idea on the state of either the GWT or
closure optimizer so could not rightly say but I suspect that without an
escape analysis this may be a very difficult optimization to get right and
probably a lot of work ;) I remember spending weeks  (months?) trying to
get some similar optimizations working in a past life and I mostly failed !
But if you want to try don't let me stop you.

create({a:'asdf',b:1,c:false});
> create(c(b(a({},'asdf'),1),false);
> Literal is 31 bytes, chained is 35, so two bytes per setter (plus the cost
> of the setter method, which can then be reused). Might not be worth more
> than a few hours of time, but then again, the work could lead to other
> unexpected benefits...
>


I think the optimization would offer a fairly significant improvement but I
also think it is a massive amount of work. Maybe time would be better spent
elsewhere.

Anyhoo interesting idea - thanks for your reply.

-- 
Cheers,

Peter Donald

-- 
You received this message because you are subscribed to the Google Groups "GWT 
Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to google-web-toolkit+unsubscr...@googlegroups.com.
To post to this group, send email to google-web-toolkit@googlegroups.com.
Visit this group at https://groups.google.com/group/google-web-toolkit.
For more options, visit https://groups.google.com/d/optout.


Re: Controlling Inling in GWT compiler

2017-10-17 Thread Peter Donald
>
> I still suspect (having not experimented with it) that the "return this"
> aliasing will still confuse matters, at least without deliberate code in
> closure to handle it. At least with strings, it isn't smart enough:
> https://closure-compiler.appspot.com/home#code%3D%252F%252F%2520%253D%
> 253DClosureCompiler%253D%253D%250A%252F%252F%2520%2540compilation_level%
> 2520ADVANCED_OPTIMIZATIONS%250A%252F%252F%2520%2540output_file_name%
> 2520default.js%250A%252F%252F%2520%253D%253D%
> 252FClosureCompiler%253D%253D%250A%250A%252F%252F%2520ADD%
> 2520YOUR%2520CODE%2520HERE%250Afunction%2520A()%257Bthis.
> str%253D%27%27%257D%253B%250AA.prototype.b%2520%253D%
> 2520function(string)%2520%257Bthis.str%252B%253Dstring%
> 253B%2520return%2520this%253B%257D%253B%250AA.prototype.c%
> 2520%253D%2520function()%2520%257Breturn%2520this.str%257D%
> 253B%250A%250Aconsole.log(new%2520A().b(%2522a%2522).b(
> window.prompt()).b(%2522b%2522).c())%253B
> I'm having a hard time modeling this in plain JS to get it to treat the
> constructor like an object, so as to correctly handle the "return this".
> Might be better as a @JsOverlay...
>

I should note I tried lots of different ways to try and get this working
and came up with nothing. If you do figure it out - I would love to see
what it looks like ;)

-- 
Cheers,

Peter Donald

-- 
You received this message because you are subscribed to the Google Groups "GWT 
Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to google-web-toolkit+unsubscr...@googlegroups.com.
To post to this group, send email to google-web-toolkit@googlegroups.com.
Visit this group at https://groups.google.com/group/google-web-toolkit.
For more options, visit https://groups.google.com/d/optout.