Description
While reviewing the export pipeline in Music Blocks, I noticed that prepareExport() directly mutates live block objects while serializing nop*Block types.
Location:
Current implementation:
case "nopValueBlock":
case "nopZeroArgBlock":
case "nopOneArgBlock":
case "nopTwoArgBlock":
case "nopThreeArgBlock":
myBlock.name = myBlock.privateData;
break;
prepareExport() is expected to behave as a read-only serialization step, but this code overwrites the live runtime value of:
inside the active blockList.
Because the mutation is applied directly to the canvas/runtime block object and is never restored afterward, later export or runtime operations may observe a different block name than the original nop*Block value.
This becomes especially problematic because the serialization logic itself depends on matching:
nopValueBlock
nopZeroArgBlock
nopOneArgBlock
...
during future export calls.
After the first mutation, subsequent exports may no longer enter these switch branches because the block name has already been replaced with privateData.
Expected Behavior
prepareExport() should serialize block data without mutating live runtime block objects.
The active canvas state should remain unchanged after export, auto-save, or save operations.
Current Behavior
During export, nop*Block types overwrite their live .name value with:
This mutation persists after serialization completes.
Subsequent export operations may then:
- serialize different block names
- skip
nop*Block handling logic
- produce inconsistent save/load behavior for plugin fallback blocks
Why This Matters
prepareExport() is triggered from several common workflows, including:
- auto-save
- manual save
- save-as
- play/save flows
Mutating runtime block state during serialization can therefore affect later editor behavior and repeated exports within the same session.
Root Cause
The serializer directly mutates:
instead of using a temporary serialization-only value.
This causes runtime state leakage from the export pipeline back into the active canvas model.
Suggested Fix
Avoid mutating myBlock.name during serialization.
Instead, use a local serialization variable:
const serializedName =
myBlock.privateData || myBlock.name;
and serialize that value without modifying the live block object.
Suggested Approach
case "nopValueBlock":
case "nopZeroArgBlock":
case "nopOneArgBlock":
case "nopTwoArgBlock":
case "nopThreeArgBlock": {
const serializedName =
myBlock.privateData || myBlock.name;
data.push([
blockIndexById.get(blk),
serializedName,
myBlock.container.x,
myBlock.container.y,
connections
]);
continue;
}
Checklist
Description
While reviewing the export pipeline in Music Blocks, I noticed that
prepareExport()directly mutates live block objects while serializingnop*Blocktypes.Location:
Current implementation:
prepareExport()is expected to behave as a read-only serialization step, but this code overwrites the live runtime value of:inside the active
blockList.Because the mutation is applied directly to the canvas/runtime block object and is never restored afterward, later export or runtime operations may observe a different block name than the original
nop*Blockvalue.This becomes especially problematic because the serialization logic itself depends on matching:
during future export calls.
After the first mutation, subsequent exports may no longer enter these switch branches because the block name has already been replaced with
privateData.Expected Behavior
prepareExport()should serialize block data without mutating live runtime block objects.The active canvas state should remain unchanged after export, auto-save, or save operations.
Current Behavior
During export,
nop*Blocktypes overwrite their live.namevalue with:This mutation persists after serialization completes.
Subsequent export operations may then:
nop*Blockhandling logicWhy This Matters
prepareExport()is triggered from several common workflows, including:Mutating runtime block state during serialization can therefore affect later editor behavior and repeated exports within the same session.
Root Cause
The serializer directly mutates:
instead of using a temporary serialization-only value.
This causes runtime state leakage from the export pipeline back into the active canvas model.
Suggested Fix
Avoid mutating
myBlock.nameduring serialization.Instead, use a local serialization variable:
and serialize that value without modifying the live block object.
Suggested Approach
Checklist