Skip to content

fix: test skipped-model membership with a Set, not in on an array - #281

Open
spokodev wants to merge 1 commit into
Qix-:masterfrom
spokodev:fix-skipped-models-membership
Open

fix: test skipped-model membership with a Set, not in on an array#281
spokodev wants to merge 1 commit into
Qix-:masterfrom
spokodev:fix-skipped-models-membership

Conversation

@spokodev

Copy link
Copy Markdown

Problem

The constructor nulls a model argument that is one of the deliberately-skipped models (keyword, gray, hex) so it falls back to rgb — these have no array representation. But the guard never fires, so passing them as the explicit model produces garbage or a crash:

Color([128, 128, 128], 'hex').string();       // "#80NANNAN"   (expected "rgb(128, 128, 128)")
Color([128, 128, 128], 'hex').rgb().string();  // "rgb(17, 34, 136)"
Color([128, 128, 128], 'keyword').rgb();       // TypeError: cssKeywords[keyword] is not iterable
Color([128, 128, 128], 'gray').rgb().string(); // "rgb(255, 255, 255)"

Cause

const skippedModels = ['keyword', 'gray', 'hex'];
...
if (model && model in skippedModels) { // `in` on an array tests indices '0','1','2', never the names
  model = null;
}

The in operator checks an object's keys; on an array those are the numeric indices, so the guard is dead code. The model-method loop lower in the same file already uses the correct test, skippedModels.includes(model) — confirming the intent.

Fix

Make skippedModels a Set and use .has() at both sites. (A plain .includes() at the constructor would trip the repo's own unicorn/prefer-set-has xo rule, so a Set is the clean form for both.)

Verification

  • New test in test/index.js; the skipped models now fall back to rgb — fails before, passes after.
  • npm test (xo + tsd + mocha): 31 passing, lint clean.
  • Fuzz: across all valid models × 700,000 random inputs, output is byte-identical to the current release (the change is behavior-neutral for every real model); the three skipped models now match the no-model rgb fallback (60,000 checks, 0 still broken). Reachable only via the explicit model argument with array/number input, so normal string/object usage is unaffected.

The constructor nulls a `model` argument that is one of `keyword`, `gray`,
or `hex` (they have no array representation) so it falls back to rgb. The
guard used `model in skippedModels`, but `skippedModels` is an array, so
`in` tests its indices ('0', '1', '2'), never the model names — the guard
never fired:

  Color([128, 128, 128], 'hex').string()  // was "#80NANNAN"
  Color([128, 128, 128], 'keyword').rgb() // threw TypeError

The model-method loop already uses the correct `skippedModels.includes(model)`.
Make `skippedModels` a Set and use `.has()` at both sites (a plain
`.includes()` at the constructor would trip the repo's `unicorn/prefer-set-has`
lint rule).
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.

1 participant