Skip to content

Commit 52e38e0

Browse files
authored
fix: strip disabledReasons when saving blocks to backpack (#2680)
* refactor: extract cleanFlyoutInfo method in workspace-backpack Extract the key-stripping logic from blockToJsonString into a reusable cleanFlyoutInfo method. Also fix a potential null dereference when Blockly.serialization.blocks.save returns null. Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com * fix: Strip the 'disabledReasons' property when saving blocks to the backpack. Disabled blocks that are saved to the backpack retain their 'disabledReasons' property, which makes them impossible to take. Add 'disabledReasons' to the list of stripped keys and apply the stripping to blocks added via the 'Backpackable' interface ('addBackpackables'). Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com
1 parent 1565867 commit 52e38e0

1 file changed

Lines changed: 45 additions & 24 deletions

File tree

plugins/workspace-backpack/src/backpack.ts

Lines changed: 45 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -467,32 +467,54 @@ export class Backpack
467467
* @returns The JSON object as a string.
468468
*/
469469
private blockToJsonString(block: Blockly.Block): string {
470-
const json = Blockly.serialization.blocks.save(block);
470+
const json = Blockly.serialization.blocks.save(
471+
block,
472+
) as Blockly.utils.toolbox.FlyoutItemInfo | null;
471473

472-
// Add a 'kind' key so the flyout can recognize it as a block.
473-
(json as Blockly.utils.toolbox.FlyoutItemInfo).kind = 'BLOCK';
474+
if (json) {
475+
// Add a 'kind' key so the flyout can recognize it as a block.
476+
json.kind = 'BLOCK';
477+
this.cleanFlyoutInfo(json);
478+
}
479+
480+
return JSON.stringify(json);
481+
}
474482

483+
/**
484+
* Removes unnecessary keys from flyout info in place.
485+
*
486+
* @param dirtyInfo The flyout info object to clean.
487+
*/
488+
private cleanFlyoutInfo(dirtyInfo: Blockly.utils.toolbox.FlyoutItemInfo) {
475489
// The keys to remove.
476-
const keys = ['id', 'height', 'width', 'pinned', 'enabled'];
477-
478-
// Traverse the JSON recursively.
479-
const traverseJson = function (json: StateWithIndex, keys: string[]) {
480-
for (const key in json) {
481-
if (key) {
482-
if (keys.indexOf(key) !== -1) {
483-
delete json[key];
484-
}
485-
if (json[key] && typeof json[key] === 'object') {
486-
traverseJson(json[key] as StateWithIndex, keys);
487-
}
490+
const removeKeys = [
491+
'id',
492+
'height',
493+
'width',
494+
'pinned',
495+
'enabled',
496+
'disabledReasons',
497+
];
498+
499+
// Traverse the object recursively.
500+
const traverseClean = function (
501+
obj: {[key: string]: unknown},
502+
keys: string[],
503+
) {
504+
for (const key of Object.keys(obj)) {
505+
if (keys.indexOf(key) !== -1) {
506+
delete obj[key];
507+
continue;
508+
}
509+
510+
const item = obj[key];
511+
if (item !== null && typeof item === 'object') {
512+
traverseClean(item as {[key: string]: unknown}, keys);
488513
}
489514
}
490515
};
491516

492-
if (json) {
493-
traverseJson(json as StateWithIndex, keys);
494-
}
495-
return JSON.stringify(json);
517+
traverseClean(dirtyInfo as unknown as {[key: string]: unknown}, removeKeys);
496518
}
497519

498520
/**
@@ -600,7 +622,10 @@ export class Backpack
600622
backpackables
601623
.map((b) => b.toFlyoutInfo())
602624
.reduce((acc, curr) => [...acc, ...curr])
603-
.map((info) => JSON.stringify(info)),
625+
.map((info) => {
626+
this.cleanFlyoutInfo(info);
627+
return JSON.stringify(info);
628+
}),
604629
);
605630
}
606631

@@ -1033,7 +1058,3 @@ class BackpackSerializer {
10331058
backpack?.empty();
10341059
}
10351060
}
1036-
1037-
interface StateWithIndex extends Blockly.serialization.blocks.State {
1038-
[key: string]: unknown;
1039-
}

0 commit comments

Comments
 (0)