Rule
require-new-url-try-catch
Summary
isDynamicArg treats every non-Literal, non-empty-TemplateLiteral first argument as runtime-dynamic and therefore parse-risky. Two argument shapes that provably never throw are still flagged, producing false positives:
- Compile-time constant string concatenation —
new URL("(example.com/redacted)" + "/path"). The argument is a BinaryExpression of two string literals; it evaluates to a constant valid URL and cannot throw.
import.meta.url as the sole / first argument — new URL(import.meta.url). import.meta.url is always a valid absolute URL in ES modules, so the constructor never throws. The rule already whitelists import.meta.url via isKnownSafeBase, but only for the second (base) argument; the same value in first-argument position is flagged.
Reproduction (currently flagged, should be valid)
// (1) constant concatenation — never throws
new URL("(example.com/redacted)" + "/repos");
// (2) import.meta.url as sole argument — never throws (ES module)
const u = new URL(import.meta.url);
Consistency rationale
The sibling rule no-github-request-interpolated-route explicitly accepts compile-time constant concatenations ("GET /repos" + "/{owner}/{repo}") as safe (see eslint-factory/README.md). require-new-url-try-catch should apply the same "provably-constant is safe" principle, and should honor its own isKnownSafeBase whitelist symmetrically in first-argument position.
Grounding / severity
Logic-derived precision refinement; low current frequency in actions/setup/js (the live new URL(...) sites use genuinely dynamic arguments — e.g. generate_history_link.cjs:61, awf_reflect.cjs:140 (already wrapped), sanitize_content_core.cjs:85 — and are handled correctly). Filed to prevent false positives that would push authors to wrap statements that cannot fail.
Acceptance criteria
- Treat a
BinaryExpression whose operands are (recursively) string literals / expression-less template literals as a non-dynamic, non-throwing argument.
- Reuse
isKnownSafeBase for the first argument as well, so new URL(import.meta.url) is not flagged.
- Add valid-case tests for both forms above; keep existing invalid cases (
new URL(host + "/x") where host is a variable must still flag) to confirm the fix only exempts provably-constant / known-safe values.
- Leave genuinely dynamic single-variable and template-with-expression arguments in scope (no change).
Generated by 🤖 ESLint Refiner · 429.1 AIC · ⌖ 13.4 AIC · ⊞ 4.6K · ◷
Rule
require-new-url-try-catchSummary
isDynamicArgtreats every non-Literal, non-empty-TemplateLiteralfirst argument as runtime-dynamic and therefore parse-risky. Two argument shapes that provably never throw are still flagged, producing false positives:new URL("(example.com/redacted)" + "/path"). The argument is aBinaryExpressionof two string literals; it evaluates to a constant valid URL and cannot throw.import.meta.urlas the sole / first argument —new URL(import.meta.url).import.meta.urlis always a valid absolute URL in ES modules, so the constructor never throws. The rule already whitelistsimport.meta.urlviaisKnownSafeBase, but only for the second (base) argument; the same value in first-argument position is flagged.Reproduction (currently flagged, should be valid)
Consistency rationale
The sibling rule
no-github-request-interpolated-routeexplicitly accepts compile-time constant concatenations ("GET /repos" + "/{owner}/{repo}") as safe (see eslint-factory/README.md).require-new-url-try-catchshould apply the same "provably-constant is safe" principle, and should honor its ownisKnownSafeBasewhitelist symmetrically in first-argument position.Grounding / severity
Logic-derived precision refinement; low current frequency in
actions/setup/js(the livenew URL(...)sites use genuinely dynamic arguments — e.g.generate_history_link.cjs:61,awf_reflect.cjs:140(already wrapped),sanitize_content_core.cjs:85— and are handled correctly). Filed to prevent false positives that would push authors to wrap statements that cannot fail.Acceptance criteria
BinaryExpressionwhose operands are (recursively) string literals / expression-less template literals as a non-dynamic, non-throwing argument.isKnownSafeBasefor the first argument as well, sonew URL(import.meta.url)is not flagged.new URL(host + "/x")wherehostis a variable must still flag) to confirm the fix only exempts provably-constant / known-safe values.