Skip to content

Improve rulesIf evaluation - #1876

Open
ticapix wants to merge 9 commits into
firecow:masterfrom
ticapix:fix/rules-if-jsep-evaluator
Open

Improve rulesIf evaluation#1876
ticapix wants to merge 9 commits into
firecow:masterfrom
ticapix:fix/rules-if-jsep-evaluator

Conversation

@ticapix

@ticapix ticapix commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

Hello,

This is a proposal to improve the robustness of the rules evaluations.

This address #1859

The main changes are:

  • considering more complex rules (eg. from tbc templates), add the construction and evaluation of the logical AST based on &&, ||, ( and ) operators.
  • delegating the parsing into an AST to the small library jsep
  • keep the RE2JS evaluation logic
  • keep the regex flags parsing logic
  • keep the $VAR expansion logic
  • update the tests by:
    • moving /Hello (?i)world/ as invalid regex, even if RE2JS supports it. (regex101.com, regexr.com are considering it as invalid)
    • since we don't rely on eval() only to evaluate the full rule, we can't spy on it. Removing the expected evaluation string. Keep the final expected result verification.

Summary by cubic

Make rules:if evaluation AST-based with jsep + @jsep-plugin/regex for correct precedence, safer regex handling, clearer errors, and fast failures on unsupported nodes. Keeps RE2JS matching and $VAR expansion, and fixes edge cases in complex rules.

  • Bug Fixes

    • Correctly handle &&, ||, and parentheses via AST instead of regex rewrites.
    • Fix: null !~ /pattern/ returns true; reject ${VAR} syntax.
    • Enforce RHS of =/! to be a regex; reject quoted strings and invalid flags with helpful errors.
    • Wrap jsep parse errors with a consistent “Error attempting to evaluate the following rules:” message.
    • Fail fast on unsupported AST node types in _nodeToAtom.
    • Preserve RE2JS regex flag parsing and $VAR expansion.
    • Tests assert results only; drop eval-string spying; mark /Hello (?i)world/ invalid; add “ci-skip” string-quoted regex case.
    • Fix assertion message for non-regex RHS to use the actual RHS value and avoid a ReferenceError crash in =/! evaluations.
  • Dependencies

    • Add jsep and @jsep-plugin/regex.

Written for commit 7f17da9. Summary will update on new commits.

Review in cubic

ticapix added 4 commits June 5, 2026 16:46
…ect \${VAR}

- Replace regex-based string manipulation in evaluateRuleIf with jsep AST
  parsing for correct operator precedence and cleaner expression handling
- Fix: null !~ /pattern/ now returns true (undefined variable does not match,
  so negated check passes) instead of always returning false
- Fix: reject \${VAR} curly-bracket syntax in the new evaluator, matching
  the guard already present in the legacy _evaluateRuleIf path
- Assert that the RHS of =~/!~ is a regex pattern (not a plain quoted
  string), matching the guard already present in _evaluateRuleIf
- Wrap jsep(evalStr) in try-catch so parse failures (e.g. invalid regex
  flags like /pattern/ur/) surface as "Error attempting to evaluate the
  following rules:" instead of a raw jsep exception
- Remove evalSpy and jsExpression assertions — these were white-box
  checks of an internal implementation detail, not behaviour
- Compact test data accordingly
- Fix /Hello (?i)world/ expectation: (?i) is not valid JS regex syntax
  so the new jsep path correctly rejects it; update to expectedErrSubStr
- Delete _evaluateRuleIf: its regex-substitution logic (pattern1/pattern2,
  null.matchRE2JS replacements, re-expansion) was entirely unreachable when
  called from the jsep walk, which handles =~/!~/&&/|| before falling through
- Inline a direct eval in the walk fallback (for ==, !=, comparisons, bare
  literals), replacing the _evaluateRuleIf call
- Drop unused envs parameter from _nodeToAtom and remove commented-out block

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 4 files

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread src/utils.ts Outdated
Replaces the silent `return ""` default with an explicit error, making
unexpected AST node types fail loudly instead of producing a wrong result.
@ticapix

ticapix commented Jun 22, 2026

Copy link
Copy Markdown
Contributor Author

I'm not sure how I can fix the CI timeout errors :(

Comment thread src/utils.ts Outdated
Double-quoted string prevented ${rhs} from expanding; the assert
message showed the literal text "${rhs}" instead of the actual value.
@firecow

firecow commented Jun 23, 2026

Copy link
Copy Markdown
Owner

ticapix added 3 commits June 27, 2026 00:47
${rhs} was undefined at runtime; the correct variable is ${regexStr}
(the raw RHS string after stripQuotes). The assertMsg array is eagerly
evaluated, so the ReferenceError crashed every =~/!~ evaluation, not
just cases with a non-regex RHS.
@ottok

ottok commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

I tested this branch in #1859 (comment) and can confirm it fixes at least the variant of the regex issue I experienced.

@firecow firecow left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AST is right, but two regressions vs master:

RE2-only regex aborts the rule. @jsep-plugin/regex validates with JS RegExp, matching is RE2JS. /(?i)x/, /(?P<n>x)/, /a(?s)b/ all rejected. $CI_COMMIT_TAG =~ /(?i)release/true on master, throws here. So moving /Hello (?i)world/ to the invalid set hides it, since regex101 validates JS, not RE2.

Unary ! throws. !($A == "x")Unsupported expression node type.

Fix: lex regex literals without JS-validating them; add a UnaryExpression case.

Minor: eval still on both walk branches; delete globalThis.RE2JS wants finally.

Also you have conflicts 😄

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants