chore: remove AnyDuringMigration from events (#6382)

* chore: remove AnyDuringMigration from events

* chore: format

* chore: lint

* chore: fix tests

* fix: correct types for JSON properties

* chore: fix tests

* refactor: replace exclamation markers with errors

* chore: fix build and tests

* chore: set event types as members, rather than in constructor

* chore: update comment

* chore: export new types

* chore: format

* chore: remove unnecessary override

* chore: change how we're overriding isBlank

* chore: remove unnecessary ?

* chore: remove non-null assertion in block move event

* chore: format

* chore: revert changes to isNull

* chore: format
This commit is contained in:
Beka Westberg
2022-09-27 15:08:05 -07:00
committed by GitHub
parent eb1b78663c
commit f678531389
36 changed files with 787 additions and 455 deletions

View File

@@ -147,16 +147,16 @@ function extractObjectFromEvent(
switch (e.type) {
case eventUtils.BLOCK_CREATE:
case eventUtils.BLOCK_MOVE:
object = workspace.getBlockById((e as BlockCreate | BlockMove).blockId);
object = workspace.getBlockById((e as BlockCreate | BlockMove).blockId!);
if (object) {
object = object.getRootBlock();
}
break;
case eventUtils.COMMENT_CREATE:
case eventUtils.COMMENT_MOVE:
object = workspace.getCommentById(
(e as CommentCreate | CommentMove).commentId) as
WorkspaceCommentSvg |
object =
workspace.getCommentById((e as CommentCreate | CommentMove).commentId!
) as WorkspaceCommentSvg |
null;
break;
}

View File

@@ -13,64 +13,90 @@ import * as goog from '../../closure/goog/goog.js';
goog.declareModuleId('Blockly.Events');
import {Abstract as AbstractEvent} from './events_abstract.js';
import {BlockBase} from './events_block_base.js';
import {BlockChange} from './events_block_change.js';
import {BlockCreate} from './events_block_create.js';
import {BlockDelete} from './events_block_delete.js';
import {BlockDrag} from './events_block_drag.js';
import {BlockMove} from './events_block_move.js';
import {BubbleOpen} from './events_bubble_open.js';
import {Click} from './events_click.js';
import {CommentBase} from './events_comment_base.js';
import {CommentChange} from './events_comment_change.js';
import {CommentCreate} from './events_comment_create.js';
import {Abstract as AbstractEvent, AbstractEventJson} from './events_abstract.js';
import {BlockBase, BlockBaseJson} from './events_block_base.js';
import {BlockChange, BlockChangeJson} from './events_block_change.js';
import {BlockCreate, BlockCreateJson} from './events_block_create.js';
import {BlockDelete, BlockDeleteJson} from './events_block_delete.js';
import {BlockDrag, BlockDragJson} from './events_block_drag.js';
import {BlockMove, BlockMoveJson} from './events_block_move.js';
import {BubbleOpen, BubbleOpenJson, BubbleType} from './events_bubble_open.js';
import {Click, ClickJson, ClickTarget} from './events_click.js';
import {CommentBase, CommentBaseJson} from './events_comment_base.js';
import {CommentChange, CommentChangeJson} from './events_comment_change.js';
import {CommentCreate, CommentCreateJson} from './events_comment_create.js';
import {CommentDelete} from './events_comment_delete.js';
import {CommentMove} from './events_comment_move.js';
import {MarkerMove} from './events_marker_move.js';
import {Selected} from './events_selected.js';
import {ThemeChange} from './events_theme_change.js';
import {ToolboxItemSelect} from './events_toolbox_item_select.js';
import {TrashcanOpen} from './events_trashcan_open.js';
import {CommentMove, CommentMoveJson} from './events_comment_move.js';
import {MarkerMove, MarkerMoveJson} from './events_marker_move.js';
import {Selected, SelectedJson} from './events_selected.js';
import {ThemeChange, ThemeChangeJson} from './events_theme_change.js';
import {ToolboxItemSelect, ToolboxItemSelectJson} from './events_toolbox_item_select.js';
import {TrashcanOpen, TrashcanOpenJson} from './events_trashcan_open.js';
import {Ui} from './events_ui.js';
import {UiBase} from './events_ui_base.js';
import {VarBase} from './events_var_base.js';
import {VarCreate} from './events_var_create.js';
import {VarDelete} from './events_var_delete.js';
import {VarRename} from './events_var_rename.js';
import {ViewportChange} from './events_viewport.js';
import {VarBase, VarBaseJson} from './events_var_base.js';
import {VarCreate, VarCreateJson} from './events_var_create.js';
import {VarDelete, VarDeleteJson} from './events_var_delete.js';
import {VarRename, VarRenameJson} from './events_var_rename.js';
import {ViewportChange, ViewportChangeJson} from './events_viewport.js';
import * as eventUtils from './utils.js';
import {FinishedLoading} from './workspace_events.js';
import {FinishedLoading, FinishedLoadingJson} from './workspace_events.js';
// Events.
export const Abstract = AbstractEvent;
export {AbstractEventJson};
export {BubbleOpen};
export {BubbleOpenJson};
export {BubbleType};
export {BlockBase};
export {BlockBaseJson};
export {BlockChange};
export {BlockChangeJson};
export {BlockCreate};
export {BlockCreateJson};
export {BlockDelete};
export {BlockDeleteJson};
export {BlockDrag};
export {BlockDragJson};
export {BlockMove};
export {BlockMoveJson};
export {Click};
export {ClickJson};
export {ClickTarget};
export {CommentBase};
export {CommentBaseJson};
export {CommentChange};
export {CommentChangeJson};
export {CommentCreate};
export {CommentCreateJson};
export {CommentDelete};
export {CommentMove};
export {CommentMoveJson};
export {FinishedLoading};
export {FinishedLoadingJson};
export {MarkerMove};
export {MarkerMoveJson};
export {Selected};
export {SelectedJson};
export {ThemeChange};
export {ThemeChangeJson};
export {ToolboxItemSelect};
export {ToolboxItemSelectJson};
export {TrashcanOpen};
export {TrashcanOpenJson};
export {Ui};
export {UiBase};
export {VarBase};
export {VarBaseJson};
export {VarCreate};
export {VarCreateJson};
export {VarDelete};
export {VarDeleteJson};
export {VarRename};
export {VarRenameJson};
export {ViewportChange};
export {ViewportChangeJson};
// Event types.
export const BLOCK_CHANGE = eventUtils.BLOCK_CHANGE;

View File

@@ -26,7 +26,7 @@ import * as eventUtils from './utils.js';
*/
export abstract class Abstract {
/** Whether or not the event is blank (to be populated by fromJson). */
isBlank: boolean|null = null;
abstract isBlank: boolean;
/** The workspace identifier for this event. */
workspaceId?: string = undefined;
@@ -37,7 +37,7 @@ export abstract class Abstract {
isUiEvent = false;
/** Type of this event. */
type?: string = undefined;
type = '';
/** @alias Blockly.Events.Abstract */
constructor() {
@@ -57,12 +57,11 @@ export abstract class Abstract {
*
* @returns JSON representation.
*/
toJson(): AnyDuringMigration {
const json = {'type': this.type};
if (this.group) {
(json as AnyDuringMigration)['group'] = this.group;
}
return json;
toJson(): AbstractEventJson {
return {
'type': this.type,
'group': this.group,
};
}
/**
@@ -70,9 +69,9 @@ export abstract class Abstract {
*
* @param json JSON representation.
*/
fromJson(json: AnyDuringMigration) {
fromJson(json: AbstractEventJson) {
this.isBlank = false;
this.group = json['group'];
this.group = json['group'] || '';
}
/**
@@ -112,3 +111,8 @@ export abstract class Abstract {
return workspace;
}
}
export interface AbstractEventJson {
type: string;
group: string;
}

View File

@@ -14,7 +14,7 @@ goog.declareModuleId('Blockly.Events.BlockBase');
import type {Block} from '../block.js';
import {Abstract as AbstractEvent} from './events_abstract.js';
import {Abstract as AbstractEvent, AbstractEventJson} from './events_abstract.js';
/**
@@ -23,9 +23,8 @@ import {Abstract as AbstractEvent} from './events_abstract.js';
* @alias Blockly.Events.BlockBase
*/
export class BlockBase extends AbstractEvent {
override isBlank: AnyDuringMigration;
blockId: string;
override workspaceId: string;
override isBlank = true;
blockId?: string;
/**
* @param opt_block The block this event corresponds to.
@@ -33,13 +32,15 @@ export class BlockBase extends AbstractEvent {
*/
constructor(opt_block?: Block) {
super();
this.isBlank = typeof opt_block === 'undefined';
this.isBlank = !!opt_block;
if (!opt_block) return;
/** The block ID for the block this event pertains to */
this.blockId = this.isBlank ? '' : opt_block!.id;
this.blockId = opt_block.id;
/** The workspace identifier for this event. */
this.workspaceId = this.isBlank ? '' : opt_block!.workspace.id;
this.workspaceId = opt_block.workspace.id;
}
/**
@@ -47,8 +48,13 @@ export class BlockBase extends AbstractEvent {
*
* @returns JSON representation.
*/
override toJson(): AnyDuringMigration {
const json = super.toJson();
override toJson(): AbstractEventJson {
const json = super.toJson() as BlockBaseJson;
if (!this.blockId) {
throw new Error(
'The block ID is undefined. Either pass a block to ' +
'the constructor, or call fromJson');
}
json['blockId'] = this.blockId;
return json;
}
@@ -58,8 +64,12 @@ export class BlockBase extends AbstractEvent {
*
* @param json JSON representation.
*/
override fromJson(json: AnyDuringMigration) {
override fromJson(json: BlockBaseJson) {
super.fromJson(json);
this.blockId = json['blockId'];
}
}
export interface BlockBaseJson extends AbstractEventJson {
blockId: string;
}

View File

@@ -17,7 +17,7 @@ import type {BlockSvg} from '../block_svg.js';
import * as registry from '../registry.js';
import * as Xml from '../xml.js';
import {BlockBase} from './events_block_base.js';
import {BlockBase, BlockBaseJson} from './events_block_base.js';
import * as eventUtils from './utils.js';
@@ -27,13 +27,11 @@ import * as eventUtils from './utils.js';
* @alias Blockly.Events.BlockChange
*/
export class BlockChange extends BlockBase {
override type: string;
// TODO(b/109816955): remove '!', see go/strict-prop-init-fix.
element!: string;
// TODO(b/109816955): remove '!', see go/strict-prop-init-fix.
name!: string|null;
oldValue: AnyDuringMigration;
newValue: AnyDuringMigration;
override type = eventUtils.BLOCK_CHANGE;
element?: string;
name?: string;
oldValue: unknown;
newValue: unknown;
/**
* @param opt_block The changed block. Undefined for a blank event.
@@ -44,19 +42,16 @@ export class BlockChange extends BlockBase {
*/
constructor(
opt_block?: Block, opt_element?: string, opt_name?: string|null,
opt_oldValue?: AnyDuringMigration, opt_newValue?: AnyDuringMigration) {
opt_oldValue?: unknown, opt_newValue?: unknown) {
super(opt_block);
/** Type of this event. */
this.type = eventUtils.BLOCK_CHANGE;
if (!opt_block) {
return; // Blank event to be populated by fromJson.
}
this.element = typeof opt_element === 'undefined' ? '' : opt_element;
this.name = typeof opt_name === 'undefined' ? '' : opt_name;
this.oldValue = typeof opt_oldValue === 'undefined' ? '' : opt_oldValue;
this.newValue = typeof opt_newValue === 'undefined' ? '' : opt_newValue;
this.element = opt_element;
this.name = opt_name || undefined;
this.oldValue = opt_oldValue;
this.newValue = opt_newValue;
}
/**
@@ -64,12 +59,15 @@ export class BlockChange extends BlockBase {
*
* @returns JSON representation.
*/
override toJson(): AnyDuringMigration {
const json = super.toJson();
json['element'] = this.element;
if (this.name) {
json['name'] = this.name;
override toJson(): BlockChangeJson {
const json = super.toJson() as BlockChangeJson;
if (!this.element) {
throw new Error(
'The changed element is undefined. Either pass an ' +
'element to the constructor, or call fromJson');
}
json['element'] = this.element;
json['name'] = this.name;
json['oldValue'] = this.oldValue;
json['newValue'] = this.newValue;
return json;
@@ -80,7 +78,7 @@ export class BlockChange extends BlockBase {
*
* @param json JSON representation.
*/
override fromJson(json: AnyDuringMigration) {
override fromJson(json: BlockChangeJson) {
super.fromJson(json);
this.element = json['element'];
this.name = json['name'];
@@ -104,10 +102,16 @@ export class BlockChange extends BlockBase {
*/
override run(forward: boolean) {
const workspace = this.getEventWorkspace_();
if (!this.blockId) {
throw new Error(
'The block ID is undefined. Either pass a block to ' +
'the constructor, or call fromJson');
}
const block = workspace.getBlockById(this.blockId);
if (!block) {
console.warn('Can\'t change non-existent block: ' + this.blockId);
return;
throw new Error(
'The associated block is undefined. Either pass a ' +
'block to the constructor, or call fromJson');
}
// Assume the block is rendered so that then we can check.
const blockSvg = block as BlockSvg;
@@ -176,4 +180,11 @@ export class BlockChange extends BlockBase {
}
}
export interface BlockChangeJson extends BlockBaseJson {
element: string;
name?: string;
newValue: unknown;
oldValue: unknown;
}
registry.register(registry.Type.EVENT, eventUtils.CHANGE, BlockChange);

View File

@@ -17,7 +17,7 @@ import * as registry from '../registry.js';
import * as blocks from '../serialization/blocks.js';
import * as Xml from '../xml.js';
import {BlockBase} from './events_block_base.js';
import {BlockBase, BlockBaseJson} from './events_block_base.js';
import * as eventUtils from './utils.js';
@@ -27,20 +27,15 @@ import * as eventUtils from './utils.js';
* @alias Blockly.Events.BlockCreate
*/
export class BlockCreate extends BlockBase {
override type: string;
xml: AnyDuringMigration;
// TODO(b/109816955): remove '!', see go/strict-prop-init-fix.
ids!: string[];
// TODO(b/109816955): remove '!', see go/strict-prop-init-fix.
json!: blocks.State;
override type = eventUtils.BLOCK_CREATE;
xml?: Element|DocumentFragment;
ids?: string[];
json?: blocks.State;
/** @param opt_block The created block. Undefined for a blank event. */
constructor(opt_block?: Block) {
super(opt_block);
/** Type of this event. */
this.type = eventUtils.BLOCK_CREATE;
if (!opt_block) {
return; // Blank event to be populated by fromJson.
}
@@ -62,8 +57,23 @@ export class BlockCreate extends BlockBase {
*
* @returns JSON representation.
*/
override toJson(): AnyDuringMigration {
const json = super.toJson();
override toJson(): BlockCreateJson {
const json = super.toJson() as BlockCreateJson;
if (!this.xml) {
throw new Error(
'The block XML is undefined. Either pass a block to ' +
'the constructor, or call fromJson');
}
if (!this.ids) {
throw new Error(
'The block IDs are undefined. Either pass a block to ' +
'the constructor, or call fromJson');
}
if (!this.json) {
throw new Error(
'The block JSON is undefined. Either pass a block to ' +
'the constructor, or call fromJson');
}
json['xml'] = Xml.domToText(this.xml);
json['ids'] = this.ids;
json['json'] = this.json;
@@ -78,7 +88,7 @@ export class BlockCreate extends BlockBase {
*
* @param json JSON representation.
*/
override fromJson(json: AnyDuringMigration) {
override fromJson(json: BlockCreateJson) {
super.fromJson(json);
this.xml = Xml.textToDom(json['xml']);
this.ids = json['ids'];
@@ -95,6 +105,16 @@ export class BlockCreate extends BlockBase {
*/
override run(forward: boolean) {
const workspace = this.getEventWorkspace_();
if (!this.json) {
throw new Error(
'The block JSON is undefined. Either pass a block to ' +
'the constructor, or call fromJson');
}
if (!this.ids) {
throw new Error(
'The block IDs are undefined. Either pass a block to ' +
'the constructor, or call fromJson');
}
if (forward) {
blocks.append(this.json, workspace);
} else {
@@ -112,4 +132,11 @@ export class BlockCreate extends BlockBase {
}
}
export interface BlockCreateJson extends BlockBaseJson {
xml: string;
ids: string[];
json: object;
recordUndo?: boolean;
}
registry.register(registry.Type.EVENT, eventUtils.CREATE, BlockCreate);

View File

@@ -17,7 +17,7 @@ import * as registry from '../registry.js';
import * as blocks from '../serialization/blocks.js';
import * as Xml from '../xml.js';
import {BlockBase} from './events_block_base.js';
import {BlockBase, BlockBaseJson} from './events_block_base.js';
import * as eventUtils from './utils.js';
@@ -27,22 +27,16 @@ import * as eventUtils from './utils.js';
* @alias Blockly.Events.BlockDelete
*/
export class BlockDelete extends BlockBase {
override type: string;
oldXml: AnyDuringMigration;
// TODO(b/109816955): remove '!', see go/strict-prop-init-fix.
ids!: string[];
// TODO(b/109816955): remove '!', see go/strict-prop-init-fix.
wasShadow!: boolean;
// TODO(b/109816955): remove '!', see go/strict-prop-init-fix.
oldJson!: blocks.State;
oldXml?: Element|DocumentFragment;
ids?: string[];
wasShadow?: boolean;
oldJson?: blocks.State;
override type = eventUtils.BLOCK_DELETE;
/** @param opt_block The deleted block. Undefined for a blank event. */
constructor(opt_block?: Block) {
super(opt_block);
/** Type of this event. */
this.type = eventUtils.BLOCK_DELETE;
if (!opt_block) {
return; // Blank event to be populated by fromJson.
}
@@ -71,8 +65,28 @@ export class BlockDelete extends BlockBase {
*
* @returns JSON representation.
*/
override toJson(): AnyDuringMigration {
const json = super.toJson();
override toJson(): BlockDeleteJson {
const json = super.toJson() as BlockDeleteJson;
if (!this.oldXml) {
throw new Error(
'The old block XML is undefined. Either pass a block ' +
'to the constructor, or call fromJson');
}
if (!this.ids) {
throw new Error(
'The block IDs are undefined. Either pass a block to ' +
'the constructor, or call fromJson');
}
if (this.wasShadow === undefined) {
throw new Error(
'Whether the block was a shadow is undefined. Either ' +
'pass a block to the constructor, or call fromJson');
}
if (!this.oldJson) {
throw new Error(
'The old block JSON is undefined. Either pass a block ' +
'to the constructor, or call fromJson');
}
json['oldXml'] = Xml.domToText(this.oldXml);
json['ids'] = this.ids;
json['wasShadow'] = this.wasShadow;
@@ -88,13 +102,13 @@ export class BlockDelete extends BlockBase {
*
* @param json JSON representation.
*/
override fromJson(json: AnyDuringMigration) {
override fromJson(json: BlockDeleteJson) {
super.fromJson(json);
this.oldXml = Xml.textToDom(json['oldXml']);
this.ids = json['ids'];
this.wasShadow =
json['wasShadow'] || this.oldXml.tagName.toLowerCase() === 'shadow';
this.oldJson = json['oldJson'] as blocks.State;
this.oldJson = json['oldJson'];
if (json['recordUndo'] !== undefined) {
this.recordUndo = json['recordUndo'];
}
@@ -107,6 +121,16 @@ export class BlockDelete extends BlockBase {
*/
override run(forward: boolean) {
const workspace = this.getEventWorkspace_();
if (!this.ids) {
throw new Error(
'The block IDs are undefined. Either pass a block to ' +
'the constructor, or call fromJson');
}
if (!this.oldJson) {
throw new Error(
'The old block JSON is undefined. Either pass a block ' +
'to the constructor, or call fromJson');
}
if (forward) {
for (let i = 0; i < this.ids.length; i++) {
const id = this.ids[i];
@@ -124,4 +148,12 @@ export class BlockDelete extends BlockBase {
}
}
export interface BlockDeleteJson extends BlockBaseJson {
oldXml: string;
ids: string[];
wasShadow: boolean;
oldJson: blocks.State;
recordUndo?: boolean;
}
registry.register(registry.Type.EVENT, eventUtils.DELETE, BlockDelete);

View File

@@ -14,7 +14,7 @@ goog.declareModuleId('Blockly.Events.BlockDrag');
import type {Block} from '../block.js';
import * as registry from '../registry.js';
import {AbstractEventJson} from './events_abstract.js';
import {UiBase} from './events_ui_base.js';
import * as eventUtils from './utils.js';
@@ -25,10 +25,10 @@ import * as eventUtils from './utils.js';
* @alias Blockly.Events.BlockDrag
*/
export class BlockDrag extends UiBase {
blockId: AnyDuringMigration;
blockId?: string;
isStart?: boolean;
blocks?: Block[];
override type: string;
override type = eventUtils.BLOCK_DRAG;
/**
* @param opt_block The top block in the stack that is being dragged.
@@ -41,16 +41,15 @@ export class BlockDrag extends UiBase {
constructor(opt_block?: Block, opt_isStart?: boolean, opt_blocks?: Block[]) {
const workspaceId = opt_block ? opt_block.workspace.id : undefined;
super(workspaceId);
this.blockId = opt_block ? opt_block.id : null;
if (!opt_block) return;
this.blockId = opt_block.id;
/** Whether this is the start of a block drag. */
this.isStart = opt_isStart;
/** The blocks affected by this drag event. */
this.blocks = opt_blocks;
/** Type of this event. */
this.type = eventUtils.BLOCK_DRAG;
}
/**
@@ -58,10 +57,23 @@ export class BlockDrag extends UiBase {
*
* @returns JSON representation.
*/
override toJson(): AnyDuringMigration {
const json = super.toJson();
override toJson(): BlockDragJson {
const json = super.toJson() as BlockDragJson;
if (this.isStart === undefined) {
throw new Error(
'Whether this event is the start of a drag is ' +
'undefined. Either pass the value to the constructor, or call ' +
'fromJson');
}
if (this.blockId === undefined) {
throw new Error(
'The block ID is undefined. Either pass a block to ' +
'the constructor, or call fromJson');
}
json['isStart'] = this.isStart;
json['blockId'] = this.blockId;
// TODO: I don't think we should actually apply the blocks array to the JSON
// object b/c they have functions and aren't actually serializable.
json['blocks'] = this.blocks;
return json;
}
@@ -71,7 +83,7 @@ export class BlockDrag extends UiBase {
*
* @param json JSON representation.
*/
override fromJson(json: AnyDuringMigration) {
override fromJson(json: BlockDragJson) {
super.fromJson(json);
this.isStart = json['isStart'];
this.blockId = json['blockId'];
@@ -79,4 +91,10 @@ export class BlockDrag extends UiBase {
}
}
export interface BlockDragJson extends AbstractEventJson {
isStart: boolean;
blockId: string;
blocks?: Block[];
}
registry.register(registry.Type.EVENT, eventUtils.BLOCK_DRAG, BlockDrag);

View File

@@ -17,15 +17,15 @@ import {ConnectionType} from '../connection_type.js';
import * as registry from '../registry.js';
import {Coordinate} from '../utils/coordinate.js';
import {BlockBase} from './events_block_base.js';
import {BlockBase, BlockBaseJson} from './events_block_base.js';
import * as eventUtils from './utils.js';
interface BlockLocation {
parentId: string;
inputName: string;
coordinate: Coordinate|null;
} // eslint-disable-line no-unused-vars
parentId?: string;
inputName?: string;
coordinate?: Coordinate;
}
/**
* Class for a block move event. Created before the move.
@@ -33,25 +33,19 @@ interface BlockLocation {
* @alias Blockly.Events.BlockMove
*/
export class BlockMove extends BlockBase {
override type: string;
// TODO(b/109816955): remove '!', see go/strict-prop-init-fix.
oldParentId!: string;
// TODO(b/109816955): remove '!', see go/strict-prop-init-fix.
oldInputName!: string;
// TODO(b/109816955): remove '!', see go/strict-prop-init-fix.
oldCoordinate!: Coordinate|null;
override type = eventUtils.BLOCK_MOVE;
oldParentId?: string;
oldInputName?: string;
oldCoordinate?: Coordinate;
newParentId: string|null = null;
newInputName: string|null = null;
newCoordinate: Coordinate|null = null;
newParentId?: string;
newInputName?: string;
newCoordinate?: Coordinate;
/** @param opt_block The moved block. Undefined for a blank event. */
constructor(opt_block?: Block) {
super(opt_block);
/** Type of this event. */
this.type = eventUtils.BLOCK_MOVE;
if (!opt_block) {
return;
}
@@ -72,17 +66,13 @@ export class BlockMove extends BlockBase {
*
* @returns JSON representation.
*/
override toJson(): AnyDuringMigration {
const json = super.toJson();
if (this.newParentId) {
json['newParentId'] = this.newParentId;
}
if (this.newInputName) {
json['newInputName'] = this.newInputName;
}
override toJson(): BlockMoveJson {
const json = super.toJson() as BlockMoveJson;
json['newParentId'] = this.newParentId;
json['newInputName'] = this.newInputName;
if (this.newCoordinate) {
json['newCoordinate'] = Math.round(this.newCoordinate.x) + ',' +
Math.round(this.newCoordinate.y);
json['newCoordinate'] = `${Math.round(this.newCoordinate.x)}, ` +
`${Math.round(this.newCoordinate.y)}`;
}
if (!this.recordUndo) {
json['recordUndo'] = this.recordUndo;
@@ -95,7 +85,7 @@ export class BlockMove extends BlockBase {
*
* @param json JSON representation.
*/
override fromJson(json: AnyDuringMigration) {
override fromJson(json: BlockMoveJson) {
super.fromJson(json);
this.newParentId = json['newParentId'];
this.newInputName = json['newInputName'];
@@ -124,19 +114,27 @@ export class BlockMove extends BlockBase {
*/
private currentLocation_(): BlockLocation {
const workspace = this.getEventWorkspace_();
if (!this.blockId) {
throw new Error(
'The block ID is undefined. Either pass a block to ' +
'the constructor, or call fromJson');
}
const block = workspace.getBlockById(this.blockId);
if (!block) {
throw new Error(
'The block associated with the block move event ' +
'could not be found');
}
const location = {} as BlockLocation;
const parent = block!.getParent();
const parent = block.getParent();
if (parent) {
location.parentId = parent.id;
// AnyDuringMigration because: Argument of type 'Block | null' is not
// assignable to parameter of type 'Block'.
const input = parent.getInputWithBlock(block as AnyDuringMigration);
const input = parent.getInputWithBlock(block);
if (input) {
location.inputName = input.name;
}
} else {
location.coordinate = block!.getRelativeToSurfaceXY();
location.coordinate = block.getRelativeToSurfaceXY();
}
return location;
}
@@ -159,6 +157,11 @@ export class BlockMove extends BlockBase {
*/
override run(forward: boolean) {
const workspace = this.getEventWorkspace_();
if (!this.blockId) {
throw new Error(
'The block ID is undefined. Either pass a block to ' +
'the constructor, or call fromJson');
}
const block = workspace.getBlockById(this.blockId);
if (!block) {
console.warn('Can\'t move non-existent block: ' + this.blockId);
@@ -206,4 +209,11 @@ export class BlockMove extends BlockBase {
}
}
export interface BlockMoveJson extends BlockBaseJson {
newParentId?: string;
newInputName?: string;
newCoordinate?: string;
recordUndo?: boolean;
}
registry.register(registry.Type.EVENT, eventUtils.MOVE, BlockMove);

View File

@@ -12,9 +12,9 @@
import * as goog from '../../closure/goog/goog.js';
goog.declareModuleId('Blockly.Events.BubbleOpen');
import type {AbstractEventJson} from './events_abstract.js';
import type {BlockSvg} from '../block_svg.js';
import * as registry from '../registry.js';
import {UiBase} from './events_ui_base.js';
import * as eventUtils from './utils.js';
@@ -25,10 +25,10 @@ import * as eventUtils from './utils.js';
* @alias Blockly.Events.BubbleOpen
*/
export class BubbleOpen extends UiBase {
blockId: string|null;
blockId?: string;
isOpen?: boolean;
bubbleType?: string;
override type: string;
bubbleType?: BubbleType;
override type = eventUtils.BUBBLE_OPEN;
/**
* @param opt_block The associated block. Undefined for a blank event.
@@ -38,19 +38,18 @@ export class BubbleOpen extends UiBase {
* 'warning'. Undefined for a blank event.
*/
constructor(
opt_block?: BlockSvg, opt_isOpen?: boolean, opt_bubbleType?: string) {
opt_block?: BlockSvg, opt_isOpen?: boolean, opt_bubbleType?: BubbleType) {
const workspaceId = opt_block ? opt_block.workspace.id : undefined;
super(workspaceId);
this.blockId = opt_block ? opt_block.id : null;
if (!opt_block) return;
this.blockId = opt_block.id;
/** Whether the bubble is opening (false if closing). */
this.isOpen = opt_isOpen;
/** The type of bubble. One of 'mutator', 'comment', or 'warning'. */
this.bubbleType = opt_bubbleType;
/** Type of this event. */
this.type = eventUtils.BUBBLE_OPEN;
}
/**
@@ -58,11 +57,23 @@ export class BubbleOpen extends UiBase {
*
* @returns JSON representation.
*/
override toJson(): AnyDuringMigration {
const json = super.toJson();
override toJson(): BubbleOpenJson {
const json = super.toJson() as BubbleOpenJson;
if (this.isOpen === undefined) {
throw new Error(
'Whether this event is for opening the bubble is ' +
'undefined. Either pass the value to the constructor, or call ' +
'fromJson');
}
if (!this.bubbleType) {
throw new Error(
'The type of bubble is undefined. Either pass the ' +
'value to the constructor, or call ' +
'fromJson');
}
json['isOpen'] = this.isOpen;
json['bubbleType'] = this.bubbleType;
json['blockId'] = this.blockId;
json['blockId'] = this.blockId || '';
return json;
}
@@ -71,7 +82,7 @@ export class BubbleOpen extends UiBase {
*
* @param json JSON representation.
*/
override fromJson(json: AnyDuringMigration) {
override fromJson(json: BubbleOpenJson) {
super.fromJson(json);
this.isOpen = json['isOpen'];
this.bubbleType = json['bubbleType'];
@@ -79,4 +90,16 @@ export class BubbleOpen extends UiBase {
}
}
export enum BubbleType {
MUTATOR = 'mutator',
COMMENT = 'comment',
WARNING = 'warning',
}
export interface BubbleOpenJson extends AbstractEventJson {
isOpen: boolean;
bubbleType: BubbleType;
blockId: string;
}
registry.register(registry.Type.EVENT, eventUtils.BUBBLE_OPEN, BubbleOpen);

View File

@@ -14,6 +14,7 @@ goog.declareModuleId('Blockly.Events.Click');
import type {Block} from '../block.js';
import * as registry from '../registry.js';
import {AbstractEventJson} from './events_abstract.js';
import {UiBase} from './events_ui_base.js';
import * as eventUtils from './utils.js';
@@ -25,9 +26,9 @@ import * as eventUtils from './utils.js';
* @alias Blockly.Events.Click
*/
export class Click extends UiBase {
blockId: AnyDuringMigration;
targetType?: string;
override type: string;
blockId?: string;
targetType?: ClickTarget;
override type = eventUtils.CLICK;
/**
* @param opt_block The affected block. Null for click events that do not have
@@ -40,19 +41,17 @@ export class Click extends UiBase {
*/
constructor(
opt_block?: Block|null, opt_workspaceId?: string|null,
opt_targetType?: string) {
opt_targetType?: ClickTarget) {
let workspaceId = opt_block ? opt_block.workspace.id : opt_workspaceId;
if (workspaceId === null) {
workspaceId = undefined;
}
super(workspaceId);
this.blockId = opt_block ? opt_block.id : null;
this.blockId = opt_block ? opt_block.id : undefined;
/** The type of element targeted by this click event. */
this.targetType = opt_targetType;
/** Type of this event. */
this.type = eventUtils.CLICK;
}
/**
@@ -60,12 +59,15 @@ export class Click extends UiBase {
*
* @returns JSON representation.
*/
override toJson(): AnyDuringMigration {
const json = super.toJson();
json['targetType'] = this.targetType;
if (this.blockId) {
json['blockId'] = this.blockId;
override toJson(): ClickJson {
const json = super.toJson() as ClickJson;
if (!this.targetType) {
throw new Error(
'The click target type is undefined. Either pass a block to ' +
'the constructor, or call fromJson');
}
json['targetType'] = this.targetType;
json['blockId'] = this.blockId;
return json;
}
@@ -74,11 +76,22 @@ export class Click extends UiBase {
*
* @param json JSON representation.
*/
override fromJson(json: AnyDuringMigration) {
override fromJson(json: ClickJson) {
super.fromJson(json);
this.targetType = json['targetType'];
this.blockId = json['blockId'];
}
}
export enum ClickTarget {
BLOCK = 'block',
WORKSPACE = 'workspace',
ZOOM_CONTROLS = 'zoom_controls',
}
export interface ClickJson extends AbstractEventJson {
targetType: ClickTarget;
blockId?: string;
}
registry.register(registry.Type.EVENT, eventUtils.CLICK, Click);

View File

@@ -16,7 +16,7 @@ import * as utilsXml from '../utils/xml.js';
import type {WorkspaceComment} from '../workspace_comment.js';
import * as Xml from '../xml.js';
import {Abstract as AbstractEvent} from './events_abstract.js';
import {Abstract as AbstractEvent, AbstractEventJson} from './events_abstract.js';
import type {CommentCreate} from './events_comment_create.js';
import type {CommentDelete} from './events_comment_delete.js';
import * as eventUtils from './utils.js';
@@ -28,9 +28,8 @@ import * as eventUtils from './utils.js';
* @alias Blockly.Events.CommentBase
*/
export class CommentBase extends AbstractEvent {
override isBlank: boolean;
commentId: string;
override workspaceId: string;
override isBlank = true;
commentId?: string;
/**
* @param opt_comment The comment this event corresponds to. Undefined for a
@@ -39,13 +38,15 @@ export class CommentBase extends AbstractEvent {
constructor(opt_comment?: WorkspaceComment) {
super();
/** Whether or not an event is blank. */
this.isBlank = typeof opt_comment === 'undefined';
this.isBlank = !opt_comment;
if (!opt_comment) return;
/** The ID of the comment this event pertains to. */
this.commentId = this.isBlank ? '' : opt_comment!.id;
this.commentId = opt_comment.id;
/** The workspace identifier for this event. */
this.workspaceId = this.isBlank ? '' : opt_comment!.workspace.id;
this.workspaceId = opt_comment.workspace.id;
/**
* The event group ID for the group this event belongs to. Groups define
@@ -63,11 +64,14 @@ export class CommentBase extends AbstractEvent {
*
* @returns JSON representation.
*/
override toJson(): AnyDuringMigration {
const json = super.toJson();
if (this.commentId) {
json['commentId'] = this.commentId;
override toJson(): CommentBaseJson {
const json = super.toJson() as CommentBaseJson;
if (!this.commentId) {
throw new Error(
'The comment ID is undefined. Either pass a comment to ' +
'the constructor, or call fromJson');
}
json['commentId'] = this.commentId;
return json;
}
@@ -76,7 +80,7 @@ export class CommentBase extends AbstractEvent {
*
* @param json JSON representation.
*/
override fromJson(json: AnyDuringMigration) {
override fromJson(json: CommentBaseJson) {
super.fromJson(json);
this.commentId = json['commentId'];
}
@@ -92,9 +96,17 @@ export class CommentBase extends AbstractEvent {
const workspace = event.getEventWorkspace_();
if (create) {
const xmlElement = utilsXml.createElement('xml');
if (!event.xml) {
throw new Error('Ecountered a comment event without proper xml');
}
xmlElement.appendChild(event.xml);
Xml.domToWorkspace(xmlElement, workspace);
} else {
if (!event.commentId) {
throw new Error(
'The comment ID is undefined. Either pass a comment to ' +
'the constructor, or call fromJson');
}
const comment = workspace.getCommentById(event.commentId);
if (comment) {
comment.dispose();
@@ -106,3 +118,7 @@ export class CommentBase extends AbstractEvent {
}
}
}
export interface CommentBaseJson extends AbstractEventJson {
commentId: string;
}

View File

@@ -15,7 +15,7 @@ goog.declareModuleId('Blockly.Events.CommentChange');
import * as registry from '../registry.js';
import type {WorkspaceComment} from '../workspace_comment.js';
import {CommentBase} from './events_comment_base.js';
import {CommentBase, CommentBaseJson} from './events_comment_base.js';
import * as eventUtils from './utils.js';
@@ -25,12 +25,9 @@ import * as eventUtils from './utils.js';
* @alias Blockly.Events.CommentChange
*/
export class CommentChange extends CommentBase {
override type: string;
// TODO(b/109816955): remove '!', see go/strict-prop-init-fix.
oldContents_!: string;
// TODO(b/109816955): remove '!', see go/strict-prop-init-fix.
newContents_!: string;
override type = eventUtils.COMMENT_CHANGE;
oldContents_?: string;
newContents_?: string;
/**
* @param opt_comment The comment that is being changed. Undefined for a
@@ -43,9 +40,6 @@ export class CommentChange extends CommentBase {
opt_newContents?: string) {
super(opt_comment);
/** Type of this event. */
this.type = eventUtils.COMMENT_CHANGE;
if (!opt_comment) {
return; // Blank event to be populated by fromJson.
}
@@ -61,8 +55,18 @@ export class CommentChange extends CommentBase {
*
* @returns JSON representation.
*/
override toJson(): AnyDuringMigration {
const json = super.toJson();
override toJson(): CommentChangeJson {
const json = super.toJson() as CommentChangeJson;
if (!this.oldContents_) {
throw new Error(
'The old contents is undefined. Either pass a value to ' +
'the constructor, or call fromJson');
}
if (!this.newContents_) {
throw new Error(
'The new contents is undefined. Either pass a value to ' +
'the constructor, or call fromJson');
}
json['oldContents'] = this.oldContents_;
json['newContents'] = this.newContents_;
return json;
@@ -73,7 +77,7 @@ export class CommentChange extends CommentBase {
*
* @param json JSON representation.
*/
override fromJson(json: AnyDuringMigration) {
override fromJson(json: CommentChangeJson) {
super.fromJson(json);
this.oldContents_ = json['oldContents'];
this.newContents_ = json['newContents'];
@@ -95,16 +99,35 @@ export class CommentChange extends CommentBase {
*/
override run(forward: boolean) {
const workspace = this.getEventWorkspace_();
if (!this.commentId) {
throw new Error(
'The comment ID is undefined. Either pass a comment to ' +
'the constructor, or call fromJson');
}
const comment = workspace.getCommentById(this.commentId);
if (!comment) {
console.warn('Can\'t change non-existent comment: ' + this.commentId);
return;
}
const contents = forward ? this.newContents_ : this.oldContents_;
if (!contents) {
if (forward) {
throw new Error(
'The new contents is undefined. Either pass a value to ' +
'the constructor, or call fromJson');
}
throw new Error(
'The old contents is undefined. Either pass a value to ' +
'the constructor, or call fromJson');
}
comment.setContent(contents);
}
}
export interface CommentChangeJson extends CommentBaseJson {
oldContents: string;
newContents: string;
}
registry.register(
registry.Type.EVENT, eventUtils.COMMENT_CHANGE, CommentChange);

View File

@@ -16,7 +16,7 @@ import * as registry from '../registry.js';
import type {WorkspaceComment} from '../workspace_comment.js';
import * as Xml from '../xml.js';
import {CommentBase} from './events_comment_base.js';
import {CommentBase, CommentBaseJson} from './events_comment_base.js';
import * as eventUtils from './utils.js';
@@ -26,9 +26,9 @@ import * as eventUtils from './utils.js';
* @alias Blockly.Events.CommentCreate
*/
export class CommentCreate extends CommentBase {
override type: string;
override type = eventUtils.COMMENT_CREATE;
xml: AnyDuringMigration;
xml?: Element|DocumentFragment;
/**
* @param opt_comment The created comment.
@@ -37,9 +37,6 @@ export class CommentCreate extends CommentBase {
constructor(opt_comment?: WorkspaceComment) {
super(opt_comment);
/** Type of this event. */
this.type = eventUtils.COMMENT_CREATE;
if (!opt_comment) {
return;
}
@@ -53,8 +50,13 @@ export class CommentCreate extends CommentBase {
*
* @returns JSON representation.
*/
override toJson(): AnyDuringMigration {
const json = super.toJson();
override toJson(): CommentCreateJson {
const json = super.toJson() as CommentCreateJson;
if (!this.xml) {
throw new Error(
'The comment XML is undefined. Either pass a comment to ' +
'the constructor, or call fromJson');
}
json['xml'] = Xml.domToText(this.xml);
return json;
}
@@ -64,7 +66,7 @@ export class CommentCreate extends CommentBase {
*
* @param json JSON representation.
*/
override fromJson(json: AnyDuringMigration) {
override fromJson(json: CommentCreateJson) {
super.fromJson(json);
this.xml = Xml.textToDom(json['xml']);
}
@@ -79,5 +81,9 @@ export class CommentCreate extends CommentBase {
}
}
export interface CommentCreateJson extends CommentBaseJson {
xml: string;
}
registry.register(
registry.Type.EVENT, eventUtils.COMMENT_CREATE, CommentCreate);

View File

@@ -25,8 +25,8 @@ import * as eventUtils from './utils.js';
* @alias Blockly.Events.CommentDelete
*/
export class CommentDelete extends CommentBase {
override type: string;
xml: AnyDuringMigration;
override type = eventUtils.COMMENT_DELETE;
xml?: Element;
/**
* @param opt_comment The deleted comment.
@@ -35,34 +35,12 @@ export class CommentDelete extends CommentBase {
constructor(opt_comment?: WorkspaceComment) {
super(opt_comment);
/** Type of this event. */
this.type = eventUtils.COMMENT_DELETE;
if (!opt_comment) {
return; // Blank event to be populated by fromJson.
}
this.xml = opt_comment.toXmlWithXY();
}
// TODO (#1266): "Full" and "minimal" serialization.
/**
* Encode the event as JSON.
*
* @returns JSON representation.
*/
override toJson(): AnyDuringMigration {
const json = super.toJson();
return json;
}
/**
* Decode the JSON event.
*
* @param json JSON representation.
*/
override fromJson(json: AnyDuringMigration) {
super.fromJson(json);
}
/**
* Run a creation event.

View File

@@ -16,7 +16,7 @@ import * as registry from '../registry.js';
import {Coordinate} from '../utils/coordinate.js';
import type {WorkspaceComment} from '../workspace_comment.js';
import {CommentBase} from './events_comment_base.js';
import {CommentBase, CommentBaseJson} from './events_comment_base.js';
import * as eventUtils from './utils.js';
@@ -26,17 +26,11 @@ import * as eventUtils from './utils.js';
* @alias Blockly.Events.CommentMove
*/
export class CommentMove extends CommentBase {
override type: string;
// TODO(b/109816955): remove '!', see go/strict-prop-init-fix.
comment_!: WorkspaceComment;
// TODO(b/109816955): remove '!', see go/strict-prop-init-fix.
oldCoordinate_!: Coordinate;
override type = eventUtils.COMMENT_MOVE;
comment_?: WorkspaceComment;
oldCoordinate_?: Coordinate;
/** The location after the move, in workspace coordinates. */
// AnyDuringMigration because: Type 'null' is not assignable to type
// 'Coordinate'.
newCoordinate_: Coordinate = null as AnyDuringMigration;
newCoordinate_?: Coordinate;
/**
* @param opt_comment The comment that is being moved. Undefined for a blank
@@ -45,16 +39,12 @@ export class CommentMove extends CommentBase {
constructor(opt_comment?: WorkspaceComment) {
super(opt_comment);
/** Type of this event. */
this.type = eventUtils.COMMENT_MOVE;
if (!opt_comment) {
return; // Blank event to be populated by fromJson.
}
/**
* The comment that is being moved. Will be cleared after recording the new
* location.
* The comment that is being moved.
*/
this.comment_ = opt_comment;
@@ -67,15 +57,17 @@ export class CommentMove extends CommentBase {
* called once.
*/
recordNew() {
if (!this.comment_) {
if (this.newCoordinate_) {
throw Error(
'Tried to record the new position of a comment on the ' +
'same event twice.');
}
if (!this.comment_) {
throw new Error(
'The comment is undefined. Pass a comment to ' +
'the constructor if you want to use the record functionality');
}
this.newCoordinate_ = this.comment_.getXY();
// AnyDuringMigration because: Type 'null' is not assignable to type
// 'WorkspaceComment'.
this.comment_ = null as AnyDuringMigration;
}
/**
@@ -94,16 +86,22 @@ export class CommentMove extends CommentBase {
*
* @returns JSON representation.
*/
override toJson(): AnyDuringMigration {
const json = super.toJson();
if (this.oldCoordinate_) {
json['oldCoordinate'] = Math.round(this.oldCoordinate_.x) + ',' +
Math.round(this.oldCoordinate_.y);
override toJson(): CommentMoveJson {
const json = super.toJson() as CommentMoveJson;
if (!this.oldCoordinate_) {
throw new Error(
'The old comment position is undefined. Either pass a comment to ' +
'the constructor, or call fromJson');
}
if (this.newCoordinate_) {
json['newCoordinate'] = Math.round(this.newCoordinate_.x) + ',' +
Math.round(this.newCoordinate_.y);
if (!this.newCoordinate_) {
throw new Error(
'The new comment position is undefined. Either call recordNew, or ' +
'call fromJson');
}
json['oldCoordinate'] = `${Math.round(this.oldCoordinate_.x)}, ` +
`${Math.round(this.oldCoordinate_.y)}`;
json['newCoordinate'] = Math.round(this.newCoordinate_.x) + ',' +
Math.round(this.newCoordinate_.y);
return json;
}
@@ -112,17 +110,12 @@ export class CommentMove extends CommentBase {
*
* @param json JSON representation.
*/
override fromJson(json: AnyDuringMigration) {
override fromJson(json: CommentMoveJson) {
super.fromJson(json);
if (json['oldCoordinate']) {
const xy = json['oldCoordinate'].split(',');
this.oldCoordinate_ = new Coordinate(Number(xy[0]), Number(xy[1]));
}
if (json['newCoordinate']) {
const xy = json['newCoordinate'].split(',');
this.newCoordinate_ = new Coordinate(Number(xy[0]), Number(xy[1]));
}
let xy = json['oldCoordinate'].split(',');
this.oldCoordinate_ = new Coordinate(Number(xy[0]), Number(xy[1]));
xy = json['newCoordinate'].split(',');
this.newCoordinate_ = new Coordinate(Number(xy[0]), Number(xy[1]));
}
/**
@@ -141,6 +134,11 @@ export class CommentMove extends CommentBase {
*/
override run(forward: boolean) {
const workspace = this.getEventWorkspace_();
if (!this.commentId) {
throw new Error(
'The comment ID is undefined. Either pass a comment to ' +
'the constructor, or call fromJson');
}
const comment = workspace.getCommentById(this.commentId);
if (!comment) {
console.warn('Can\'t move non-existent comment: ' + this.commentId);
@@ -148,10 +146,21 @@ export class CommentMove extends CommentBase {
}
const target = forward ? this.newCoordinate_ : this.oldCoordinate_;
if (!target) {
throw new Error(
'Either oldCoordinate_ or newCoordinate_ is undefined. ' +
'Either pass a comment to the constructor and call recordNew, ' +
'or call fromJson');
}
// TODO: Check if the comment is being dragged, and give up if so.
const current = comment.getXY();
comment.moveBy(target.x - current.x, target.y - current.y);
}
}
export interface CommentMoveJson extends CommentBaseJson {
oldCoordinate: string;
newCoordinate: string;
}
registry.register(registry.Type.EVENT, eventUtils.COMMENT_MOVE, CommentMove);

View File

@@ -16,6 +16,7 @@ import type {Block} from '../block.js';
import {ASTNode} from '../keyboard_nav/ast_node.js';
import * as registry from '../registry.js';
import type {Workspace} from '../workspace.js';
import {AbstractEventJson} from './events_abstract.js';
import {UiBase} from './events_ui_base.js';
import * as eventUtils from './utils.js';
@@ -27,11 +28,11 @@ import * as eventUtils from './utils.js';
* @alias Blockly.Events.MarkerMove
*/
export class MarkerMove extends UiBase {
blockId: string|null;
oldNode?: ASTNode|null;
blockId?: string;
oldNode?: ASTNode;
newNode?: ASTNode;
isCursor?: boolean;
override type: string;
override type = eventUtils.MARKER_MOVE;
/**
* @param opt_block The affected block. Null if current node is of type
@@ -52,20 +53,17 @@ export class MarkerMove extends UiBase {
}
super(workspaceId);
/** The workspace identifier for this event. */
this.blockId = opt_block ? opt_block.id : null;
/** The block identifier for this event. */
this.blockId = opt_block?.id;
/** The old node the marker used to be on. */
this.oldNode = opt_oldNode;
this.oldNode = opt_oldNode || undefined;
/** The new node the marker is now on. */
this.newNode = opt_newNode;
/** Whether this is a cursor event. */
this.isCursor = isCursor;
/** Type of this event. */
this.type = eventUtils.MARKER_MOVE;
}
/**
@@ -73,8 +71,18 @@ export class MarkerMove extends UiBase {
*
* @returns JSON representation.
*/
override toJson(): AnyDuringMigration {
const json = super.toJson();
override toJson(): MarkerMoveJson {
const json = super.toJson() as MarkerMoveJson;
if (this.isCursor === undefined) {
throw new Error(
'Whether this is a cursor event or not is undefined. Either pass ' +
'a value to the constructor, or call fromJson');
}
if (!this.newNode) {
throw new Error(
'The new node is undefined. Either pass a node to ' +
'the constructor, or call fromJson');
}
json['isCursor'] = this.isCursor;
json['blockId'] = this.blockId;
json['oldNode'] = this.oldNode;
@@ -87,7 +95,7 @@ export class MarkerMove extends UiBase {
*
* @param json JSON representation.
*/
override fromJson(json: AnyDuringMigration) {
override fromJson(json: MarkerMoveJson) {
super.fromJson(json);
this.isCursor = json['isCursor'];
this.blockId = json['blockId'];
@@ -96,4 +104,11 @@ export class MarkerMove extends UiBase {
}
}
export interface MarkerMoveJson extends AbstractEventJson {
isCursor: boolean;
blockId?: string;
oldNode?: ASTNode;
newNode: ASTNode;
}
registry.register(registry.Type.EVENT, eventUtils.MARKER_MOVE, MarkerMove);

View File

@@ -13,6 +13,7 @@ import * as goog from '../../closure/goog/goog.js';
goog.declareModuleId('Blockly.Events.Selected');
import * as registry from '../registry.js';
import {AbstractEventJson} from './events_abstract.js';
import {UiBase} from './events_ui_base.js';
import * as eventUtils from './utils.js';
@@ -24,9 +25,9 @@ import * as eventUtils from './utils.js';
* @alias Blockly.Events.Selected
*/
export class Selected extends UiBase {
oldElementId?: string|null;
newElementId?: string|null;
override type: string;
oldElementId?: string;
newElementId?: string;
override type = eventUtils.SELECTED;
/**
* @param opt_oldElementId The ID of the previously selected element. Null if
@@ -41,14 +42,11 @@ export class Selected extends UiBase {
opt_workspaceId?: string) {
super(opt_workspaceId);
/** The ID of the last selected element. */
this.oldElementId = opt_oldElementId;
/** The id of the last selected element. */
this.oldElementId = opt_oldElementId ?? undefined;
/** The ID of the selected element. */
this.newElementId = opt_newElementId;
/** Type of this event. */
this.type = eventUtils.SELECTED;
/** The id of the selected element. */
this.newElementId = opt_newElementId ?? undefined;
}
/**
@@ -56,8 +54,8 @@ export class Selected extends UiBase {
*
* @returns JSON representation.
*/
override toJson(): AnyDuringMigration {
const json = super.toJson();
override toJson(): SelectedJson {
const json = super.toJson() as SelectedJson;
json['oldElementId'] = this.oldElementId;
json['newElementId'] = this.newElementId;
return json;
@@ -68,11 +66,16 @@ export class Selected extends UiBase {
*
* @param json JSON representation.
*/
override fromJson(json: AnyDuringMigration) {
override fromJson(json: SelectedJson) {
super.fromJson(json);
this.oldElementId = json['oldElementId'];
this.newElementId = json['newElementId'];
}
}
export interface SelectedJson extends AbstractEventJson {
oldElementId?: string;
newElementId?: string;
}
registry.register(registry.Type.EVENT, eventUtils.SELECTED, Selected);

View File

@@ -13,7 +13,7 @@ import * as goog from '../../closure/goog/goog.js';
goog.declareModuleId('Blockly.Events.ThemeChange');
import * as registry from '../registry.js';
import {AbstractEventJson} from './events_abstract.js';
import {UiBase} from './events_ui_base.js';
import * as eventUtils from './utils.js';
@@ -25,7 +25,7 @@ import * as eventUtils from './utils.js';
*/
export class ThemeChange extends UiBase {
themeName?: string;
override type: string;
override type = eventUtils.THEME_CHANGE;
/**
* @param opt_themeName The theme name. Undefined for a blank event.
@@ -37,9 +37,6 @@ export class ThemeChange extends UiBase {
/** The theme name. */
this.themeName = opt_themeName;
/** Type of this event. */
this.type = eventUtils.THEME_CHANGE;
}
/**
@@ -47,8 +44,13 @@ export class ThemeChange extends UiBase {
*
* @returns JSON representation.
*/
override toJson(): AnyDuringMigration {
const json = super.toJson();
override toJson(): ThemeChangeJson {
const json = super.toJson() as ThemeChangeJson;
if (!this.themeName) {
throw new Error(
'The theme name is undefined. Either pass a theme name to ' +
'the constructor, or call fromJson');
}
json['themeName'] = this.themeName;
return json;
}
@@ -58,10 +60,14 @@ export class ThemeChange extends UiBase {
*
* @param json JSON representation.
*/
override fromJson(json: AnyDuringMigration) {
override fromJson(json: ThemeChangeJson) {
super.fromJson(json);
this.themeName = json['themeName'];
}
}
export interface ThemeChangeJson extends AbstractEventJson {
themeName: string;
}
registry.register(registry.Type.EVENT, eventUtils.THEME_CHANGE, ThemeChange);

View File

@@ -13,7 +13,7 @@ import * as goog from '../../closure/goog/goog.js';
goog.declareModuleId('Blockly.Events.ToolboxItemSelect');
import * as registry from '../registry.js';
import {AbstractEventJson} from './events_abstract.js';
import {UiBase} from './events_ui_base.js';
import * as eventUtils from './utils.js';
@@ -24,9 +24,9 @@ import * as eventUtils from './utils.js';
* @alias Blockly.Events.ToolboxItemSelect
*/
export class ToolboxItemSelect extends UiBase {
oldItem?: string|null;
newItem?: string|null;
override type: string;
oldItem?: string;
newItem?: string;
override type = eventUtils.TOOLBOX_ITEM_SELECT;
/**
* @param opt_oldItem The previously selected toolbox item.
@@ -42,13 +42,10 @@ export class ToolboxItemSelect extends UiBase {
super(opt_workspaceId);
/** The previously selected toolbox item. */
this.oldItem = opt_oldItem;
this.oldItem = opt_oldItem ?? undefined;
/** The newly selected toolbox item. */
this.newItem = opt_newItem;
/** Type of this event. */
this.type = eventUtils.TOOLBOX_ITEM_SELECT;
this.newItem = opt_newItem ?? undefined;
}
/**
@@ -56,8 +53,8 @@ export class ToolboxItemSelect extends UiBase {
*
* @returns JSON representation.
*/
override toJson(): AnyDuringMigration {
const json = super.toJson();
override toJson(): ToolboxItemSelectJson {
const json = super.toJson() as ToolboxItemSelectJson;
json['oldItem'] = this.oldItem;
json['newItem'] = this.newItem;
return json;
@@ -68,12 +65,17 @@ export class ToolboxItemSelect extends UiBase {
*
* @param json JSON representation.
*/
override fromJson(json: AnyDuringMigration) {
override fromJson(json: ToolboxItemSelectJson) {
super.fromJson(json);
this.oldItem = json['oldItem'];
this.newItem = json['newItem'];
}
}
export interface ToolboxItemSelectJson extends AbstractEventJson {
oldItem?: string;
newItem?: string;
}
registry.register(
registry.Type.EVENT, eventUtils.TOOLBOX_ITEM_SELECT, ToolboxItemSelect);

View File

@@ -13,6 +13,7 @@ import * as goog from '../../closure/goog/goog.js';
goog.declareModuleId('Blockly.Events.TrashcanOpen');
import * as registry from '../registry.js';
import {AbstractEventJson} from './events_abstract.js';
import {UiBase} from './events_ui_base.js';
import * as eventUtils from './utils.js';
@@ -25,7 +26,7 @@ import * as eventUtils from './utils.js';
*/
export class TrashcanOpen extends UiBase {
isOpen?: boolean;
override type: string;
override type = eventUtils.TRASHCAN_OPEN;
/**
* @param opt_isOpen Whether the trashcan flyout is opening (false if
@@ -38,9 +39,6 @@ export class TrashcanOpen extends UiBase {
/** Whether the trashcan flyout is opening (false if closing). */
this.isOpen = opt_isOpen;
/** Type of this event. */
this.type = eventUtils.TRASHCAN_OPEN;
}
/**
@@ -48,8 +46,13 @@ export class TrashcanOpen extends UiBase {
*
* @returns JSON representation.
*/
override toJson(): AnyDuringMigration {
const json = super.toJson();
override toJson(): TrashcanOpenJson {
const json = super.toJson() as TrashcanOpenJson;
if (this.isOpen === undefined) {
throw new Error(
'Whether this is already open or not is undefined. Either pass ' +
'a value to the constructor, or call fromJson');
}
json['isOpen'] = this.isOpen;
return json;
}
@@ -59,10 +62,14 @@ export class TrashcanOpen extends UiBase {
*
* @param json JSON representation.
*/
override fromJson(json: AnyDuringMigration) {
override fromJson(json: TrashcanOpenJson) {
super.fromJson(json);
this.isOpen = json['isOpen'];
}
}
export interface TrashcanOpenJson extends AbstractEventJson {
isOpen: boolean;
}
registry.register(registry.Type.EVENT, eventUtils.TRASHCAN_OPEN, TrashcanOpen);

View File

@@ -15,7 +15,6 @@ goog.declareModuleId('Blockly.Events.Ui');
import type {Block} from '../block.js';
import * as registry from '../registry.js';
import {UiBase} from './events_ui_base.js';
import * as eventUtils from './utils.js';
@@ -31,7 +30,7 @@ export class Ui extends UiBase {
element: AnyDuringMigration;
oldValue: AnyDuringMigration;
newValue: AnyDuringMigration;
override type: string;
override type = eventUtils.UI;
/**
* @param opt_block The affected block. Null for UI events that do not have
@@ -50,9 +49,6 @@ export class Ui extends UiBase {
this.element = typeof opt_element === 'undefined' ? '' : opt_element;
this.oldValue = typeof opt_oldValue === 'undefined' ? '' : opt_oldValue;
this.newValue = typeof opt_newValue === 'undefined' ? '' : opt_newValue;
/** Type of this event. */
this.type = eventUtils.UI;
}
/**
@@ -61,7 +57,7 @@ export class Ui extends UiBase {
* @returns JSON representation.
*/
override toJson(): AnyDuringMigration {
const json = super.toJson();
const json = super.toJson() as AnyDuringMigration;
json['element'] = this.element;
if (this.newValue !== undefined) {
json['newValue'] = this.newValue;

View File

@@ -26,7 +26,7 @@ import {Abstract as AbstractEvent} from './events_abstract.js';
* @alias Blockly.Events.UiBase
*/
export class UiBase extends AbstractEvent {
override isBlank: boolean;
override isBlank = true;
override workspaceId: string;
// UI events do not undo or redo.

View File

@@ -14,7 +14,7 @@ goog.declareModuleId('Blockly.Events.VarBase');
import type {VariableModel} from '../variable_model.js';
import {Abstract as AbstractEvent} from './events_abstract.js';
import {Abstract as AbstractEvent, AbstractEventJson} from './events_abstract.js';
/**
@@ -23,9 +23,8 @@ import {Abstract as AbstractEvent} from './events_abstract.js';
* @alias Blockly.Events.VarBase
*/
export class VarBase extends AbstractEvent {
override isBlank: AnyDuringMigration;
varId: string;
override workspaceId: string;
override isBlank = true;
varId?: string;
/**
* @param opt_variable The variable this event corresponds to. Undefined for
@@ -34,12 +33,13 @@ export class VarBase extends AbstractEvent {
constructor(opt_variable?: VariableModel) {
super();
this.isBlank = typeof opt_variable === 'undefined';
if (!opt_variable) return;
/** The variable ID for the variable this event pertains to. */
this.varId = this.isBlank ? '' : opt_variable!.getId();
/** The variable id for the variable this event pertains to. */
this.varId = opt_variable.getId();
/** The workspace identifier for this event. */
this.workspaceId = this.isBlank ? '' : opt_variable!.workspace.id;
this.workspaceId = opt_variable.workspace.id;
}
/**
@@ -47,8 +47,13 @@ export class VarBase extends AbstractEvent {
*
* @returns JSON representation.
*/
override toJson(): AnyDuringMigration {
const json = super.toJson();
override toJson(): VarBaseJson {
const json = super.toJson() as VarBaseJson;
if (!this.varId) {
throw new Error(
'The var ID is undefined. Either pass a variable to ' +
'the constructor, or call fromJson');
}
json['varId'] = this.varId;
return json;
}
@@ -58,8 +63,12 @@ export class VarBase extends AbstractEvent {
*
* @param json JSON representation.
*/
override fromJson(json: AnyDuringMigration) {
override fromJson(json: VarBaseJson) {
super.fromJson(json);
this.varId = json['varId'];
}
}
export interface VarBaseJson extends AbstractEventJson {
varId: string;
}

View File

@@ -15,7 +15,7 @@ goog.declareModuleId('Blockly.Events.VarCreate');
import * as registry from '../registry.js';
import type {VariableModel} from '../variable_model.js';
import {VarBase} from './events_var_base.js';
import {VarBase, VarBaseJson} from './events_var_base.js';
import * as eventUtils from './utils.js';
@@ -25,12 +25,9 @@ import * as eventUtils from './utils.js';
* @alias Blockly.Events.VarCreate
*/
export class VarCreate extends VarBase {
override type: string;
// TODO(b/109816955): remove '!', see go/strict-prop-init-fix.
varType!: string;
// TODO(b/109816955): remove '!', see go/strict-prop-init-fix.
varName!: string;
override type = eventUtils.VAR_CREATE;
varType?: string;
varName?: string;
/**
* @param opt_variable The created variable. Undefined for a blank event.
@@ -38,9 +35,6 @@ export class VarCreate extends VarBase {
constructor(opt_variable?: VariableModel) {
super(opt_variable);
/** Type of this event. */
this.type = eventUtils.VAR_CREATE;
if (!opt_variable) {
return; // Blank event to be populated by fromJson.
}
@@ -53,8 +47,18 @@ export class VarCreate extends VarBase {
*
* @returns JSON representation.
*/
override toJson(): AnyDuringMigration {
const json = super.toJson();
override toJson(): VarCreateJson {
const json = super.toJson() as VarCreateJson;
if (!this.varType) {
throw new Error(
'The var type is undefined. Either pass a variable to ' +
'the constructor, or call fromJson');
}
if (!this.varName) {
throw new Error(
'The var name is undefined. Either pass a variable to ' +
'the constructor, or call fromJson');
}
json['varType'] = this.varType;
json['varName'] = this.varName;
return json;
@@ -65,7 +69,7 @@ export class VarCreate extends VarBase {
*
* @param json JSON representation.
*/
override fromJson(json: AnyDuringMigration) {
override fromJson(json: VarCreateJson) {
super.fromJson(json);
this.varType = json['varType'];
this.varName = json['varName'];
@@ -78,6 +82,16 @@ export class VarCreate extends VarBase {
*/
override run(forward: boolean) {
const workspace = this.getEventWorkspace_();
if (!this.varId) {
throw new Error(
'The var ID is undefined. Either pass a variable to ' +
'the constructor, or call fromJson');
}
if (!this.varName) {
throw new Error(
'The var name is undefined. Either pass a variable to ' +
'the constructor, or call fromJson');
}
if (forward) {
workspace.createVariable(this.varName, this.varType, this.varId);
} else {
@@ -86,4 +100,9 @@ export class VarCreate extends VarBase {
}
}
export interface VarCreateJson extends VarBaseJson {
varType: string;
varName: string;
}
registry.register(registry.Type.EVENT, eventUtils.VAR_CREATE, VarCreate);

View File

@@ -15,7 +15,7 @@ goog.declareModuleId('Blockly.Events.VarDelete');
import * as registry from '../registry.js';
import type {VariableModel} from '../variable_model.js';
import {VarBase} from './events_var_base.js';
import {VarBase, VarBaseJson} from './events_var_base.js';
import * as eventUtils from './utils.js';
@@ -25,12 +25,9 @@ import * as eventUtils from './utils.js';
* @alias Blockly.Events.VarDelete
*/
export class VarDelete extends VarBase {
override type: string;
// TODO(b/109816955): remove '!', see go/strict-prop-init-fix.
varType!: string;
// TODO(b/109816955): remove '!', see go/strict-prop-init-fix.
varName!: string;
override type = eventUtils.VAR_DELETE;
varType?: string;
varName?: string;
/**
* @param opt_variable The deleted variable. Undefined for a blank event.
@@ -38,9 +35,6 @@ export class VarDelete extends VarBase {
constructor(opt_variable?: VariableModel) {
super(opt_variable);
/** Type of this event. */
this.type = eventUtils.VAR_DELETE;
if (!opt_variable) {
return; // Blank event to be populated by fromJson.
}
@@ -53,8 +47,18 @@ export class VarDelete extends VarBase {
*
* @returns JSON representation.
*/
override toJson(): AnyDuringMigration {
const json = super.toJson();
override toJson(): VarDeleteJson {
const json = super.toJson() as VarDeleteJson;
if (!this.varType) {
throw new Error(
'The var type is undefined. Either pass a variable to ' +
'the constructor, or call fromJson');
}
if (!this.varName) {
throw new Error(
'The var name is undefined. Either pass a variable to ' +
'the constructor, or call fromJson');
}
json['varType'] = this.varType;
json['varName'] = this.varName;
return json;
@@ -65,7 +69,7 @@ export class VarDelete extends VarBase {
*
* @param json JSON representation.
*/
override fromJson(json: AnyDuringMigration) {
override fromJson(json: VarDeleteJson) {
super.fromJson(json);
this.varType = json['varType'];
this.varName = json['varName'];
@@ -78,6 +82,16 @@ export class VarDelete extends VarBase {
*/
override run(forward: boolean) {
const workspace = this.getEventWorkspace_();
if (!this.varId) {
throw new Error(
'The var ID is undefined. Either pass a variable to ' +
'the constructor, or call fromJson');
}
if (!this.varName) {
throw new Error(
'The var name is undefined. Either pass a variable to ' +
'the constructor, or call fromJson');
}
if (forward) {
workspace.deleteVariableById(this.varId);
} else {
@@ -86,4 +100,9 @@ export class VarDelete extends VarBase {
}
}
export interface VarDeleteJson extends VarBaseJson {
varType: string;
varName: string;
}
registry.register(registry.Type.EVENT, eventUtils.VAR_DELETE, VarDelete);

View File

@@ -15,7 +15,7 @@ goog.declareModuleId('Blockly.Events.VarRename');
import * as registry from '../registry.js';
import type {VariableModel} from '../variable_model.js';
import {VarBase} from './events_var_base.js';
import {VarBase, VarBaseJson} from './events_var_base.js';
import * as eventUtils from './utils.js';
@@ -25,12 +25,9 @@ import * as eventUtils from './utils.js';
* @alias Blockly.Events.VarRename
*/
export class VarRename extends VarBase {
override type: string;
// TODO(b/109816955): remove '!', see go/strict-prop-init-fix.
oldName!: string;
// TODO(b/109816955): remove '!', see go/strict-prop-init-fix.
newName!: string;
override type = eventUtils.VAR_RENAME;
oldName?: string;
newName?: string;
/**
* @param opt_variable The renamed variable. Undefined for a blank event.
@@ -39,9 +36,6 @@ export class VarRename extends VarBase {
constructor(opt_variable?: VariableModel, newName?: string) {
super(opt_variable);
/** Type of this event. */
this.type = eventUtils.VAR_RENAME;
if (!opt_variable) {
return; // Blank event to be populated by fromJson.
}
@@ -54,8 +48,18 @@ export class VarRename extends VarBase {
*
* @returns JSON representation.
*/
override toJson(): AnyDuringMigration {
const json = super.toJson();
override toJson(): VarRenameJson {
const json = super.toJson() as VarRenameJson;
if (!this.oldName) {
throw new Error(
'The old var name is undefined. Either pass a variable to ' +
'the constructor, or call fromJson');
}
if (!this.newName) {
throw new Error(
'The new var name is undefined. Either pass a value to ' +
'the constructor, or call fromJson');
}
json['oldName'] = this.oldName;
json['newName'] = this.newName;
return json;
@@ -66,7 +70,7 @@ export class VarRename extends VarBase {
*
* @param json JSON representation.
*/
override fromJson(json: AnyDuringMigration) {
override fromJson(json: VarRenameJson) {
super.fromJson(json);
this.oldName = json['oldName'];
this.newName = json['newName'];
@@ -79,6 +83,21 @@ export class VarRename extends VarBase {
*/
override run(forward: boolean) {
const workspace = this.getEventWorkspace_();
if (!this.varId) {
throw new Error(
'The var ID is undefined. Either pass a variable to ' +
'the constructor, or call fromJson');
}
if (!this.oldName) {
throw new Error(
'The old var name is undefined. Either pass a variable to ' +
'the constructor, or call fromJson');
}
if (!this.newName) {
throw new Error(
'The new var name is undefined. Either pass a value to ' +
'the constructor, or call fromJson');
}
if (forward) {
workspace.renameVariableById(this.varId, this.newName);
} else {
@@ -87,4 +106,9 @@ export class VarRename extends VarBase {
}
}
export interface VarRenameJson extends VarBaseJson {
oldName: string;
newName: string;
}
registry.register(registry.Type.EVENT, eventUtils.VAR_RENAME, VarRename);

View File

@@ -13,7 +13,7 @@ import * as goog from '../../closure/goog/goog.js';
goog.declareModuleId('Blockly.Events.ViewportChange');
import * as registry from '../registry.js';
import {AbstractEventJson} from './events_abstract.js';
import {UiBase} from './events_ui_base.js';
import * as eventUtils from './utils.js';
@@ -28,7 +28,7 @@ export class ViewportChange extends UiBase {
viewLeft?: number;
scale?: number;
oldScale?: number;
override type: string;
override type = eventUtils.VIEWPORT_CHANGE;
/**
* @param opt_top Top-edge of the visible portion of the workspace, relative
@@ -63,9 +63,6 @@ export class ViewportChange extends UiBase {
/** The old scale of the workspace. */
this.oldScale = opt_oldScale;
/** Type of this event. */
this.type = eventUtils.VIEWPORT_CHANGE;
}
/**
@@ -73,8 +70,28 @@ export class ViewportChange extends UiBase {
*
* @returns JSON representation.
*/
override toJson(): AnyDuringMigration {
const json = super.toJson();
override toJson(): ViewportChangeJson {
const json = super.toJson() as ViewportChangeJson;
if (this.viewTop === undefined) {
throw new Error(
'The view top is undefined. Either pass a value to ' +
'the constructor, or call fromJson');
}
if (this.viewLeft === undefined) {
throw new Error(
'The view left is undefined. Either pass a value to ' +
'the constructor, or call fromJson');
}
if (this.scale === undefined) {
throw new Error(
'The scale is undefined. Either pass a value to ' +
'the constructor, or call fromJson');
}
if (this.oldScale === undefined) {
throw new Error(
'The old scale is undefined. Either pass a value to ' +
'the constructor, or call fromJson');
}
json['viewTop'] = this.viewTop;
json['viewLeft'] = this.viewLeft;
json['scale'] = this.scale;
@@ -87,7 +104,7 @@ export class ViewportChange extends UiBase {
*
* @param json JSON representation.
*/
override fromJson(json: AnyDuringMigration) {
override fromJson(json: ViewportChangeJson) {
super.fromJson(json);
this.viewTop = json['viewTop'];
this.viewLeft = json['viewLeft'];
@@ -96,5 +113,12 @@ export class ViewportChange extends UiBase {
}
}
export interface ViewportChangeJson extends AbstractEventJson {
viewTop: number;
viewLeft: number;
scale: number;
oldScale: number;
}
registry.register(
registry.Type.EVENT, eventUtils.VIEWPORT_CHANGE, ViewportChange);

View File

@@ -536,6 +536,9 @@ export function disableOrphans(event: Abstract) {
}
const eventWorkspace =
common.getWorkspaceById(blockEvent.workspaceId) as WorkspaceSvg;
if (!blockEvent.blockId) {
throw new Error('Encountered a blockEvent without a proper blockId');
}
let block = eventWorkspace.getBlockById(blockEvent.blockId);
if (block) {
// Changing blocks as part of this event shouldn't be undoable.

View File

@@ -14,8 +14,7 @@ goog.declareModuleId('Blockly.Events.FinishedLoading');
import * as registry from '../registry.js';
import type {Workspace} from '../workspace.js';
import {Abstract as AbstractEvent} from './events_abstract.js';
import {Abstract as AbstractEvent, AbstractEventJson} from './events_abstract.js';
import * as eventUtils from './utils.js';
@@ -28,13 +27,9 @@ import * as eventUtils from './utils.js';
* @alias Blockly.Events.FinishedLoading
*/
export class FinishedLoading extends AbstractEvent {
override isBlank: boolean;
override workspaceId: string;
// Workspace events do not undo or redo.
override isBlank = true;
override recordUndo = false;
override type: string;
override group: AnyDuringMigration;
override type = eventUtils.FINISHED_LOADING;
/**
* @param opt_workspace The workspace that has finished loading. Undefined
@@ -43,13 +38,12 @@ export class FinishedLoading extends AbstractEvent {
constructor(opt_workspace?: Workspace) {
super();
/** Whether or not the event is blank (to be populated by fromJson). */
this.isBlank = typeof opt_workspace === 'undefined';
this.isBlank = !!opt_workspace;
if (!opt_workspace) return;
/** The workspace identifier for this event. */
this.workspaceId = opt_workspace ? opt_workspace.id : '';
/** Type of this event. */
this.type = eventUtils.FINISHED_LOADING;
this.workspaceId = opt_workspace.id;
}
/**
@@ -57,16 +51,14 @@ export class FinishedLoading extends AbstractEvent {
*
* @returns JSON representation.
*/
override toJson(): AnyDuringMigration {
const json = {
'type': this.type,
};
if (this.group) {
(json as AnyDuringMigration)['group'] = this.group;
}
if (this.workspaceId) {
(json as AnyDuringMigration)['workspaceId'] = this.workspaceId;
override toJson(): FinishedLoadingJson {
const json = super.toJson() as FinishedLoadingJson;
if (!this.workspaceId) {
throw new Error(
'The workspace ID is undefined. Either pass a workspace to ' +
'the constructor, or call fromJson');
}
json['workspaceId'] = this.workspaceId;
return json;
}
@@ -75,12 +67,15 @@ export class FinishedLoading extends AbstractEvent {
*
* @param json JSON representation.
*/
override fromJson(json: AnyDuringMigration) {
this.isBlank = false;
override fromJson(json: FinishedLoadingJson) {
super.fromJson(json);
this.workspaceId = json['workspaceId'];
this.group = json['group'];
}
}
export interface FinishedLoadingJson extends AbstractEventJson {
workspaceId: string;
}
registry.register(
registry.Type.EVENT, eventUtils.FINISHED_LOADING, FinishedLoading);

View File

@@ -552,6 +552,9 @@ export class Trashcan extends DeleteArea implements IAutoHideable,
}
const deleteEvent = event as BlockDelete;
if (event.type === eventUtils.BLOCK_DELETE && !deleteEvent.wasShadow) {
if (!deleteEvent.oldJson) {
throw new Error('Encountered a delete event without proper oldJson');
}
const cleanedJson =
JSON.stringify(this.cleanBlockJson_(deleteEvent.oldJson));
if (this.contents_.indexOf(cleanedJson) !== -1) {

View File

@@ -69,7 +69,7 @@ export class Coordinate {
* @param b A Coordinate.
* @returns True iff the coordinates are equal, or if both are null.
*/
static equals(a: Coordinate|null, b: Coordinate|null): boolean {
static equals(a?: Coordinate|null, b?: Coordinate|null): boolean {
if (a === b) {
return true;
}