konsoletyper / teavm

Compiles Java bytecode to JavaScript, WebAssembly and C
https://teavm.org
Apache License 2.0
2.64k stars 265 forks source link

Minification doesn't skip variable name 'if', causing "Uncaught SyntaxError: Unexpected token if" #397

Open PokingUrsa opened 5 years ago

PokingUrsa commented 5 years ago

Minification uses variable names like 'ab', 'bb', etc. When enough variables are created, it creates a variable named 'if', which is a reserved word and prevents the application from loading. Instead, the console displays this message:

Uncaught SyntaxError: Unexpected token if classes.js:2060

We are using TeaVM version 0.6.0-dev-674

konsoletyper commented 5 years ago

Do you mean local variables in function? How did you manage to get that many local variables in a single function?

PokingUrsa commented 5 years ago

It happened when we added a new method to an existing interface and implementation. The method did not have many parameters. The interface already had a bunch of methods.

The workaround was to disable minification. That increases the size of classes.js by about 7X, however.

PokingUrsa commented 5 years ago

This is the generated code where you can see the variable name "if".

function BTe(a,b,c,d,e){var f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,ab,bb,cb,db,eb,fb,gb,hb,ib,jb,kb,lb,mb,nb,ob,pb,qb,rb,sb,tb,ub,vb,wb,xb,yb,zb,ac,bc,cc,dc,ec,fc,gc,hc,ic,jc,kc,lc,mc,nc,oc,pc,qc,rc,sc,tc,uc,vc,wc,xc,yc,zc,ad,bd,cd,dd,ed,fd,gd,hd,id,jd,kd,ld,md,nd,od,pd,qd,rd,sd,td,ud,vd,wd,xd,yd,zd,ae,be,ce,de,ee,fe,ge,he,ie,je,ke,le,me,ne,oe,pe,qe,re,se,te,ue,ve,we,xe,ye,ze,af,bf,cf,df,ef,ff,gf,hf,if,jf,kf,lf,mf,nf,of,pf,qf,rf,sf,tf,uf,vf,wf,xf,yf,zf,ag,bg,cg,dg,eg,fg,gg,hg,ig,jg,kg,lg,mg,ng,og,pg,qg,rg, sg,tg,ug,vg,wg,xg,yg,zg,ah,bh,ch,dh,eh,fh,gh,hh,ih,jh,kh,lh,mh,nh,oh,ph,qh,rh,sh,th,uh,vh,wh,xh;

konsoletyper commented 5 years ago

Ok, but how comes you have that much local variables?

konsoletyper commented 5 years ago

Did you use 'FULL' optimization level?

PokingUrsa commented 5 years ago

I'm using 'ADVANCED' optimization. I'l try full.

I'm trying to figure out why there are so many variables by looking in the non-minified JS. It's a big project though, so it's taking a little while to find it.

konsoletyper commented 5 years ago

No, don't use FULL, it can generate even more local variables. Is your project proprietary?

PokingUrsa commented 5 years ago

I think this is the corresponding non-minified JavaScript.

This happened when we added a new method in our Route interface for a big proprietary Flavour project. We have lots of methods and many with path parameters. Do these get turned in to a big regex? Maybe we hit a limit on the regex complexity.

function otfri_Matcher5_feed(var$0, var$1, var$2, var$3, var$4) {
    var var$5, var$6, var$7, var$8, var$9, var$10, var$11, var$12, var$13, var$14, var$15, var$16, var$17, var$18, var$19, var$20, var$21, var$22, var$23, var$24, var$25, var$26, var$27, var$28, var$29, var$30, var$31, var$32, var$33, var$34, var$35, var$36, var$37, var$38, var$39, var$40, var$41, var$42, var$43, var$44, var$45, var$46, var$47, var$48, var$49, var$50, var$51, var$52, var$53, var$54, var$55, var$56, var$57, var$58, var$59, var$60, var$61, var$62, var$63, var$64, var$65, var$66, var$67, var$68, var$69, var$70, var$71, var$72, var$73, var$74, var$75, var$76, var$77, var$78, var$79, var$80, var$81, var$82, var$83, var$84, var$85, var$86, var$87, var$88, var$89, var$90, var$91, var$92, var$93, var$94, var$95, var$96, var$97, var$98, var$99, var$100, var$101, var$102, var$103, var$104, var$105, var$106, var$107, var$108, var$109, var$110, var$111, var$112, var$113, var$114, var$115, var$116, var$117, var$118, var$119, var$120, var$121, var$122, var$123, var$124, var$125, var$126, var$127, var$128, var$129, var$130, var$131, var$132, var$133, var$134, var$135, var$136, var$137, var$138, var$139, var$140, var$141, var$142, var$143, var$144, var$145, var$146, var$147, var$148, var$149, var$150, var$151, var$152, var$153, var$154, var$155, var$156, var$157, var$158, var$159, var$160, var$161, var$162, var$163, var$164, var$165, var$166, var$167, var$168, var$169, var$170, var$171, var$172, var$173, var$174, var$175, var$176, var$177, var$178, var$179, var$180, var$181, var$182, var$183, var$184, var$185, var$186, var$187, var$188, var$189, var$190, var$191, var$192, var$193, var$194, var$195, var$196, var$197, var$198, var$199, var$200, var$201, var$202, var$203, var$204, var$205;
    var$5 = var$0.$state;
konsoletyper commented 5 years ago

I believe this commit should solve your problem, at least until you reach 500 local variables. I'll also look through the code generated by Flavour routing

konsoletyper commented 5 years ago

Ah, I see. Flavour does not generate lots of variables. It's TeaVM tries to apply global value numbering and eliminates duplicates of constants. Though it can be useful when there's multiple usages of a large constant within one method, this case seems to be quite rare. In more usual case this optimization makes worse. So I'll try to turn off GVN for constants.

PokingUrsa commented 5 years ago

Thanks! I will get that commit and see the result.

konsoletyper commented 5 years ago

I made one more commit that reduces number of variables in state machine generated from regexp.