Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 19 additions & 1 deletion blocks/procedures.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ const {Block} = goog.requireType('Blockly.Block');
// TODO (6248): Properly import the BlockDefinition type.
/* eslint-disable-next-line no-unused-vars */
const BlockDefinition = Object;
const {isProcedureBlock} = goog.require('Blockly.procedures.IProcedureModel');
const {ObservableProcedureModel} = goog.require('Blockly.procedures.ObservableProcedureModel');
const {ObservableParameterModel} = goog.require('Blockly.procedures.ObservableParameterModel');
const {config} = goog.require('Blockly.config');
Expand Down Expand Up @@ -576,7 +577,9 @@ const procedureDefMutator = {
const map = this.workspace.getProcedureMap();
const procedureId = state['procedureId'];
if (procedureId && procedureId != this.model_.getId() &&
map.has(procedureId)) {
map.has(procedureId) &&
(this.isInsertionMarker() ||
this.noBlockHasClaimedModel_(procedureId))) {
if (map.has(this.model_.getId())) {
map.delete(this.model_.getId());
}
Expand All @@ -598,6 +601,21 @@ const procedureDefMutator = {
Procedures.mutateCallers(this);
},

/**
* Returns true if there is no definition block currently associated with the
* given procedure ID. False otherwise.
* @param {string} procedureId The ID of the procedure to check for a claiming
* block.
* @return {boolean} True if there is no definition block currently associated
* with the given procedure ID. False otherwise.
*/
noBlockHasClaimedModel_(procedureId) {
const model = this.workspace.getProcedureMap().get(procedureId);
return this.workspace.getAllBlocks(false).every(
(b) => !isProcedureBlock(b) || !b.isProcedureDef() ||
b.getProcedureModel() !== model);
},

/**
* Populate the mutator's dialog with this block's components.
* @param {!Workspace} workspace Mutator's workspace.
Expand Down
2 changes: 2 additions & 0 deletions core/interfaces/i_procedure_block.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

import type {Block} from '../block.js';
import {IProcedureModel} from './i_procedure_model.js';
import * as goog from '../../closure/goog/goog.js';
goog.declareModuleId('Blockly.procedures.IProcedureModel');


/** The interface for a block which models a procedure. */
Expand Down
54 changes: 53 additions & 1 deletion tests/mocha/blocks/procedures_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1985,7 +1985,7 @@ suite('Procedures', function() {
});
});

suite('extra serialization test cases', function() {
suite('full workspace serialization test cases', function() {
test('definitions with parameters are properly rendered', function() {
Blockly.serialization.workspaces.load({
"blocks": {
Expand Down Expand Up @@ -2032,6 +2032,58 @@ suite('Procedures', function() {
assertDefBlockStructure(
this.workspace.getTopBlocks(false)[0], false, ['x'], ['varId']);
});
test(
'multiple definitions pointing to the same model end up with ' +
'different models',
function() {
Blockly.serialization.workspaces.load({
"blocks": {
"languageVersion": 0,
"blocks": [
{
"type": "procedures_defnoreturn",
"extraState": {
"procedureId": "procId",
},
"fields": {
"NAME": "do something",
},
},
{
"type": "procedures_defnoreturn",
"y": 10,
"extraState": {
"procedureId": "procId",
},
"fields": {
"NAME": "do something",
},
},
],
},
"procedures": [
{
"id": "procId",
"name": "do something",
"returnTypes": null,
},
],
}, this.workspace);
const def1 = this.workspace.getTopBlocks(true)[0];
const def2 = this.workspace.getTopBlocks(true)[1];
chai.assert.equal(
def1.getProcedureModel().getName(),
'do something',
'Expected the first procedure definition to have the name in XML');
chai.assert.equal(
def2.getProcedureModel().getName(),
'do something2',
'Expected the second procedure definition to be renamed');
chai.assert.notEqual(
def1.getProcedureModel(),
def2.getProcedureModel(),
'Expected the procedures to have different models');
});
});

const testSuites = [
Expand Down