Skip to content

Commit

Permalink
fix: check in hasEffectsOnInteractionAtPath
Browse files Browse the repository at this point in the history
  • Loading branch information
TrickyPi committed Dec 10, 2022
1 parent da82fe1 commit efb6544
Show file tree
Hide file tree
Showing 7 changed files with 72 additions and 11 deletions.
7 changes: 7 additions & 0 deletions src/ast/nodes/Literal.ts
Expand Up @@ -70,6 +70,13 @@ export default class Literal<T extends LiteralValue = LiteralValue> extends Node
return true;
}
case INTERACTION_CALLED: {
if (
this.included &&
this.value instanceof RegExp &&
(this.value.global || this.value.sticky)
) {
return true;
}
return (
path.length !== 1 ||
hasMemberEffectWhenCalled(this.members, path[0], interaction, context)
Expand Down
12 changes: 8 additions & 4 deletions src/ast/values.ts
Expand Up @@ -200,8 +200,12 @@ const literalNumberMembers: MemberDescriptions = assembleMemberDescriptions(
objectMembers
);

// RegExp are stateful when they have the global or sticky flags set.
const literalParticularRegExpMembers: MemberDescriptions = assembleMemberDescriptions(
/**
* RegExp are stateful when they have the global or sticky flags set.
* But if we actually don't use them, the side effect does not matter.
* the check logic in `hasEffectsOnInteractionAtPath`.
*/
const literalRegExpMembers: MemberDescriptions = assembleMemberDescriptions(
{
exec: returnsUnknown,
test: returnsBoolean
Expand Down Expand Up @@ -267,8 +271,8 @@ export const literalStringMembers: MemberDescriptions = assembleMemberDescriptio
export function getLiteralMembersForValue<T extends LiteralValue = LiteralValue>(
value: T
): MemberDescriptions {
if (value instanceof RegExp && !value.global && !value.sticky) {
return literalParticularRegExpMembers;
if (value instanceof RegExp) {
return literalRegExpMembers;
}
switch (typeof value) {
case 'boolean': {
Expand Down
@@ -0,0 +1,3 @@
module.exports = {
description: 'check tree-shake on RegExp if it is used'
};
@@ -0,0 +1,23 @@
const normalRegexp_1 = /1/;
const normalRegexp_2 = /1/;

assert.strictEqual(normalRegexp_1.test(1), true);
assert.ok(normalRegexp_2.exec(1));

const globalRegexp_1 = /1/g;
const globalRegexp_2 = /1/g;

globalRegexp_1.test(1);
globalRegexp_2.exec(1);

assert.strictEqual(globalRegexp_1.test(1), null);
assert.strictEqual(globalRegexp_2.exec(1), null);

const stickyRegexp_1 = /1/y;
const stickyRegexp_2 = /1/y;

stickyRegexp_1.test(1);
stickyRegexp_2.exec(1);

assert.strictEqual(stickyRegexp_1.test(1), null);
assert.strictEqual(stickyRegexp_2.exec(1), null);
@@ -0,0 +1,26 @@
const normalRegexp_1 = /1/;
const normalRegexp_2 = /1/;

normalRegexp_1.test(1);
normalRegexp_2.exec(1);

assert.strictEqual(normalRegexp_1.test(1), true);
assert.ok(normalRegexp_2.exec(1));

const globalRegexp_1 = /1/g;
const globalRegexp_2 = /1/g;

globalRegexp_1.test(1);
globalRegexp_2.exec(1);

assert.strictEqual(globalRegexp_1.test(1), null);
assert.strictEqual(globalRegexp_2.exec(1), null);

const stickyRegexp_1 = /1/y;
const stickyRegexp_2 = /1/y;

stickyRegexp_1.test(1);
stickyRegexp_2.exec(1);

assert.strictEqual(stickyRegexp_1.test(1), null);
assert.strictEqual(stickyRegexp_2.exec(1), null);
3 changes: 0 additions & 3 deletions test/form/samples/builtin-prototypes/literal/_expected.js
Expand Up @@ -17,9 +17,6 @@ true.valueOf().unknown.unknown().unknown;
'ab'.charAt(1).unknown.unknown();
'ab'.charAt(1).unknown.unknown().unknown;

/1/g.exec(1);
/1/y.exec(1);

null.unknown;
'ab'.replace('a', () => console.log(1) || 'b');
'ab'.replaceAll('a', () => console.log(1) || 'b');
Expand Down
9 changes: 5 additions & 4 deletions test/form/samples/builtin-prototypes/literal/main.js
Expand Up @@ -17,9 +17,6 @@ true.valueOf().unknown.unknown().unknown;
'ab'.charAt(1).unknown.unknown();
'ab'.charAt(1).unknown.unknown().unknown;

/1/g.exec(1);
/1/y.exec(1);

null.unknown;

// boolean prototype
Expand Down Expand Up @@ -52,8 +49,12 @@ const _numberIsPrototypeOf = (1).isPrototypeOf(1).valueOf();
const _numberPropertyIsEnumerable = (1).propertyIsEnumerable('toString').valueOf();

// RegExp prototype
/1/.test(2);
/1/.test(1);
/1/.exec(1);
/1/y.test(1);
/1/y.exec(1);
/1/g.test(1);
/1/g.exec(1);

// string prototype
'ab'.valueOf();
Expand Down

0 comments on commit efb6544

Please sign in to comment.