Controlling Inling in GWT compiler
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
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
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
On Wed, Oct 18, 2017 at 1:14 PM, Colin Alworthwrote: > 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
> > 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.