Skip to content

Change Request: Stable way to detect the unsupported var()/env() match errors #141

Description

@minseonkkim

What problem do you want to solve?

When a value contains var() or env(), Lexer#matchProperty() / matchSyntax() returns a match result whose error is a plain Error object:

// lib/lexer/Lexer.js — matchSyntax()
if (valueHasVar(tokens)) {
    return buildMatchResult(null, new Error('Matching for a tree with var() is not supported'));
}

if (valueHasEnv(tokens)) {
    return buildMatchResult(null, new Error('Matching for a tree with env() is not supported'));
}

Consumers that need to distinguish this "matching is unsupported for this value" case from other generic errors currently have no reliable way to do so. The only option is comparing the error message string. For example, in eslint/css#510 the plugin has to do:

// eslint/css src/util.js
export function isEnvMatchError(error) {
	return error.message === "Matching for a tree with env() is not supported";
}

During review of that PR it was pointed out that relying on an internal error message is fragile: error messages are not a stable API and may change between versions, which would silently break downstream detection. Unlike SyntaxMatchError / SyntaxReferenceError, these two errors carry no distinguishing property that consumers could check instead.

Since these errors only exist in this fork (upstream csstree does not throw them), downstream consumers cannot rely on any upstream convention either.

What do you think is the correct solution?

Give these errors a stable, documented identity. Two options were discussed in the eslint/css PR review:

  1. Add a stable code property to the existing errors:
   const error = new Error('Matching for a tree with env() is not supported');
   error.code = 'ERR_LEXER_ENV_MATCH_UNSUPPORTED'; // and ERR_LEXER_VAR_MATCH_UNSUPPORTED
  • This is the smallest change — no new public class — and consumers can check error.code === 'ERR_LEXER_ENV_MATCH_UNSUPPORTED' regardless of future message wording changes.
  1. Introduce a custom error class following the existing SyntaxReferenceError / SyntaxMatchError pattern (lib/lexer/error.js, via createCustomError)

Either way, both the var() and env() errors should be covered in the same change, since they have the same shape and downstream code handles both.

I have a slight preference for option 1 (error code) as the smaller change, but I'm happy to implement whichever direction the team prefers.

Participation

  • I am willing to submit a pull request for this change.

AI acknowledgment

  • I did not use AI to generate this issue report.
  • (If the above is not checked) I have reviewed the AI-generated content before submitting.

Additional comments

No response

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Type

No type

Projects

Status
Needs Triage

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions