Skip to content

fix: splitUnit returns original unit when called as a method with array parts (#3644)#3671

Open
MaksZhukov wants to merge 1 commit into
josdejong:developfrom
MaksZhukov:fix/issue-3644-splitunit-matrix-parts
Open

fix: splitUnit returns original unit when called as a method with array parts (#3644)#3671
MaksZhukov wants to merge 1 commit into
josdejong:developfrom
MaksZhukov:fix/issue-3644-splitunit-matrix-parts

Conversation

@MaksZhukov

Copy link
Copy Markdown

What

Fixes the splitUnit method-call form in the expression parser, which silently returned the original unit unchanged.

(1 m).splitUnit([ft, in])      // before: 1 m        after: 3 ft,3.3700787401574765 in
(1 m).splitUnit(["ft", "in"])  // before: 1 m        after: 3 ft,3.3700787401574765 in

Closes #3644.

Why

Unit.prototype.splitUnit iterates over parts.length. When splitUnit is invoked as a method in the expression parser (e.g. (1 m).splitUnit([ft, in])), the parser dispatches the call directly to the prototype method via getSafeMethod/fn.apply(object, values), passing the array literal as a Matrix (the default matrix: 'Matrix' config) rather than a plain Array.

A Matrix has no .length property, so parts.length is undefined, the for loop never executes, and the method falls through to returning [this] — the original, unsplit unit.

The function form splitUnit(1 m, [ft, in]) was unaffected because it goes through the typed-function 'Unit, Array' signature, which converts the Matrix to an Array before reaching the prototype method.

Fix

Normalize parts to an Array (via toArray()) when it is a Matrix, so the method-call form behaves identically to the function-call form. Minimal change, no new dependencies.

How to test

math.evaluate('(1 m).splitUnit([ft, in])').toString()     // '3 ft,3.3700787401574765 in'
math.evaluate('(1 m).splitUnit(["ft", "in"])').toString() // '3 ft,3.3700787401574765 in'

A regression test covering the Matrix/method-call form was added to test/unit-tests/type/unit/function/splitUnit.test.js. The full unit-test suite (npx mocha test/unit-tests) passes (6653 passing) and eslint is clean on the changed files.

🤖 Generated with Claude Code

When splitUnit is called as a method in the expression parser
(e.g. `(1 m).splitUnit([ft, in])`), the parts argument is passed as a
Matrix rather than a plain Array. Unit.prototype.splitUnit iterated over
`parts.length`, which is undefined for a Matrix, so the loop was skipped
and the original unit was returned unchanged.

Normalize `parts` to an Array (via toArray) when it is a Matrix so the
method-call form behaves the same as the function-call form.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.

splitUnit behavior does not match documentation

1 participant