Summary
getcolors.js directly mutates the objects passed in via style.colorMode,
style.frameColor, and style.iconColor rather than working on copies. When a
caller reuses any of those objects across multiple Symbol() calls, mutations
from one render corrupt subsequent renders.
Affected file
src/ms/symbol/getcolors.js
What happens
Lines 3–14 assign the caller's objects to local variables by reference:
let baseFillColor =
typeof this.style.colorMode === "object"
? this.style.colorMode // ← same object the caller owns
: ms.getColorMode(this.style.colorMode);
const baseFrameColor =
typeof this.style.frameColor === "object"
? this.style.frameColor // ← same object the caller owns
: ms.getColorMode("FrameColor");
const baseIconColor =
typeof this.style.iconColor === "object"
? this.style.iconColor // ← same object the caller owns
: ms.getColorMode("IconColor");
Lines 22–48 then mutate those variables directly:
// civilian branch
baseFillColor.Friend = baseFillColor.Neutral = baseFillColor.Unknown = baseFillColor.Civilian;
baseFrameColor.Friend = baseFrameColor.Neutral = baseFrameColor.Unknown = baseFrameColor.Civilian;
// joker/faker branch
baseFillColor.Friend = baseFillColor.Hostile;
baseFrameColor.Friend = baseFrameColor.Hostile;
// suspect branch
baseFillColor.Friend = baseFillColor.Hostile = baseFillColor.Suspect;
baseFrameColor.Friend = baseFrameColor.Hostile = baseFrameColor.Suspect;
// monoColor branch
baseFrameColor.Friend = baseFrameColor.Neutral = baseFrameColor.Hostile = ... = this.style.monoColor;
Because these are in-place property assignments on the original object, the
caller's shared color-mode object is permanently altered after any civilian,
joker, faker, suspect, or monoColor symbol renders.
Reproduction
import ms from 'milsymbol';
const colorMode = ms.getColorMode('Light'); // shared object
// First render: a Suspect symbol — mutates colorMode.Friend
new ms.Symbol('10031500001101000000', { colorMode }).asSVG();
// Second render: a Friend symbol — colorMode.Friend is now corrupted
// to the Suspect value, so this renders with the wrong color
new ms.Symbol('10031000001101000000', { colorMode }).asSVG();
The same issue occurs with any object literal passed as colorMode,
frameColor, or iconColor and reused across calls — a common pattern
when rendering a grid of symbols with a shared color theme.
Fix
Shallow-clone the incoming objects before mutating:
let baseFillColor = {
...(typeof this.style.colorMode === "object"
? this.style.colorMode
: ms.getColorMode(this.style.colorMode))
};
const baseFrameColor = {
...(typeof this.style.frameColor === "object"
? this.style.frameColor
: ms.getColorMode("FrameColor"))
};
const baseIconColor = {
...(typeof this.style.iconColor === "object"
? this.style.iconColor
: ms.getColorMode("IconColor"))
};
One spread per variable; no downstream behavior changes.
Summary
getcolors.jsdirectly mutates the objects passed in viastyle.colorMode,style.frameColor, andstyle.iconColorrather than working on copies. When acaller reuses any of those objects across multiple
Symbol()calls, mutationsfrom one render corrupt subsequent renders.
Affected file
src/ms/symbol/getcolors.jsWhat happens
Lines 3–14 assign the caller's objects to local variables by reference: