Page MenuHomePhabricator

Support minification of ES2022 Class fields syntax
Open, LowPublic

Description

The following Javascript results in a SyntaxError when minified. Unminified source:

class Badge extends HTMLElement{$badge;$badgeContent;$defaults={positionX:'left',positionY:'bottom',mode:'auto',transition:'slide',delayType:'time',delay:1000,url:null,target:'_self',hideOn:null}
constructor(){super();this.attachShadow({mode:'open'});}

After minification:

class Badge extends HTMLElement{$badge;$badgeContent;$defaults={positionX:'left',positionY:'bottom',mode:'auto',transition:'slide',delayType:'time',delay:1000,url:null,target:'_self',hideOn:null}constructor(){super();this.attachShadow({mode:'open'});}

When the newline is removed before the constructor, the browser is unable to automatically insert a ;. Manually editing the code to add the ; resolves the issue:

class Badge extends HTMLElement{$badge;$badgeContent;$defaults={positionX:'left',positionY:'bottom',mode:'auto',transition:'slide',delayType:'time',delay:1000,url:null,target:'_self',hideOn:null};constructor(){super();this.attachShadow({mode:'open'});}

I've contacted the author of the Javascript above and reported the issue as well. I am reporting here in case the parser can be improved for these situations. I have tested in Firefox (104.0.2) and Safari (Version 15.6.1 (17613.3.9.1.16)). In Safari, the error is SyntaxError: Unexpected identifier 'constructor'. Expected a ';' following a class field.

Event Timeline

Restricted Application added a subscriber: Aklapper. · View Herald Transcript

The "unminified" snippet produces SyntaxError: Unexpected end of input, likely missing a few characters at the end. It also does not appear unminified.

Is this code loaded as JS file in a MediaWiki extension, or an on-wiki gadget, or a user script?

Which version of MediaWiki?

This is a snippet from a custom JS. Not the entire script. I am using the JSMinfier library outside of MediaWiki. The php library doesn’t handle class fields where the browser can auto insert ;

@KPqmwCSpjQkx I understand, but to validate that I do need a snippet that is a minimal valid example. The current example is incomplete.

It looks like the only thing missing to make the first example valid, is a } closing brace.

Minimal example, and is indeed reproducible on latest master (v2.3.0).

class Badge {
  foo = 1; bar = 2
  constructor() {}
}
$ echo -e 'class Badge { foo = 1; bar = 2\nconstructor(){ ; } }'
class Badge { foo = 1; bar = 2
constructor(){ ; } }

$ echo -e 'class Badge { foo = 1; bar = 2\nconstructor(){ ; } }' | node
(no error)

Minify$ echo -e 'class Badge { foo = 1; bar = 2\nconstructor(){ ; } }' | ./bin/minify js
class Badge{foo=1;bar=2 constructor(){;}}
(looks invalid)

Minify$ echo -e 'class Badge { foo = 1; bar = 2\nconstructor(){ ; } }' | ./bin/minify js | node
class Badge{foo=1;bar=2 constructor(){;}}
                        ^^^^^^^^^^^
SyntaxError: Unexpected identifier
Krinkle triaged this task as Medium priority.Sep 17 2022, 10:33 PM
Krinkle added a project: patch-welcome.
Krinkle moved this task from Inbox to Confirmed Problem on the MediaWiki-ResourceLoader board.
Krinkle lowered the priority of this task from Medium to Low.Sep 19 2022, 7:01 PM

@KPqmwCSpjQkx I've consulted the ES6 specification (https://262.ecma-international.org/6.0/#sec-class-definitions) and do not find reference to the class field syntax.

If I understand correctly, the code you're using is not valid ES6/ES2015 nor valid ES2016,17,18,19 or 20; but is new under ES2022 Class fields syntax. This was released in most browsers in 2020 or 2019, and would currently be too new to require support for; as it immediately breaks payload safety in other browsers.

I'll keep this open for discovery purposes but realistically we'll likely get to when we raise the general MediaWiki platform requirements to this level, which will take a few years before we get there. I'll gladly accept a patch for T277675: Add native support for ES2016-ES2020 or higher versions or an incremental step specifically for ES2022 class fields, though.

Krinkle renamed this task from Javascript syntax error after minified to Support minification of ES2022 Class fields syntax.Sep 19 2022, 9:14 PM