mirror of
https://github.com/scratchfoundation/scratch-vm.git
synced 2025-06-26 06:10:26 -04:00
Fix up variable references after deserializing a .sprite2 or .sprite3 to avoid conflicts with pre-existing variables.
This commit is contained in:
parent
5cc48b6ef3
commit
f2aacbc79c
4 changed files with 162 additions and 33 deletions
src/engine
|
@ -6,6 +6,8 @@ const Clone = require('../util/clone');
|
|||
const {Map} = require('immutable');
|
||||
const BlocksExecuteCache = require('./blocks-execute-cache');
|
||||
const log = require('../util/log');
|
||||
const Variable = require('./variable');
|
||||
const StringUtil = require('../util/string-util');
|
||||
|
||||
/**
|
||||
* @fileoverview
|
||||
|
@ -670,6 +672,68 @@ class Blocks {
|
|||
this.resetCache();
|
||||
}
|
||||
|
||||
/**
|
||||
* Fixes up variable references in this blocks container avoiding conflicts with
|
||||
* pre-existing variables in the same scope.
|
||||
* This is used when uploading a new sprite (the given target)
|
||||
* into an existing project, where the new sprite may contain references
|
||||
* to variable names that already exist as global variables in the project
|
||||
* (and thus are in scope for variable references in the given sprite).
|
||||
*
|
||||
* If the given target has a block that references an existing global variable and that
|
||||
* variable *does not* exist in the target itself (e.g. it was a global variable in the
|
||||
* project the sprite was originally exported from), fix the variable references in this sprite
|
||||
* to reference the id of the pre-existing global variable.
|
||||
* If the given target has a block that references an existing global variable and that
|
||||
* variable does exist in the target itself (e.g. it's a local variable in the sprite being uploaded),
|
||||
* then the variable is renamed to distinguish itself from the pre-existing variable.
|
||||
* All blocks that reference the local variable will be updated to use the new name.
|
||||
* @param {Target} target The new target being uploaded, with potential variable conflicts
|
||||
* @param {Runtime} runtime The runtime context with any pre-existing variables
|
||||
*/
|
||||
fixUpVariableReferences (target, runtime) {
|
||||
const blocks = this._blocks;
|
||||
for (const blockId in blocks) {
|
||||
let varOrListField = null;
|
||||
let varType = null;
|
||||
if (blocks[blockId].fields.VARIABLE) {
|
||||
varOrListField = blocks[blockId].fields.VARIABLE;
|
||||
varType = Variable.SCALAR_TYPE;
|
||||
} else if (blocks[blockId].fields.LIST) {
|
||||
varOrListField = blocks[blockId].fields.LIST;
|
||||
varType = Variable.LIST_TYPE;
|
||||
}
|
||||
if (varOrListField) {
|
||||
const currVarId = varOrListField.id;
|
||||
const currVarName = varOrListField.value;
|
||||
if (target.lookupVariableById(currVarId)) {
|
||||
// Found a variable with the id in either the target or the stage,
|
||||
// figure out which one.
|
||||
if (target.variables.hasOwnProperty(currVarId)) {
|
||||
// If the target has the variable, then check whether the stage
|
||||
// has one with the same name and type. If it does, then rename
|
||||
// this target specific variable so that there is a distinction.
|
||||
const stage = runtime.getTargetForStage();
|
||||
if (stage && stage.variables &&
|
||||
stage.lookupVariableByNameAndType(currVarName, varType)) {
|
||||
// TODO what should the new name be?
|
||||
const newName = StringUtil.unusedName(
|
||||
`${target.getName()}_${currVarName}`,
|
||||
target.getAllVariableNamesInScopeByType(varType));
|
||||
target.renameVariable(currVarId, newName);
|
||||
this.updateBlocksAfterVarRename(currVarId, newName);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const existingVar = target.lookupVariableByNameAndType(currVarName, varType);
|
||||
if (existingVar) {
|
||||
varOrListField.id = existingVar.id;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Keep blocks up to date after a variable gets renamed.
|
||||
* @param {string} varId The id of the variable that was renamed
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue