Replace xml-unsafe chars in sb3 variables.

This commit is contained in:
Karishma Chadha committed 2019-02-04 15:32:01 -05:00
1 parent 57f112cbfd
commit 7faddb6c8f
3 files changed
+88 -7

No files matched your search

+2 -7
View File
@@ -7,6 +7,7 @@ const uid = require('../util/uid');
const {Map} = require('immutable');
const log = require('../util/log');
const StringUtil = require('../util/string-util');
const VariableUtil = require('../util/variable-util');
/**
* @fileoverview
@@ -514,13 +515,7 @@ class Target extends EventEmitter {
// for all references for a given ID instead of doing the below..?
this.blocks.getAllVariableAndListReferences()[idToBeMerged];
referencesToChange.map(ref => {
ref.referencingField.id = idToMergeWith;
if (optNewName) {
ref.referencingField.value = optNewName;
}
return ref;
});
VariableUtil.mergeVariables(idToBeMerged, idToMergeWith, referencesToChange, optNewName);
}
/**
+38
View File
@@ -14,6 +14,8 @@ const StageLayering = require('../engine/stage-layering');
const log = require('../util/log');
const uid = require('../util/uid');
const MathUtil = require('../util/math-util');
const StringUtil = require('../util/string-util');
const VariableUtil = require('../util/variable-util');
const {loadCostume} = require('../import/load-costume.js');
const {loadSound} = require('../import/load-sound.js');
@@ -1075,6 +1077,12 @@ const deserializeMonitor = function (monitorData, runtime, targets, extensions)
monitorBlockInfo && monitorBlockInfo.isSpriteSpecific) {
monitorData.id = monitorBlockInfo.getId(
monitorData.targetId, fields);
} else {
// Replace unsafe characters in monitor ID, if there are any.
// These would have come from projects that were originally 2.0 projects
// that had unsafe characters in the variable name (and then the name was
// used as part of the variable ID when importing the project).
monitorData.id = StringUtil.replaceUnsafeChars(monitorData.id);
}
// If the runtime already has a monitor block for this monitor's id,
@@ -1128,6 +1136,35 @@ const deserializeMonitor = function (monitorData, runtime, targets, extensions)
runtime.requestAddMonitor(MonitorRecord(monitorData));
};
// Replace variable IDs throughout the project with
// xml-safe versions.
// This is to fix up projects imported from 2.0 where xml-unsafe names
// were getting added to the variable ids.
const replaceUnsafeCharsInVariableIds = function (targets) {
const allVarRefs = VariableUtil.getAllVarRefsForTargets(targets);
// Re-id the variables in the actual targets
targets.forEach(t => {
Object.keys(t.variables).forEach(id => {
const newId = StringUtil.replaceUnsafeChars(id);
if (newId === id) return;
t.variables[id].id = newId;
t.variables[newId] = t.variables[id];
delete t.variables[id];
});
});
// Replace the IDs in the blocks refrencing variables or lists
for (const id in allVarRefs) {
const newId = StringUtil.replaceUnsafeChars(id);
if (id === newId) continue; // ID was already safe, skip
// We're calling this on the stage target because we need a
// target to call on but this shouldn't matter because we're passing
// in all the varRefs we want to operate on
VariableUtil.mergeVariables(id, newId, allVarRefs);
}
return targets;
};
/**
* Deserialize the specified representation of a VM runtime and loads it into the provided runtime instance.
* @param {object} json - JSON representation of a VM runtime.
@@ -1171,6 +1208,7 @@ const deserialize = function (json, runtime, zip, isSingleSprite) {
delete t.targetPaneOrder;
return t;
}))
.then(targets => replaceUnsafeCharsInVariableIds(targets))
.then(targets => {
monitorObjects.map(monitorDesc => deserializeMonitor(monitorDesc, runtime, targets, extensions));
return targets;
+48
View File
@@ -0,0 +1,48 @@
class VariableUtil {
static _mergeVarRefObjects (accum, obj2) {
for (const id in obj2) {
if (accum[id]) {
accum[id] = accum[id].concat(obj2[id]);
} else {
accum[id] = obj2[id];
}
}
return accum;
}
/**
* Get all variable/list references in the given list of targets
* in the project.
* @param {Array.<Target>} targets The list of targets to get the variable
* and list references from.
* @return {object} An object with variable ids as the keys and a list of block fields referencing
* the variable.
*/
static getAllVarRefsForTargets (targets) {
return targets
.map(t => t.blocks.getAllVariableAndListReferences())
.reduce(VariableUtil._mergeVarRefObjects, {});
}
/**
* Merge variable references with another variable.
* @param {string} idToBeMerged ID of the variable whose references need to be updated
* @param {string} idToMergeWith ID of the variable that the old references should be replaced with
* @param {Array<object>} referencesToUpdate Context of the change, the object containing variable
* references to update.
* @param {?string} optNewName New variable name to merge with. The old
* variable name in the references being updated should be replaced with this new name.
* If this parameter is not provided or is '', no name change occurs.
*/
static mergeVariables (idToBeMerged, idToMergeWith, referencesToUpdate, optNewName) {
referencesToUpdate.map(ref => {
ref.referencingField.id = idToMergeWith;
if (optNewName) {
ref.referencingField.value = optNewName;
}
return ref;
});
}
}
module.exports = VariableUtil;