Okay so I slept on this cause it wasn't sitting well with me. Here are some thoughts on it.

Using 4 doubles instead of a vec4 isn't consistent with what you'd expect. Spectre uses Dart Vector Math which has properties for vec4 that fit with the semantics of an RGBA color. If this were C++ you'd definitely expect it to be a vec4, and I'd still like to leave the door open for a native port of Spectre and whatever we put over it.

Additionally this helps the tooling. In the future we could annotate the blendFactor with a @color or something along those lines and then within a UI we can easily generate a color picker.

You have a point with a vec4 causing 5 allocations instead of 4, but how many instances of BlendState are we honestly expecting? You've obviously studied the VM code more than me so I don't the full cost of having an instance of a class over the four doubles. Also if this is the case wouldn't an integer flag for the write masks be less wasteful than 4 bools?

You also have a good point about vec4 being a reference, but that's one of the natures of the beast with Dart. I personally don't like it, I was lobbying for a struct designation like C# though I have no idea how much of a benefit it would be for speed within Dart. Its certainly a gotcha so I get that, but I don't think its enough of one to hurt the clarity of the API.

Let me know what you think and I'll move forward with suggested changes.