trullock / NUglify

NUglify is a HTML, JavaScript and CSS minification Library for .NET (fork of AjaxMin + new features)
Other
396 stars 78 forks source link

Three.js minification - Uncaught SyntaxError: Invalid left-hand side in assignment #363

Open mattscotty opened 1 year ago

mattscotty commented 1 year ago

Latest version, trying to minify Three.js v146 but the issue is also present on the latest version 154.

I'm not sure how to phrase it but I think the issue is being caused because the function is being removed and directly called because it's only referenced in one place. Apologies, I'm not sure how to reference this kind of multiple variable assignment (I'd love to know).

Original code, line 10403; ({ sizeLods: this._sizeLods, lodPlanes: this._lodPlanes, sigmas: this._sigmas } = _createPlanes(_lodMax)); this._blurMaterial = _getBlurShader(_lodMax, width, height);

Minified using latest Nuglify (v1.20.7), (also includes the full function), crashes browser with "Uncaught SyntaxError: Invalid left-hand side in assignment" ({sizeLods:this._sizeLods,lodPlanes:this._lodPlanes,sigmas:this._sigmas})=function(n){const i=[],r=[],u=[];let t=n;const f=n-3+ok.length;for(let e=0;e<f;e++){const a=Math.pow(2,t);r.push(a);let y=1/a;e>n-4?y=ok[e-n+4-1]:0===e&&(y=0);u.push(y);const k=1/(a-2),f=-k,o=1+k,tt=[f,f,o,f,o,o,f,f,o,o,f,o],c=6,h=6,p=3,w=2,b=1,d=new Float32Array(p*h*c),g=new Float32Array(w*h*c),nt=new Float32Array(b*h*c);for(let n=0;n<c;n++){const t=n%3*2/3-1,i=n>2?0:-1,r=[t,i,0,t+2/3,i,0,t+2/3,i+1,0,t,i,0,t+2/3,i+1,0,t,i+1,0];d.set(r,p*h*n);g.set(tt,w*h*n);const u=[n,n,n,n,n,n];nt.set(u,b*h*n)}const l=new s;l.setAttribute("position",new v(d,p));l.setAttribute("uv",new v(g,w));l.setAttribute("faceIndex",new v(nt,b));i.push(l);t>4&&t--}return{lodPlanes:i,sizeLods:r,sigmas:u}}(u);

Three.min.js, works; ({sizeLods:this._sizeLods,lodPlanes:this._lodPlanes,sigmas:this._sigmas}=function(t){const e=[],i=[],n=[];let r=t;const s=t-4+1+Rn.length;for(let a=0;a<s;a++){const s=Math.pow(2,r);i.push(s);let o=1/s;a>t-4?o=Rn[a-t+4-1]:0===a&&(o=0),n.push(o);const l=1/(s-2),c=-l,h=1+l,u=[c,c,h,c,h,h,c,c,h,h,c,h],d=6,p=6,m=3,f=2,g=1,v=new Float32Array(m*p*d),x=new Float32Array(f*p*d),_=new Float32Array(g*p*d);for(let t=0;t<d;t++){const e=t%3*2/3-1,i=t>2?0:-1,n=[e,i,0,e+2/3,i,0,e+2/3,i+1,0,e,i,0,e+2/3,i+1,0,e,i+1,0];v.set(n,m*p*t),x.set(u,f*p*t);const r=[t,t,t,t,t,t];_.set(r,g*p*t)}const y=new Di;y.setAttribute("position",new Mi(v,m)),y.setAttribute("uv",new Mi(x,f)),y.setAttribute("faceIndex",new Mi(_,g)),e.push(y),r>4&&r--}return{lodPlanes:e,sizeLods:i,sigmas:n}}(n))

The only difference I can see is that in Nuglify, the initial variables method is being closed before the function is called, wheras the three.min.js isn't and is pulling the function in before closing (apologies for the terminology, happy to be corrected).

trullock commented 1 year ago

Im gonna need you to provide a minimum viable repro of the problem.

As youve done, minify your source and get the bad minified output. Remove input code and keep minifying to and keep getting bad output. As you remove input code it doesnt need to be functional, just syntactically valid. Keep going until you get the minimun amount of input code that produces a broken output, then i can help you investigate

:)

mattscotty commented 1 year ago

Fair enough, hows this;

Original;

class TEST {
    constructor() { }

    abc() {
        const _varA = 0;

        return { _varA };
    }

    def() {
        ({ varA: this._varA } = abc());
    }
}

Minified;

class TEST{constructor(){}abc(){return{_varA:0}}def(){({varA:this._varA})=abc()}};

We can see that the closing bracket is added after this._varA} instead of after the function abc() is called right at the end

trullock commented 1 year ago

Thats great, thanks.

Next step, can you make a branch and add a Test that repros this?

gotos Bugs.cs under the javascript folder, and add a bug method with the name 363 (this ticket), then add a .js file of the same name to the test data folders for input and expected with the appropriate content in each, run the test and see it work, but fail with the error you describe.

Just look how another js bug test works, pretty straightforward, you want one with the rename:all option set

AndrewKIqvia commented 1 year ago

I get the same error when NUglify minifies pdf.js the function that causes the invalid Jscript is: function putBinaryImageMask(ctx, imgData) { if (imgData.bitmap) { ctx.drawImage(imgData.bitmap, 0, 0); return; } const height = imgData.height, width = imgData.width; const partialChunkHeight = height % FULL_CHUNK_HEIGHT; const fullChunks = (height - partialChunkHeight) / FULL_CHUNK_HEIGHT; const totalChunks = partialChunkHeight === 0 ? fullChunks : fullChunks + 1; const chunkImgData = ctx.createImageData(width, FULL_CHUNK_HEIGHT); let srcPos = 0; const src = imgData.data; const dest = chunkImgData.data; for (let i = 0; i < totalChunks; i++) { const thisChunkHeight = i < fullChunks ? FULL_CHUNK_HEIGHT : partialChunkHeight; ({ srcPos } = (0, _image_utils.convertBlackAndWhiteToRGBA)({ src, srcPos, dest, width, height: thisChunkHeight, nonBlackColor: 0 })); ctx.putImageData(chunkImgData, 0, i * FULL_CHUNK_HEIGHT); } }

this gets minified to function k(n,t){if(t.bitmap){n.drawImage(t.bitmap,0,0);return}const u=t.height,e=t.width,i=u%f,r=(u-i)/f,h=i===0?r:r+1,o=n.createImageData(e,f);let s=0;const c=t.data,l=o.data;for(let t=0;t<h;t++){const u=t<r?f:i;({srcPos:s})=nt.convertBlackAndWhiteToRGBA({src:c,srcPos:s,dest:l,width:e,height:u,nonBlackColor:0});n.putImageData(o,0,t*f)}}

it's the "({srcPos:s})=nt.convertBlackAndWhiteToRGBA( " that create the error i'm no exper but i think it needed the original brackets.

mattscotty commented 1 year ago

Quick update, I've done the tests but was having creating a pull request and got busy, I'll try to get back to it.

mrandrewlane commented 1 year ago

I had this same issue with chart.js and pdf.js. To assist with a fix or for those looking for a workaround this looks like it's related to the minification of object literal destructuring assignments. I noticed this was fixed in version 1.17.9. reverting to that build minifies chart.js and pdf.js correctly.