@@ -8215,35 +8215,43 @@ const createNodePrinter = (modules) => {
82158215 let constructedWhenCalled;
82168216
82178217 /**
8218- * Whether a `new` of a built-in nothing assigns constructs as a call of it
8219- * does, as webpack's improvements have it; a `RegExp` call hands back an
8220- * expression it is given, so only one of a primitive or nothing does.
8221- * @param {number} node the `new`
8222- * @returns {boolean} true where it prints as the call
8218+ * @param {number} node a name
8219+ * @returns {boolean} whether it reads a built-in constructor nothing assigns, one constructing the same called without `new`
82238220 */
8224- const constructsWhenCalled = (node) => {
8225- const callee = childOf(Field.callee, node);
8226- if (typeOf(callee) !== NodeType.Identifier || mangledNames === null) {
8221+ const readsBuiltInConstructor = (node) => {
8222+ if (typeOf(node) !== NodeType.Identifier || mangledNames === null) {
82278223 return false;
82288224 }
8229- const name = tree.name(callee);
82308225 if (constructedWhenCalled === undefined) {
82318226 constructedWhenCalled = new Set(
82328227 require("./syntax-printer-data").foldedBuiltIns().constructedWhenCalled
82338228 );
8234- constructedWhenCalled.delete("RegExp");
82358229 }
8236- const definition = mangledNames[callee ];
8230+ const definition = mangledNames[node ];
82378231 return (
8238- (constructedWhenCalled.has(name) ||
8239- (name === "RegExp" && patternIsPrimitive(node))) &&
8232+ constructedWhenCalled.has(tree.name(node)) &&
82408233 isMinifierVariable(definition) &&
82418234 definition.undeclared &&
82428235 !definition.written &&
82438236 !(/** @type {MinifierScope} */ (definition.scope).isPinned())
82448237 );
82458238 };
82468239
8240+ /**
8241+ * Whether a `new` of a built-in nothing assigns constructs as a call of it
8242+ * does, as webpack's improvements have it; a `RegExp` call hands back an
8243+ * expression it is given, so only one of a primitive or nothing does.
8244+ * @param {number} node the `new`
8245+ * @returns {boolean} true where it prints as the call
8246+ */
8247+ const constructsWhenCalled = (node) => {
8248+ const callee = childOf(Field.callee, node);
8249+ return (
8250+ readsBuiltInConstructor(callee) &&
8251+ (tree.name(callee) !== "RegExp" || patternIsPrimitive(node))
8252+ );
8253+ };
8254+
82478255 /**
82488256 * Whether a name reads the global `undefined`, read where a unary operator
82498257 * may stand for it.
@@ -8345,7 +8353,8 @@ const createNodePrinter = (modules) => {
83458353 nameKind,
83468354 isPureCall,
83478355 readValue: collapsedValue,
8348- comparesConvert
8356+ comparesConvert,
8357+ heritageConstructs
83498358 };
83508359 }
83518360 sideEffectsContext.decides =
@@ -8572,28 +8581,28 @@ const createNodePrinter = (modules) => {
85728581 keepsEffect[declarator] === 1 && aliasesRead[declarator] !== 3;
85738582
85748583 /**
8575- * Whether defining a class makes nothing happen: what it runs is pure and
8576- * its heritage is a constructor, which only a class made before it is known
8577- * to be, so extending an arrow or a generator still throws where it was .
8578- * @param {number} node a class declaration
8579- * @returns {boolean} whether it may go unread
8584+ * Whether a class's heritage is a constructor, so defining the class does
8585+ * not throw: `null`, a built-in one, or a class made before it and never
8586+ * set since, which an arrow or a generator a name holds is not .
8587+ * @param {number} heritage the heritage, past parentheses
8588+ * @returns {boolean} true where it is known to construct
85808589 */
8581- const definesNothing = (node) => {
8582- const heritage = childOf(Field.superClass, node);
8583- if (heritage !== 0 && !(madeReads.size !== 0 && madeReads.has(heritage))) {
8584- const left =
8585- typeOf(heritage) === NodeType.LogicalExpression &&
8586- tree.textOf(Part.operator, heritage) === "&&"
8587- ? childOf(Field.left, heritage)
8588- : heritage;
8589- if (
8590- typeOf(left) !== NodeType.Literal ||
8591- tree.textOf(Part.raw, left) !== "null"
8592- ) {
8593- return false;
8594- }
8590+ const heritageConstructs = (heritage) => {
8591+ if (
8592+ (madeReads.size !== 0 && madeReads.has(heritage)) ||
8593+ readsBuiltInConstructor(heritage)
8594+ ) {
8595+ return true;
85958596 }
8596- return isPureValue(node);
8597+ const left =
8598+ typeOf(heritage) === NodeType.LogicalExpression &&
8599+ tree.textOf(Part.operator, heritage) === "&&"
8600+ ? childOf(Field.left, heritage)
8601+ : heritage;
8602+ return (
8603+ typeOf(left) === NodeType.Literal &&
8604+ tree.textOf(Part.raw, left) === "null"
8605+ );
85978606 };
85988607
85998608 /**
@@ -8608,7 +8617,7 @@ const createNodePrinter = (modules) => {
86088617 if (type === NodeType.ClassDeclaration) {
86098618 return (
86108619 isUnusedBinding(tree.field(0, Field.id, candidate)) &&
8611- definesNothing (candidate)
8620+ isPureValue (candidate)
86128621 );
86138622 }
86148623 if (!isUnusedBinding(childOf(Field.id, candidate))) return false;
@@ -10297,27 +10306,55 @@ const createNodePrinter = (modules) => {
1029710306 };
1029810307
1029910308 /**
10300- * Notes a class extending a class declared before it in the same list,
10301- * and never set again, whose read there is made and so cannot throw.
10302- * @param {number} declaration a class declaration of a list
10309+ * @param {number} statement a statement of a list
10310+ * @param {TreeDefinition} definition a name's definition
10311+ * @param {number=} count how many of a declaration's first declarators to read, all where not given
10312+ * @returns {boolean} whether it makes that name a class: declares the class, or a variable a class expression sets
10313+ */
10314+ const makesClass = (statement, definition, count = -1) => {
10315+ const names = /** @type {TreeDefinition[]} */ (mangledNames);
10316+ if (typeOf(statement) === NodeType.ExportNamedDeclaration) {
10317+ statement = tree.field(0, Field.declaration, statement);
10318+ }
10319+ const type = statement === 0 ? 0 : typeOf(statement);
10320+ if (type === NodeType.ClassDeclaration) {
10321+ return names[tree.field(0, Field.id, statement)] === definition;
10322+ }
10323+ if (type !== NodeType.VariableDeclaration) return false;
10324+ if (count === -1) count = tree.fieldCount(Field.declarations, statement);
10325+ for (let i = 0; i < count; i++) {
10326+ const declarator = tree.field(i, Field.declarations, statement);
10327+ if (names[tree.field(0, Field.id, declarator)] === definition) {
10328+ return (
10329+ typeOf(childOf(Field.init, declarator)) === NodeType.ClassExpression
10330+ );
10331+ }
10332+ }
10333+ return false;
10334+ };
10335+
10336+ /**
10337+ * Notes a class extending a class made before it in the same list, and
10338+ * never set again, whose read there is made and so cannot throw.
10339+ * @param {number} node a class declaration of a list, or a class expression one of its declarators sets
1030310340 * @param {number} list the list
10304- * @param {number} index its place there
10341+ * @param {number} index the place there of the statement holding it
10342+ * @param {number=} declarator where it is a declarator's value, that declarator's place in the statement, whose declarators before it are read too
1030510343 * @returns {void}
1030610344 */
10307- const noteExtendsDeclared = (declaration , list, index) => {
10308- const superClass = childOf(Field.superClass, declaration );
10345+ const noteExtendsDeclared = (node , list, index, declarator = 0 ) => {
10346+ const superClass = childOf(Field.superClass, node );
1030910347 if (typeOf(superClass) !== NodeType.Identifier) return;
1031010348 const definition = /** @type {TreeDefinition[]} */ (mangledNames)[
1031110349 superClass
1031210350 ];
1031310351 if (!isMinifierVariable(definition) || definition.written) return;
10314- for (let i = 0; i < index; i++) {
10352+ for (let i = 0; i <= index; i++) {
1031510353 const statement = tree.field(i, Field.body, list);
1031610354 if (
10317- typeOf(statement) === NodeType.ClassDeclaration &&
10318- /** @type {TreeDefinition[]} */ (mangledNames)[
10319- tree.field(0, Field.id, statement)
10320- ] === definition
10355+ i < index
10356+ ? makesClass(statement, definition)
10357+ : declarator > 0 && makesClass(statement, definition, declarator)
1032110358 ) {
1032210359 madeReads.add(superClass);
1032310360 return;
@@ -10388,6 +10425,9 @@ const createNodePrinter = (modules) => {
1038810425 keepsEffect[declarator] = 2;
1038910426 }
1039010427 const init = childOf(Field.init, declarator);
10428+ if (typeOf(init) === NodeType.ClassExpression) {
10429+ noteExtendsDeclared(init, node, i, j);
10430+ }
1039110431 if (quiet && init !== 0 && findNode(init, findRun)) quiet = false;
1039210432 }
1039310433 } else if (
@@ -11931,7 +11971,7 @@ const createNodePrinter = (modules) => {
1193111971 if (!mayGoUnread(id)) return 0;
1193211972 if (type === NodeType.FunctionDeclaration) return id;
1193311973 if (type === NodeType.ClassDeclaration) {
11934- return definesNothing (candidate) ? id : 0;
11974+ return isPureValue (candidate) ? id : 0;
1193511975 }
1193611976 const init = childOf(Field.init, candidate);
1193711977 return init !== 0 &&
0 commit comments