Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
mattscotty opened this issue Jul 24, 2023 · 6 comments

Comments

@mattscotty
Copy link

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
Copy link
Owner

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
Copy link
Author

mattscotty commented Jul 24, 2023

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
Copy link
Owner

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
Copy link

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
Copy link
Author

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
Copy link

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants