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
1 change: 1 addition & 0 deletions core/block_svg.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ goog.require('Blockly.ICopyable');
goog.require('Blockly.IDraggable');
goog.require('Blockly.Msg');
goog.require('Blockly.RenderedConnection');
goog.require('Blockly.serialization.blocks');
goog.require('Blockly.TabNavigateCursor');
goog.require('Blockly.Tooltip');
/** @suppress {extraRequire} */
Expand Down
2 changes: 1 addition & 1 deletion core/connection.js
Original file line number Diff line number Diff line change
Expand Up @@ -770,7 +770,7 @@ Blockly.Connection.prototype.createShadowBlock_ = function(attemptToConnect) {
}

if (shadowState) {
var blockShadow = Blockly.serialization.blocks.loadInternal(
var blockShadow = Blockly.serialization.blocks.appendInternal(
shadowState,
parentBlock.workspace,
{
Expand Down
4 changes: 2 additions & 2 deletions core/events/block_events.js
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,7 @@ Blockly.Events.Create.prototype.fromJson = function(json) {
Blockly.Events.Create.prototype.run = function(forward) {
var workspace = this.getEventWorkspace_();
if (forward) {
Blockly.serialization.blocks.load(this.json, workspace);
Blockly.serialization.blocks.append(this.json, workspace);
} else {
for (var i = 0, id; (id = this.ids[i]); i++) {
var block = workspace.getBlockById(id);
Expand Down Expand Up @@ -428,7 +428,7 @@ Blockly.Events.Delete.prototype.run = function(forward) {
}
}
} else {
Blockly.serialization.blocks.load(this.oldJson, workspace);
Blockly.serialization.blocks.append(this.oldJson, workspace);
}
};

Expand Down
7 changes: 4 additions & 3 deletions core/flyout_base.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ goog.require('Blockly.FlyoutMetricsManager');
goog.require('Blockly.Gesture');
goog.require('Blockly.IFlyout');
goog.require('Blockly.ScrollbarPair');
goog.require('Blockly.serialization.blocks');
goog.require('Blockly.Tooltip');
/** @suppress {extraRequire} */
goog.require('Blockly.Touch');
Expand Down Expand Up @@ -659,7 +660,7 @@ Blockly.Flyout.prototype.createButton_ = function(btnInfo, isLabel) {
* Create a block from the xml and permanently disable any blocks that were
* defined as disabled.
* @param {!Blockly.utils.toolbox.BlockInfo} blockInfo The info of the block.
* @return {!Blockly.BlockSvg} The block created from the blockXml.
* @return {!Blockly.BlockSvg} The block created from the blockInfo.
* @private
*/
Blockly.Flyout.prototype.createFlyoutBlock_ = function(blockInfo) {
Expand All @@ -679,7 +680,7 @@ Blockly.Flyout.prototype.createFlyoutBlock_ = function(blockInfo) {
blockInfo['enabled'] =
blockInfo['disabled'] !== 'true' && blockInfo['disabled'] !== true;
}
block = Blockly.serialization.blocks.load(
block = Blockly.serialization.blocks.append(
/** @type {Blockly.serialization.blocks.State} */ (blockInfo),
this.workspace_);
}
Expand Down Expand Up @@ -1068,7 +1069,7 @@ Blockly.Flyout.prototype.placeNewBlock_ = function(oldBlock) {
// Normallly this resizes leading to weird jumps. Save it for terminateDrag.
targetWorkspace.setResizesEnabled(false);
var block = /** @type {!Blockly.BlockSvg} */
(Blockly.serialization.blocks.load(json, targetWorkspace));
(Blockly.serialization.blocks.append(json, targetWorkspace));

this.positionNewBlock_(oldBlock, block);

Expand Down
22 changes: 11 additions & 11 deletions core/interfaces/i_serializer.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,17 @@ const Workspace = goog.requireType('Blockly.Workspace');


/**
* Serializes and deserializes a plugin.
* Serializes and deserializes a plugin or system.
* @interface
*/
class ISerializer {
constructor() {
/**
* A priority value used to determine the order of deserializing plugins.
* A priority value used to determine the order of deserializing state.
* More positive priorities are deserialized before less positive
* priorities. Eg if you have priorities (0, -10, 10, 100) the order of
* deserialiation will be (100, 10, 0, -10).
* If two plugins have the same priority, they are deserialized in an
* If two serializers have the same priority, they are deserialized in an
* arbitrary order relative to each other.
* @type {number}
*/
Expand All @@ -39,28 +39,28 @@ class ISerializer {
/* eslint-disable no-unused-vars, valid-jsdoc */

/**
* Saves the state of the plugin.
* @param {!Workspace} workspace The workspace the plugin to serialize is
* Saves the state of the plugin or system.
* @param {!Workspace} workspace The workspace the system to serialize is
* associated with.
* @return {?} A JS object containing the plugin's state, or null if
* @return {?} A JS object containing the system's state, or null if
* there is no state to record.
*/
save(workspace) {}

/* eslint-enable valid-jsdoc */

/**
* Loads the state of the plugin.
* @param {?} state The state of the plugin to deserialize. This will always
* Loads the state of the plugin or system.
* @param {?} state The state of the system to deserialize. This will always
* be non-null.
* @param {!Workspace} workspace The workspace the plugin to deserialize is
* @param {!Workspace} workspace The workspace the system to deserialize is
* associated with.
*/
load(state, workspace) {}

/**
* Clears the state of the plugin.
* @param {!Workspace} workspace The workspace the plugin to clear the state
* Clears the state of the plugin or system.
* @param {!Workspace} workspace The workspace the system to clear the state
* of is associated with.
*/
clear(workspace) {}
Expand Down
2 changes: 1 addition & 1 deletion core/registry.js
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ Blockly.registry.Type.SERIALIZER = new Blockly.registry.Type('serializer');
* an already registered item.
* @throws {Error} if the type or name is empty, a name with the given type has
* already been registered, or if the given class or object is not valid for
* it's type.
* its type.
* @template T
*/
Blockly.registry.register = function(
Expand Down
64 changes: 29 additions & 35 deletions core/serialization/blocks.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const Block = goog.requireType('Blockly.Block');
const Connection = goog.requireType('Blockly.Connection');
const Events = goog.require('Blockly.Events');
// eslint-disable-next-line no-unused-vars
const {ISerializer} = goog.requireType('Blockly.serialization.ISerializer');
const {ISerializer} = goog.require('Blockly.serialization.ISerializer');
const Size = goog.require('Blockly.utils.Size');
// eslint-disable-next-line no-unused-vars
const Workspace = goog.requireType('Blockly.Workspace');
Expand All @@ -30,7 +30,7 @@ const priorities = goog.require('Blockly.serialization.priorities');
const serializationRegistry = goog.require('Blockly.serialization.registry');


// TODO: Remove this once lint is fixed.
// TODO(#5160): Remove this once lint is fixed.
/* eslint-disable no-use-before-define */

/**
Expand All @@ -52,9 +52,6 @@ exports.ConnectionState = ConnectionState;
* y: (number|undefined),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not from this PR, but can we remove the TODO and the /* eslint-disable no-use-before-define */ above?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can, but lint still isn't fixed, so we'd have to reorganize the file :/ Right now higher level functions are defined before lower level procedures, and we'd have to flip it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahhh, makes sense. Do you plan on fixing before merging in to master? If not, then we should just make an issue to update it so we have something to reference in the TODO.

Copy link
Contributor Author

@BeksOmega BeksOmega Sep 10, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can link it to #5160 Does that sound good to you?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup, sounds great : )

* collapsed: (boolean|undefined),
* enabled: (boolean|undefined),
* editable: (boolean|undefined),
* deletable: (boolean|undefined),
* movable: (boolean|undefined),
* inline: (boolean|undefined),
* data: (string|undefined),
* extra-state: (*|undefined),
Expand Down Expand Up @@ -148,8 +145,8 @@ const saveAttributes = function(block, state) {

/**
* Adds the coordinates of the given block to the given state object.
* @param {!Block} block The block to base the coordinates on
* @param {!State} state The state object to append to
* @param {!Block} block The block to base the coordinates on.
* @param {!State} state The state object to append to.
*/
const saveCoords = function(block, state) {
const workspace = block.workspace;
Expand Down Expand Up @@ -206,19 +203,17 @@ const saveIcons = function(block, state) {
* state).
*/
const saveFields = function(block, state, doFullSerialization) {
let hasFieldState = false;
const fields = Object.create(null);
for (let i = 0; i < block.inputList.length; i++) {
const input = block.inputList[i];
for (let j = 0; j < input.fieldRow.length; j++) {
const field = input.fieldRow[j];
if (field.isSerializable()) {
hasFieldState = true;
fields[field.name] = field.saveState(doFullSerialization);
}
}
}
if (hasFieldState) {
if (Object.keys(fields).length) {
state['fields'] = fields;
}
};
Expand Down Expand Up @@ -301,10 +296,10 @@ const saveConnection = function(connection, doFullSerialization) {
* by the user. False by default.
* @return {!Block} The block that was just loaded.
*/
const load = function(state, workspace, {recordUndo = false} = {}) {
return loadInternal(state, workspace, {recordUndo});
const append = function(state, workspace, {recordUndo = false} = {}) {
return appendInternal(state, workspace, {recordUndo});
};
exports.load = load;
exports.append = append;

/**
* Loads the block represented by the given state into the given workspace.
Expand All @@ -318,13 +313,13 @@ exports.load = load;
* (boolean|undefined), recordUndo: (boolean|undefined)}=} param1
* parentConnection: If provided, the system will attempt to connect the
* block to this connection after it is created. Undefined by default.
* isShadow: The block will be set to a shadow block after it is created.
* False by default.
* isShadow: If true, the block will be set to a shadow block after it is
* created. False by default.
* recordUndo: If true, events triggered by this function will be undo-able
* by the user. False by default.
* @return {!Block} The block that was just loaded.
* @return {!Block} The block that was just appended.
*/
const loadInternal = function(
const appendInternal = function(
state,
workspace,
{
Expand All @@ -341,7 +336,7 @@ const loadInternal = function(
}
Events.disable();

const block = loadPrivate(state, workspace, {parentConnection, isShadow});
const block = appendPrivate(state, workspace, {parentConnection, isShadow});

Events.enable();
Events.fire(new (Events.get(Events.BLOCK_CREATE))(block));
Expand All @@ -361,24 +356,24 @@ const loadInternal = function(
return block;
};
/** @package */
exports.loadInternal = loadInternal;
exports.appendInternal = appendInternal;

/**
* Loads the block represented by the given state into the given workspace.
* This is defined privately so that it can be called recursively without firing
* eroneous events. Events (and other things we only want to occur on the top
* block) are handled by loadInternal.
* block) are handled by appendInternal.
* @param {!State} state The state of a block to deserialize into the workspace.
* @param {!Workspace} workspace The workspace to add the block to.
* @param {{parentConnection: (!Connection|undefined), isShadow:
* (boolean|undefined), recordUndo: (boolean|undefined)}=} param1
* @param {{parentConnection: (!Connection|undefined),
* isShadow: (boolean|undefined)}=} param1
* parentConnection: If provided, the system will attempt to connect the
* block to this connection after it is created. Undefined by default.
* isShadow: The block will be set to a shadow block after it is created.
* False by default.
* @return {!Block} The block that was just loaded.
* @return {!Block} The block that was just appended.
*/
const loadPrivate = function(
const appendPrivate = function(
state,
workspace,
{
Expand Down Expand Up @@ -460,9 +455,9 @@ const loadExtraState = function(block, state) {

/**
* Attempts to connect the block to the parent connection, if it exists.
* @param {(!Connection|undefined)} parentConnection The parent connnection to
* @param {(!Connection|undefined)} parentConnection The parent connection to
* try to connect the block to.
* @param {!Block} child The block to try to conecnt to the parent.
* @param {!Block} child The block to try to connect to the parent.
* @param {!State} state The state which defines the given block
*/
const tryToConnectParent = function(parentConnection, child, state) {
Expand Down Expand Up @@ -591,7 +586,7 @@ const loadNextBlocks = function(block, state) {
/**
* Applies the state defined by connectionState to the given connection, ie
* assigns shadows and attaches child blocks.
* @param {!Connection} connection The connection to serialize the
* @param {!Connection} connection The connection to deserialize the
* connected blocks of.
* @param {!ConnectionState} connectionState The object containing the state of
* any connected shadow block, or any connected real block.
Expand All @@ -601,7 +596,7 @@ const loadConnection = function(connection, connectionState) {
connection.setShadowState(connectionState['shadow']);
}
if (connectionState['block']) {
loadPrivate(
appendPrivate(
connectionState['block'],
connection.getSourceBlock().workspace,
{parentConnection: connection});
Expand All @@ -627,9 +622,8 @@ const initBlock = function(block, rendered) {
}
};

// Aliases to disambiguate saving/loading within the serializer.
// Alias to disambiguate saving within the serializer.
const saveBlock = save;
const loadBlock = load;

/**
* Serializer for saving and loading block state.
Expand All @@ -651,18 +645,18 @@ class BlockSerializer {
* the workspace's blocks, or null if there are no blocks.
*/
save(workspace) {
const blockState = [];
const blockStates = [];
for (const block of workspace.getTopBlocks(false)) {
const state = saveBlock(
block, {addCoordinates: true, doFullSerialization: false});
if (state) {
blockState.push(state);
blockStates.push(state);
}
}
if (blockState.length) {
if (blockStates.length) {
return {
'languageVersion': 0, // Currently unused.
'blocks': blockState
'blocks': blockStates
};
}
return null;
Expand All @@ -678,7 +672,7 @@ class BlockSerializer {
load(state, workspace) {
const blockStates = state['blocks'];
for (const state of blockStates) {
loadBlock(state, workspace, {recordUndo: Events.recordUndo});
append(state, workspace, {recordUndo: Events.recordUndo});
}
}

Expand Down
4 changes: 4 additions & 0 deletions core/serialization/exceptions.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ exports.DeserializationError = DeserializationError;
class MissingBlockType extends DeserializationError {
/**
* @param {!State} state The state object which is missing the block type.
* @package
*/
constructor(state) {
super(`Expected to find a 'type' property, defining the block type`);
Expand All @@ -50,6 +51,7 @@ class MissingConnection extends DeserializationError {
* 'IF0', or 'next'.
* @param {!Blockly.Block} block The block missing the connection.
* @param {!State} state The state object containing the bad connection.
* @package
*/
constructor(connection, block, state) {
super(`The block ${block.toDevString()} is missing a(n) ${connection}
Expand Down Expand Up @@ -82,6 +84,7 @@ class BadConnectionCheck extends DeserializationError {
* @param {!Blockly.Block} childBlock The child block that could not connect
* to its parent.
* @param {!State} childState The state object representing the child block.
* @package
*/
constructor(reason, childConnection, childBlock, childState) {
super(`The block ${childBlock.toDevString()} could not connect its
Expand Down Expand Up @@ -112,6 +115,7 @@ exports.BadConnectionCheck = BadConnectionCheck;
class RealChildOfShadow extends DeserializationError {
/**
* @param {!State} state The state object representing the real block.
* @package
*/
constructor(state) {
super(`Encountered a real block which is defined as a child of a shadow
Expand Down
Loading