diff --git a/src/ast/nodes/shared/knownGlobals.ts b/src/ast/nodes/shared/knownGlobals.ts index a6c7a6eaa10..d7bc8b1556b 100644 --- a/src/ast/nodes/shared/knownGlobals.ts +++ b/src/ast/nodes/shared/knownGlobals.ts @@ -10,6 +10,7 @@ import { UNKNOWN_NON_ACCESSOR_PATH, UNKNOWN_PATH } from '../../utils/PathTracker'; +import ArrayExpression from '../ArrayExpression'; import type { LiteralValueOrUnknown } from './Expression'; import { UnknownTruthyValue } from './Expression'; @@ -43,6 +44,14 @@ const IMPURE: ValueDescription = { hasEffectsWhenCalled: returnTrue }; +const PURE_WITH_ARRAY: ValueDescription = { + deoptimizeArgumentsOnCall: doNothing, + getLiteralValue: getTruthyLiteralValue, + hasEffectsWhenCalled({ args }) { + return args.length > 1 && !(args[1] instanceof ArrayExpression); + } +}; + // We use shortened variables to reduce file size here /* OBJECT */ const O: GlobalDescription = { @@ -91,6 +100,12 @@ const PC: GlobalDescription = { prototype: O }; +const PC_WITH_ARRAY = { + __proto__: null, + [ValueProperties]: PURE_WITH_ARRAY, + prototype: O +}; + const ARRAY_TYPE: GlobalDescription = { __proto__: null, [ValueProperties]: PURE, @@ -164,7 +179,7 @@ const knownGlobals: GlobalDescription = { isNaN: PF, isPrototypeOf: O, JSON: O, - Map: C, + Map: PC_WITH_ARRAY, Math: { __proto__: null, [ValueProperties]: IMPURE, @@ -260,7 +275,7 @@ const knownGlobals: GlobalDescription = { ReferenceError: PC, Reflect: O, RegExp: PC, - Set: C, + Set: PC_WITH_ARRAY, SharedArrayBuffer: C, String: { __proto__: null, @@ -300,8 +315,8 @@ const knownGlobals: GlobalDescription = { unescape: PF, URIError: PC, valueOf: O, - WeakMap: C, - WeakSet: C, + WeakMap: PC_WITH_ARRAY, + WeakSet: PC_WITH_ARRAY, // Additional globals shared by Node and Browser that are not strictly part of the language clearInterval: C, diff --git a/test/form/samples/tree-shake-global-variables/_config.js b/test/form/samples/tree-shake-global-variables/_config.js new file mode 100644 index 00000000000..fd7f618e7e7 --- /dev/null +++ b/test/form/samples/tree-shake-global-variables/_config.js @@ -0,0 +1,3 @@ +module.exports = defineTest({ + description: 'retain Set, Map, WeakSet and WeakMap which called with array arguments' +}); diff --git a/test/form/samples/tree-shake-global-variables/_expected.js b/test/form/samples/tree-shake-global-variables/_expected.js new file mode 100644 index 00000000000..d164447d06d --- /dev/null +++ b/test/form/samples/tree-shake-global-variables/_expected.js @@ -0,0 +1,7 @@ +new Set([f()]); //retained + +new WeakSet([f()]); //retained + +new Map([['a', f()]]); //retained + +new WeakMap([[f(), 'a']]); //retained diff --git a/test/form/samples/tree-shake-global-variables/main.js b/test/form/samples/tree-shake-global-variables/main.js new file mode 100644 index 00000000000..32182ba5b91 --- /dev/null +++ b/test/form/samples/tree-shake-global-variables/main.js @@ -0,0 +1,23 @@ +new Set([f()]); //retained + +new Set(['a']); + +new Set(); + +new WeakSet([f()]); //retained + +new WeakSet([{}]); + +new WeakSet(); + +new Map([['a', f()]]); //retained + +new Map([['a', 'a']]); + +new Map(); + +new WeakMap([[f(), 'a']]); //retained + +new WeakMap([[{}, 'a']]); + +new WeakMap();