@@ -10,7 +10,6 @@ const { InlinedUsedName } = require("../optimize/InlineExports");
1010const { equals } = require ( "../util/ArrayHelpers" ) ;
1111const SortableSet = require ( "../util/SortableSet" ) ;
1212const makeSerializable = require ( "../util/makeSerializable" ) ;
13- const { forEachRuntime } = require ( "../util/runtime" ) ;
1413const { registerLegacyRequest } = require ( "../util/serialization" ) ;
1514
1615/**
@@ -70,6 +69,59 @@ const UsageState = Object.freeze({
7069
7170const RETURNS_TRUE = ( ) => true ;
7271
72+ /**
73+ * Condition for `setUsedConditionally`, hoisted so no closure is made per call.
74+ * @param {UsageStateType } used usage state
75+ * @returns {boolean } true, when the export is unused
76+ */
77+ const isUnused = ( used ) => used === UsageState . Unused ;
78+
79+ /**
80+ * Condition for `setUsedConditionally`, hoisted so no closure is made per call.
81+ * @param {UsageStateType } used usage state
82+ * @returns {boolean } true, when the usage is less than unknown
83+ */
84+ const isBelowUnknown = ( used ) => used < UsageState . Unknown ;
85+
86+ /**
87+ * Sets the usage of one runtime in a per-runtime usage map.
88+ * @param {UsedInRuntime } usedInRuntime usage per runtime
89+ * @param {string } runtime the runtime
90+ * @param {UsageStateType } newValue new usage state
91+ * @param {((condition: UsageStateType) => boolean) | undefined } condition only set when it holds for the old value
92+ * @returns {boolean } true, when the usage changed
93+ */
94+ const setUsedInRuntime = ( usedInRuntime , runtime , newValue , condition ) => {
95+ /** @type {UsageStateType | undefined } */
96+ let oldValue = usedInRuntime . get ( runtime ) ;
97+ if ( oldValue === undefined ) oldValue = UsageState . Unused ;
98+ if ( newValue === oldValue ) return false ;
99+ if ( condition !== undefined && ! condition ( oldValue ) ) return false ;
100+ if ( newValue === UsageState . Unused ) {
101+ usedInRuntime . delete ( runtime ) ;
102+ } else {
103+ usedInRuntime . set ( runtime , newValue ) ;
104+ }
105+ return true ;
106+ } ;
107+
108+ /**
109+ * Creates a per-runtime usage map holding one usage state for every runtime.
110+ * @param {Exclude<RuntimeSpec, undefined> } runtime the runtime
111+ * @param {RuntimeUsageStateType } value usage state
112+ * @returns {UsedInRuntime } usage per runtime
113+ */
114+ const createUsedInRuntime = ( runtime , value ) => {
115+ /** @type {UsedInRuntime } */
116+ const usedInRuntime = new Map ( ) ;
117+ if ( typeof runtime === "string" ) {
118+ usedInRuntime . set ( runtime , value ) ;
119+ } else {
120+ for ( const name of runtime ) usedInRuntime . set ( name , value ) ;
121+ }
122+ return usedInRuntime ;
123+ } ;
124+
73125// Shared empty visited-set for `findTarget`: `_findTarget` only reads
74126// `alreadyVisited` (`.has`), never mutates it, so a fresh `new Set()` per call
75127// is pure churn on the per-export reexport hot path. Must stay never-mutated.
@@ -591,7 +643,7 @@ class ExportsInfo {
591643 */
592644 setUsedForSideEffectsOnly ( runtime ) {
593645 return this . _sideEffectsOnlyInfo . setUsedConditionally (
594- ( used ) => used === UsageState . Unused ,
646+ isUnused ,
595647 UsageState . Used ,
596648 runtime
597649 ) ;
@@ -712,8 +764,9 @@ class ExportsInfo {
712764 const inner = this . _redirectTo . getProvidedExports ( ) ;
713765 if ( inner === null ) return null ;
714766 if ( inner === true ) return true ;
767+ const seen = new Set ( array ) ;
715768 for ( const item of inner ) {
716- if ( ! array . includes ( item ) ) {
769+ if ( ! seen . has ( item ) ) {
717770 array . push ( item ) ;
718771 }
719772 }
@@ -1261,11 +1314,7 @@ class ExportInfo {
12611314 setUsedInUnknownWay ( runtime ) {
12621315 let changed = false ;
12631316 if (
1264- this . setUsedConditionally (
1265- ( used ) => used < UsageState . Unknown ,
1266- UsageState . Unknown ,
1267- runtime
1268- )
1317+ this . setUsedConditionally ( isBelowUnknown , UsageState . Unknown , runtime )
12691318 ) {
12701319 changed = true ;
12711320 }
@@ -1392,33 +1441,21 @@ class ExportInfo {
13921441 }
13931442 } else if ( this . _usedInRuntime === undefined ) {
13941443 if ( newValue !== UsageState . Unused && condition ( UsageState . Unused ) ) {
1395- this . _usedInRuntime = new Map ( ) ;
1396- forEachRuntime ( runtime , ( runtime ) =>
1397- /** @type {UsedInRuntime } */
1398- ( this . _usedInRuntime ) . set ( /** @type {string } */ ( runtime ) , newValue )
1399- ) ;
1444+ this . _usedInRuntime = createUsedInRuntime ( runtime , newValue ) ;
14001445 return true ;
14011446 }
14021447 } else {
1448+ const usedInRuntime = this . _usedInRuntime ;
14031449 let changed = false ;
1404- forEachRuntime ( runtime , ( runtime_ ) => {
1405- const runtime = /** @type {string } */ ( runtime_ ) ;
1406- const usedInRuntime =
1407- /** @type {UsedInRuntime } */
1408- ( this . _usedInRuntime ) ;
1409- let oldValue =
1410- /** @type {UsageStateType } */
1411- ( usedInRuntime . get ( runtime ) ) ;
1412- if ( oldValue === undefined ) oldValue = UsageState . Unused ;
1413- if ( newValue !== oldValue && condition ( oldValue ) ) {
1414- if ( newValue === UsageState . Unused ) {
1415- usedInRuntime . delete ( runtime ) ;
1416- } else {
1417- usedInRuntime . set ( runtime , newValue ) ;
1450+ if ( typeof runtime === "string" ) {
1451+ changed = setUsedInRuntime ( usedInRuntime , runtime , newValue , condition ) ;
1452+ } else {
1453+ for ( const name of runtime ) {
1454+ if ( setUsedInRuntime ( usedInRuntime , name , newValue , condition ) ) {
1455+ changed = true ;
14181456 }
1419- changed = true ;
14201457 }
1421- } ) ;
1458+ }
14221459 if ( changed ) {
14231460 if ( this . _usedInRuntime . size === 0 ) this . _usedInRuntime = undefined ;
14241461 return true ;
@@ -1441,33 +1478,21 @@ class ExportInfo {
14411478 }
14421479 } else if ( this . _usedInRuntime === undefined ) {
14431480 if ( newValue !== UsageState . Unused ) {
1444- this . _usedInRuntime = new Map ( ) ;
1445- forEachRuntime ( runtime , ( runtime ) =>
1446- /** @type {UsedInRuntime } */
1447- ( this . _usedInRuntime ) . set ( /** @type {string } */ ( runtime ) , newValue )
1448- ) ;
1481+ this . _usedInRuntime = createUsedInRuntime ( runtime , newValue ) ;
14491482 return true ;
14501483 }
14511484 } else {
1485+ const usedInRuntime = this . _usedInRuntime ;
14521486 let changed = false ;
1453- forEachRuntime ( runtime , ( _runtime ) => {
1454- const runtime = /** @type {string } */ ( _runtime ) ;
1455- const usedInRuntime =
1456- /** @type {UsedInRuntime } */
1457- ( this . _usedInRuntime ) ;
1458- let oldValue =
1459- /** @type {UsageStateType } */
1460- ( usedInRuntime . get ( runtime ) ) ;
1461- if ( oldValue === undefined ) oldValue = UsageState . Unused ;
1462- if ( newValue !== oldValue ) {
1463- if ( newValue === UsageState . Unused ) {
1464- usedInRuntime . delete ( runtime ) ;
1465- } else {
1466- usedInRuntime . set ( runtime , newValue ) ;
1487+ if ( typeof runtime === "string" ) {
1488+ changed = setUsedInRuntime ( usedInRuntime , runtime , newValue , undefined ) ;
1489+ } else {
1490+ for ( const name of runtime ) {
1491+ if ( setUsedInRuntime ( usedInRuntime , name , newValue , undefined ) ) {
1492+ changed = true ;
14671493 }
1468- changed = true ;
14691494 }
1470- } ) ;
1495+ }
14711496 if ( changed ) {
14721497 if ( this . _usedInRuntime . size === 0 ) this . _usedInRuntime = undefined ;
14731498 return true ;
0 commit comments