Skip to content

Commit

Permalink
fix: check whether RegExp have the global or sticky flags set (#4742)
Browse files Browse the repository at this point in the history
* fix: check whether RegExp have the global or sticky flags set

* fix: check in hasEffectsOnInteractionAtPath

* chore: tweak

* chore: tweak variable names
  • Loading branch information
TrickyPi committed Dec 13, 2022
1 parent 243eba5 commit bd3522b
Show file tree
Hide file tree
Showing 6 changed files with 70 additions and 2 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
5 changes: 5 additions & 0 deletions src/ast/values.ts
Expand Up @@ -200,6 +200,11 @@ const literalNumberMembers: MemberDescriptions = assembleMemberDescriptions(
objectMembers
);

/**
* 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,
Expand Down
@@ -0,0 +1,3 @@
module.exports = {
description: 'check tree-shake on RegExp if it is used'
};
@@ -0,0 +1,23 @@
const commonRegexp_1 = /1/;
const commonRegexp_2 = /1/;

assert.strictEqual(commonRegexp_1.test('1'), true);
assert.ok(commonRegexp_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 commonRegexp_1 = /1/;
const commonRegexp_2 = /1/;

commonRegexp_1.test('1');
commonRegexp_2.exec('1');

assert.strictEqual(commonRegexp_1.test('1'), true);
assert.ok(commonRegexp_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);
8 changes: 6 additions & 2 deletions test/form/samples/builtin-prototypes/literal/main.js
Expand Up @@ -49,8 +49,12 @@ const _numberIsPrototypeOf = (1).isPrototypeOf(1).valueOf();
const _numberPropertyIsEnumerable = (1).propertyIsEnumerable('toString').valueOf();

// RegExp prototype
/1/.test(2);
/1/.exec(1);
/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 bd3522b

Please sign in to comment.