fix: Made workspace non-nullable. (#6300)

* Made workspace non-nullable.

* chore: clang-format files.

* fix: Fixed incorrect block disposal check in connection.ts
This commit is contained in:
Aaron Dodson
2022-08-02 13:36:15 -07:00
committed by GitHub
parent 21d90696d1
commit 83a3e74ec9
27 changed files with 121 additions and 130 deletions

View File

@@ -221,9 +221,7 @@ export class Block implements IASTNodeLocation, IDeletable {
type!: string;
// Record initial inline state.
inputsInlineDefault?: boolean;
// Setting this to null indicates that the block has been disposed. Must be
// nullable.
workspace: Workspace|null;
workspace: Workspace;
/**
* @param workspace The block's workspace.
@@ -317,7 +315,7 @@ export class Block implements IASTNodeLocation, IDeletable {
* @suppress {checkTypes}
*/
dispose(healStack: boolean) {
if (!this.workspace) {
if (this.disposed) {
// Already deleted.
return;
}
@@ -335,13 +333,10 @@ export class Block implements IASTNodeLocation, IDeletable {
try {
// This block is now at the top of the workspace.
// Remove this block from the workspace's list of top-most blocks.
if (this.workspace) {
this.workspace.removeTopBlock(this);
this.workspace.removeTypedBlock(this);
// Remove from block database.
this.workspace.removeBlockById(this.id);
this.workspace = null;
}
this.workspace.removeTopBlock(this);
this.workspace.removeTypedBlock(this);
// Remove from block database.
this.workspace.removeBlockById(this.id);
// First, dispose of all my children.
for (let i = this.childBlocks_.length - 1; i >= 0; i--) {
@@ -428,7 +423,7 @@ export class Block implements IASTNodeLocation, IDeletable {
// Disconnect the child block.
childConnection?.disconnect();
// Connect child to the parent if possible, otherwise bump away.
if (this.workspace!.connectionChecker.canConnect(
if (this.workspace.connectionChecker.canConnect(
childConnection, parentConnection, false)) {
parentConnection.connect(childConnection!);
} else {
@@ -481,7 +476,7 @@ export class Block implements IASTNodeLocation, IDeletable {
const nextTarget = this.nextConnection.targetConnection;
nextTarget?.disconnect();
if (previousTarget &&
this.workspace!.connectionChecker.canConnect(
this.workspace.connectionChecker.canConnect(
previousTarget, nextTarget, false)) {
// Attach the next statement to the previous statement.
previousTarget.connect(nextTarget!);
@@ -721,7 +716,7 @@ export class Block implements IASTNodeLocation, IDeletable {
} else {
// New parent must be non-null so remove this block from the workspace's
// list of top-most blocks.
this.workspace!.removeTopBlock(this);
this.workspace.removeTopBlock(this);
}
this.parentBlock_ = newParent;
@@ -729,7 +724,7 @@ export class Block implements IASTNodeLocation, IDeletable {
// Add this block to the new parent's child list.
newParent.childBlocks_.push(this);
} else {
this.workspace!.addTopBlock(this);
this.workspace.addTopBlock(this);
}
}
@@ -759,8 +754,8 @@ export class Block implements IASTNodeLocation, IDeletable {
* @return True if deletable.
*/
isDeletable(): boolean {
return this.deletable_ && !this.isShadow_ &&
!(this.workspace && this.workspace.options.readOnly);
return this.deletable_ && !this.isShadow_ && !this.disposed &&
!this.workspace.options.readOnly;
}
/**
@@ -776,8 +771,8 @@ export class Block implements IASTNodeLocation, IDeletable {
* @return True if movable.
*/
isMovable(): boolean {
return this.movable_ && !this.isShadow_ &&
!(this.workspace && this.workspace.options.readOnly);
return this.movable_ && !this.isShadow_ && !this.disposed &&
!this.workspace.options.readOnly;
}
/**
@@ -796,10 +791,10 @@ export class Block implements IASTNodeLocation, IDeletable {
* @return True if duplicatable.
*/
isDuplicatable(): boolean {
if (!this.workspace!.hasBlockLimits()) {
if (!this.workspace.hasBlockLimits()) {
return true;
}
return this.workspace!.isCapacityAvailable(
return this.workspace.isCapacityAvailable(
common.getBlockTypeCounts(this, true));
}
@@ -843,8 +838,7 @@ export class Block implements IASTNodeLocation, IDeletable {
* @return True if editable.
*/
isEditable(): boolean {
return this.editable_ &&
!(this.workspace && this.workspace.options.readOnly);
return this.editable_ && !this.disposed && !this.workspace.options.readOnly;
}
/**
@@ -974,11 +968,11 @@ export class Block implements IASTNodeLocation, IDeletable {
throw Error('onchange must be a function.');
}
if (this.onchangeWrapper_) {
this.workspace!.removeChangeListener(this.onchangeWrapper_);
this.workspace.removeChangeListener(this.onchangeWrapper_);
}
this.onchange = onchangeFn;
this.onchangeWrapper_ = onchangeFn.bind(this);
this.workspace!.addChangeListener(this.onchangeWrapper_);
this.workspace.addChangeListener(this.onchangeWrapper_);
}
/**
@@ -1031,7 +1025,7 @@ export class Block implements IASTNodeLocation, IDeletable {
for (let j = 0, field; field = input.fieldRow[j]; j++) {
if (field.referencesVariables()) {
const model =
this.workspace!.getVariableById(field.getValue() as string);
this.workspace.getVariableById(field.getValue() as string);
// Check if the variable actually exists (and isn't just a potential
// variable).
if (model) {

View File

@@ -42,7 +42,7 @@ let disconnectGroup: Element = null as AnyDuringMigration;
* @internal
*/
export function disposeUiEffect(block: BlockSvg) {
const workspace = block.workspace!;
const workspace = block.workspace;
const svgGroup = block.getSvgRoot();
workspace.getAudioManager().play('delete');
@@ -100,7 +100,7 @@ function disposeUiStep(
* @internal
*/
export function connectionUiEffect(block: BlockSvg) {
const workspace = block.workspace!;
const workspace = block.workspace;
const scale = workspace.scale;
workspace.getAudioManager().play('click');
if (scale < 1) {
@@ -157,8 +157,8 @@ function connectionUiStep(ripple: SVGElement, start: Date, scale: number) {
* @internal
*/
export function disconnectUiEffect(block: BlockSvg) {
block.workspace!.getAudioManager().play('disconnect');
if (block.workspace!.scale < 1) {
block.workspace.getAudioManager().play('disconnect');
if (block.workspace.scale < 1) {
return; // Too small to care about visual effects.
}
// Horizontal distance for bottom of block to wiggle.

View File

@@ -242,7 +242,7 @@ export class BlockDragger implements IBlockDragger {
// Blocks dragged directly from a flyout may need to be bumped into
// bounds.
bumpObjects.bumpIntoBounds(
this.draggingBlock_.workspace!,
this.draggingBlock_.workspace,
this.workspace_.getMetricsManager().getScrollMetrics(true),
this.draggingBlock_);
}

View File

@@ -144,7 +144,7 @@ export class BlockSvg extends Block implements IASTNodeLocationSvg,
/** Whether mousedown events have been bound yet. */
private eventsInit_ = false;
override workspace: WorkspaceSvg|null;
override workspace: WorkspaceSvg;
// TODO(b/109816955): remove '!', see go/strict-prop-init-fix.
override outputConnection!: RenderedConnection;
// TODO(b/109816955): remove '!', see go/strict-prop-init-fix.
@@ -223,7 +223,7 @@ export class BlockSvg extends Block implements IASTNodeLocationSvg,
* May be called more than once.
*/
initSvg() {
if (!this.workspace!.rendered) {
if (!this.workspace.rendered) {
throw TypeError('Workspace is headless.');
}
for (let i = 0, input; input = this.inputList[i]; i++) {
@@ -236,13 +236,13 @@ export class BlockSvg extends Block implements IASTNodeLocationSvg,
this.applyColour();
this.pathObject.updateMovable(this.isMovable());
const svg = this.getSvgRoot();
if (!this.workspace!.options.readOnly && !this.eventsInit_ && svg) {
if (!this.workspace.options.readOnly && !this.eventsInit_ && svg) {
browserEvents.conditionalBind(svg, 'mousedown', this, this.onMouseDown_);
}
this.eventsInit_ = true;
if (!svg.parentNode) {
this.workspace!.getCanvas().appendChild(svg);
this.workspace.getCanvas().appendChild(svg);
}
}
@@ -287,7 +287,7 @@ export class BlockSvg extends Block implements IASTNodeLocationSvg,
}
}
const event = new (eventUtils.get(eventUtils.SELECTED))!
(oldId, this.id, this.workspace!.id);
(oldId, this.id, this.workspace.id);
eventUtils.fire(event);
common.setSelected(this);
this.addSelect();
@@ -302,8 +302,8 @@ export class BlockSvg extends Block implements IASTNodeLocationSvg,
return;
}
const event = new (eventUtils.get(eventUtils.SELECTED))!
(this.id, null, this.workspace!.id);
event.workspaceId = this.workspace!.id;
(this.id, null, this.workspace.id);
event.workspaceId = this.workspace.id;
eventUtils.fire(event);
common.setSelected(null);
this.removeSelect();
@@ -348,7 +348,7 @@ export class BlockSvg extends Block implements IASTNodeLocationSvg,
// Bail early if workspace is clearing, or we aren't rendered.
// We won't need to reattach ourselves anywhere.
if (this.workspace!.isClearing || !svgRoot) {
if (this.workspace.isClearing || !svgRoot) {
return;
}
@@ -361,7 +361,7 @@ export class BlockSvg extends Block implements IASTNodeLocationSvg,
} else if (oldParent) {
// If we are losing a parent, we want to move our DOM element to the
// root of the workspace.
this.workspace!.getCanvas().appendChild(svgRoot);
this.workspace.getCanvas().appendChild(svgRoot);
this.translate(oldXY.x, oldXY.y);
}
@@ -381,7 +381,7 @@ export class BlockSvg extends Block implements IASTNodeLocationSvg,
let y = 0;
const dragSurfaceGroup = this.useDragSurface_ ?
this.workspace!.getBlockDragSurface()!.getGroup() :
this.workspace.getBlockDragSurface()!.getGroup() :
null;
let element: SVGElement = this.getSvgRoot();
@@ -394,15 +394,15 @@ export class BlockSvg extends Block implements IASTNodeLocationSvg,
// If this element is the current element on the drag surface, include
// the translation of the drag surface itself.
if (this.useDragSurface_ &&
this.workspace!.getBlockDragSurface()!.getCurrentBlock() ===
this.workspace.getBlockDragSurface()!.getCurrentBlock() ===
element) {
const surfaceTranslation =
this.workspace!.getBlockDragSurface()!.getSurfaceTranslation();
this.workspace.getBlockDragSurface()!.getSurfaceTranslation();
x += surfaceTranslation.x;
y += surfaceTranslation.y;
}
element = element.parentNode as SVGElement;
} while (element && element !== this.workspace!.getCanvas() &&
} while (element && element !== this.workspace.getCanvas() &&
element !== dragSurfaceGroup);
}
return new Coordinate(x, y);
@@ -429,7 +429,7 @@ export class BlockSvg extends Block implements IASTNodeLocationSvg,
event!.recordNew();
eventUtils.fire(event);
}
this.workspace!.resizeContents();
this.workspace.resizeContents();
}
/**
@@ -459,11 +459,11 @@ export class BlockSvg extends Block implements IASTNodeLocationSvg,
// This is in workspace coordinates.
const xy = this.getRelativeToSurfaceXY();
this.clearTransformAttributes_();
this.workspace!.getBlockDragSurface()!.translateSurface(xy.x, xy.y);
this.workspace.getBlockDragSurface()!.translateSurface(xy.x, xy.y);
// Execute the move on the top-level SVG component
const svg = this.getSvgRoot();
if (svg) {
this.workspace!.getBlockDragSurface()!.setBlocksAndShow(svg);
this.workspace.getBlockDragSurface()!.setBlocksAndShow(svg);
}
}
@@ -490,8 +490,8 @@ export class BlockSvg extends Block implements IASTNodeLocationSvg,
}
// Translate to current position, turning off 3d.
this.translate(newXY.x, newXY.y);
this.workspace!.getBlockDragSurface()!.clearAndHide(
this.workspace!.getCanvas());
this.workspace.getBlockDragSurface()!.clearAndHide(
this.workspace.getCanvas());
}
/**
@@ -503,7 +503,7 @@ export class BlockSvg extends Block implements IASTNodeLocationSvg,
*/
moveDuringDrag(newLoc: Coordinate) {
if (this.useDragSurface_) {
this.workspace!.getBlockDragSurface()!.translateSurface(
this.workspace.getBlockDragSurface()!.translateSurface(
newLoc.x, newLoc.y);
} else {
(this.svgGroup_ as AnyDuringMigration).translate_ =
@@ -526,10 +526,10 @@ export class BlockSvg extends Block implements IASTNodeLocationSvg,
/** Snap this block to the nearest grid point. */
snapToGrid() {
if (!this.workspace) {
if (this.disposed) {
return; // Deleted block.
}
if (this.workspace!.isDragging()) {
if (this.workspace.isDragging()) {
return // Don't bump blocks during a drag.;
}
@@ -539,7 +539,7 @@ export class BlockSvg extends Block implements IASTNodeLocationSvg,
if (this.isInFlyout) {
return; // Don't move blocks around in a flyout.
}
const grid = this.workspace!.getGrid();
const grid = this.workspace.getGrid();
if (!grid || !grid.shouldSnap()) {
return; // Config says no snapping.
}
@@ -581,7 +581,7 @@ export class BlockSvg extends Block implements IASTNodeLocationSvg,
* A dirty field is a field that needs to be re-rendered.
*/
markDirty() {
this.pathObject.constants = this.workspace!.getRenderer().getConstants();
this.pathObject.constants = this.workspace.getRenderer().getConstants();
for (let i = 0, input; input = this.inputList[i]; i++) {
input.markDirty();
}
@@ -667,8 +667,8 @@ export class BlockSvg extends Block implements IASTNodeLocationSvg,
nextField.showEditor();
// Also move the cursor if we're in keyboard nav mode.
if (this.workspace!.keyboardAccessibilityMode) {
this.workspace!.getCursor()!.setCurNode(nextNode);
if (this.workspace.keyboardAccessibilityMode) {
this.workspace.getCursor()!.setCurNode(nextNode);
}
}
}
@@ -678,7 +678,7 @@ export class BlockSvg extends Block implements IASTNodeLocationSvg,
* @param e Mouse down event or touch start event.
*/
private onMouseDown_(e: Event) {
const gesture = this.workspace && this.workspace!.getGesture(e);
const gesture = this.workspace.getGesture(e);
if (gesture) {
gesture.handleBlockStart(e, this);
}
@@ -702,7 +702,7 @@ export class BlockSvg extends Block implements IASTNodeLocationSvg,
*/
protected generateContextMenu():
Array<ContextMenuOption|LegacyContextMenuOption>|null {
if (this.workspace!.options.readOnly || !this.contextMenu) {
if (this.workspace.options.readOnly || !this.contextMenu) {
return null;
}
// AnyDuringMigration because: Argument of type '{ block: this; }' is not
@@ -830,7 +830,7 @@ export class BlockSvg extends Block implements IASTNodeLocationSvg,
this.isInsertionMarker_ = insertionMarker;
if (this.isInsertionMarker_) {
this.setColour(
this.workspace!.getRenderer().getConstants().INSERTION_MARKER_COLOUR);
this.workspace.getRenderer().getConstants().INSERTION_MARKER_COLOUR);
this.pathObject.updateInsertionMarker(true);
}
}
@@ -852,7 +852,7 @@ export class BlockSvg extends Block implements IASTNodeLocationSvg,
* @suppress {checkTypes}
*/
override dispose(healStack?: boolean, animate?: boolean) {
if (!this.workspace) {
if (this.disposed) {
// The block has already been deleted.
return;
}
@@ -865,7 +865,7 @@ export class BlockSvg extends Block implements IASTNodeLocationSvg,
// If this block is being dragged, unlink the mouse events.
if (common.getSelected() === this) {
this.unselect();
this.workspace!.cancelCurrentGesture();
this.workspace.cancelCurrentGesture();
}
// If this block has a context menu open, close it.
if (ContextMenu.getCurrentBlock() === this) {
@@ -920,11 +920,11 @@ export class BlockSvg extends Block implements IASTNodeLocationSvg,
* grouping, or hide chaff, then use `block.dispose()` directly.
*/
checkAndDelete() {
if (this.workspace!.isFlyout) {
if (this.workspace.isFlyout) {
return;
}
eventUtils.setGroup(true);
this.workspace!.hideChaff();
this.workspace.hideChaff();
if (this.outputConnection) {
// Do not attempt to heal rows
// (https://github.com/google/blockly/issues/4832)
@@ -953,7 +953,7 @@ export class BlockSvg extends Block implements IASTNodeLocationSvg,
this as AnyDuringMigration,
{addCoordinates: true, addNextBlocks: false}) as
blocks.State,
source: this.workspace!,
source: this.workspace,
typeCounts: common.getBlockTypeCounts(this as AnyDuringMigration, true),
};
}
@@ -1062,12 +1062,12 @@ export class BlockSvg extends Block implements IASTNodeLocationSvg,
clearTimeout(this.warningTextDb_[id]);
delete this.warningTextDb_[id];
}
if (this.workspace!.isDragging()) {
if (this.workspace.isDragging()) {
// Don't change the warning text during a drag.
// Wait until the drag finishes.
const thisBlock = this;
this.warningTextDb_[id] = setTimeout(function() {
if (thisBlock.workspace) { // Check block wasn't deleted.
if (!thisBlock.disposed) { // Check block wasn't deleted.
delete thisBlock.warningTextDb_[id];
thisBlock.setWarningText(text, id);
}
@@ -1212,7 +1212,7 @@ export class BlockSvg extends Block implements IASTNodeLocationSvg,
override setColour(colour: number|string) {
super.setColour(colour);
const styleObj =
this.workspace!.getRenderer().getConstants().getBlockStyleForColour(
this.workspace.getRenderer().getConstants().getBlockStyleForColour(
this.colour_);
this.pathObject.setStyle(styleObj.style);
@@ -1229,7 +1229,7 @@ export class BlockSvg extends Block implements IASTNodeLocationSvg,
*/
override setStyle(blockStyleName: string) {
const blockStyle =
this.workspace!.getRenderer().getConstants().getBlockStyle(
this.workspace.getRenderer().getConstants().getBlockStyle(
blockStyleName);
this.styleName_ = blockStyleName;
@@ -1516,10 +1516,10 @@ export class BlockSvg extends Block implements IASTNodeLocationSvg,
* connected should not coincidentally line up on screen.
*/
override bumpNeighbours() {
if (!this.workspace) {
if (this.disposed) {
return; // Deleted block.
}
if (this.workspace!.isDragging()) {
if (this.workspace.isDragging()) {
return; // Don't bump blocks during a drag.
}
const rootBlock = this.getRootBlock();
@@ -1639,7 +1639,7 @@ export class BlockSvg extends Block implements IASTNodeLocationSvg,
if (this.isCollapsed()) {
this.updateCollapsed_();
}
this.workspace!.getRenderer().render(this);
this.workspace.getRenderer().render(this);
this.updateConnectionLocations_();
if (opt_bubble !== false) {
@@ -1648,7 +1648,7 @@ export class BlockSvg extends Block implements IASTNodeLocationSvg,
parentBlock.render(true);
} else {
// Top-most block. Fire an event to allow scrollbars to resize.
this.workspace!.resizeContents();
this.workspace.resizeContents();
}
}
@@ -1661,14 +1661,12 @@ export class BlockSvg extends Block implements IASTNodeLocationSvg,
/** Redraw any attached marker or cursor svgs if needed. */
protected updateMarkers_() {
if (this.workspace!.keyboardAccessibilityMode &&
this.pathObject.cursorSvg) {
this.workspace!.getCursor()!.draw();
if (this.workspace.keyboardAccessibilityMode && this.pathObject.cursorSvg) {
this.workspace.getCursor()!.draw();
}
if (this.workspace!.keyboardAccessibilityMode &&
this.pathObject.markerSvg) {
if (this.workspace.keyboardAccessibilityMode && this.pathObject.markerSvg) {
// TODO(#4592): Update all markers on the block.
this.workspace!.getMarker(MarkerManager.LOCAL_MARKER)!.draw();
this.workspace.getMarker(MarkerManager.LOCAL_MARKER)!.draw();
}
}
@@ -1740,7 +1738,7 @@ export class BlockSvg extends Block implements IASTNodeLocationSvg,
if (nextBlock) {
const nextHeightWidth = nextBlock.getHeightWidth();
const tabHeight =
this.workspace!.getRenderer().getConstants().NOTCH_HEIGHT;
this.workspace.getRenderer().getConstants().NOTCH_HEIGHT;
height += nextHeightWidth.height - tabHeight;
width = Math.max(width, nextHeightWidth.width);
}

View File

@@ -271,7 +271,7 @@ export class Comment extends Icon {
/** Show an editable bubble. */
private createEditableBubble_() {
this.bubble_ = new Bubble(
this.block_.workspace!, this.createEditor_(),
this.block_.workspace, this.createEditor_(),
this.block_.pathObject.svgPath, (this.iconXY_ as Coordinate),
this.model_.size.width, this.model_.size.height);
// Expose this comment's block's ID on its top-level SVG group.

View File

@@ -197,7 +197,7 @@ export class Connection implements IASTNodeLocationWithBlock {
* @internal
*/
getConnectionChecker(): IConnectionChecker {
return this.sourceBlock_.workspace!.connectionChecker;
return this.sourceBlock_.workspace.connectionChecker;
}
/**
@@ -563,7 +563,7 @@ export class Connection implements IASTNodeLocationWithBlock {
const parentBlock = this.getSourceBlock();
const shadowState = this.getShadowState();
const shadowDom = this.getShadowDom();
if (!parentBlock.workspace || !shadowState && !shadowDom) {
if (parentBlock.disposed || !shadowState && !shadowDom) {
return null;
}

View File

@@ -250,7 +250,7 @@ function deleteNext_(deleteList: BlockSvg[], eventGroup: string) {
eventUtils.setGroup(eventGroup);
const block = deleteList.shift();
if (block) {
if (block.workspace) {
if (!block.disposed) {
block.dispose(false, true);
setTimeout(deleteNext_, DELAY, deleteList, eventGroup);
} else {
@@ -372,7 +372,7 @@ export function registerComment() {
const block = scope.block;
// IE doesn't support necessary features for comment editing.
if (!userAgent.IE && !block!.isInFlyout &&
block!.workspace!.options.comments && !block!.isCollapsed() &&
block!.workspace.options.comments && !block!.isCollapsed() &&
block!.isEditable()) {
return 'enabled';
}
@@ -440,7 +440,7 @@ export function registerCollapseExpandBlock() {
preconditionFn(scope: Scope) {
const block = scope.block;
if (!block!.isInFlyout && block!.isMovable() &&
block!.workspace!.options.collapse) {
block!.workspace.options.collapse) {
return 'enabled';
}
return 'hidden';
@@ -467,7 +467,7 @@ export function registerDisable() {
},
preconditionFn(scope: Scope) {
const block = scope.block;
if (!block!.isInFlyout && block!.workspace!.options.disable &&
if (!block!.isInFlyout && block!.workspace.options.disable &&
block!.isEditable()) {
if (block!.getInheritedDisabled()) {
return 'disabled';

View File

@@ -226,7 +226,7 @@ export function showPositionedByField(
*/
function getScaledBboxOfBlock(block: BlockSvg): Rect {
const blockSvg = block.getSvgRoot();
const scale = block.workspace!.scale;
const scale = block.workspace.scale;
const scaledHeight = block.height * scale;
const scaledWidth = block.width * scale;
const xy = style.getPageOffset(blockSvg);
@@ -268,7 +268,7 @@ function showPositionedByRect(
}
const sourceBlock = field.getSourceBlock() as BlockSvg;
// Set bounds to main workspace; show the drop-down.
let workspace = sourceBlock.workspace!;
let workspace = sourceBlock.workspace;
while (workspace.options.parentWorkspace) {
workspace = workspace.options.parentWorkspace;
}

View File

@@ -41,7 +41,7 @@ export class BlockBase extends AbstractEvent {
this.blockId = this.isBlank ? '' : opt_block!.id;
/** The workspace identifier for this event. */
this.workspaceId = this.isBlank ? '' : opt_block!.workspace?.id ?? '';
this.workspaceId = this.isBlank ? '' : opt_block!.workspace.id;
}
/**

View File

@@ -41,7 +41,7 @@ export class BlockDrag extends UiBase {
* event.
*/
constructor(opt_block?: Block, opt_isStart?: boolean, opt_blocks?: Block[]) {
const workspaceId = opt_block ? opt_block.workspace?.id : undefined;
const workspaceId = opt_block ? opt_block.workspace.id : undefined;
super(workspaceId);
this.blockId = opt_block ? opt_block.id : null;

View File

@@ -41,7 +41,7 @@ export class BubbleOpen extends UiBase {
*/
constructor(
opt_block: BlockSvg, opt_isOpen?: boolean, opt_bubbleType?: string) {
const workspaceId = opt_block ? opt_block.workspace!.id : undefined;
const workspaceId = opt_block ? opt_block.workspace.id : undefined;
super(workspaceId);
this.blockId = opt_block ? opt_block.id : null;

View File

@@ -43,7 +43,7 @@ export class Click extends UiBase {
constructor(
opt_block?: Block|null, opt_workspaceId?: string|null,
opt_targetType?: string) {
let workspaceId = opt_block ? opt_block.workspace!.id : opt_workspaceId;
let workspaceId = opt_block ? opt_block.workspace.id : opt_workspaceId;
if (workspaceId === null) {
workspaceId = undefined;
}

View File

@@ -48,7 +48,7 @@ export class MarkerMove extends UiBase {
constructor(
opt_block?: Block|null, isCursor?: boolean, opt_oldNode?: ASTNode|null,
opt_newNode?: ASTNode) {
let workspaceId = opt_block ? opt_block.workspace!.id : undefined;
let workspaceId = opt_block ? opt_block.workspace.id : undefined;
if (opt_newNode && opt_newNode.getType() === ASTNode.types.WORKSPACE) {
workspaceId = (opt_newNode.getLocation() as Workspace).id;
}

View File

@@ -46,7 +46,7 @@ export class Ui extends UiBase {
constructor(
opt_block?: Block|null, opt_element?: string,
opt_oldValue?: AnyDuringMigration, opt_newValue?: AnyDuringMigration) {
const workspaceId = opt_block ? opt_block.workspace!.id : undefined;
const workspaceId = opt_block ? opt_block.workspace.id : undefined;
super(workspaceId);
this.blockId = opt_block ? opt_block.id : null;

View File

@@ -264,7 +264,7 @@ export abstract class Field implements IASTNodeLocationSvg,
* @return The renderer constant provider.
*/
getConstants(): ConstantProvider|null {
if (!this.constants_ && this.sourceBlock_ && this.sourceBlock_.workspace &&
if (!this.constants_ && this.sourceBlock_ && !this.sourceBlock_.disposed &&
this.sourceBlock_.workspace.rendered) {
this.constants_ = (this.sourceBlock_.workspace as WorkspaceSvg)
.getRenderer()
@@ -1023,7 +1023,7 @@ export abstract class Field implements IASTNodeLocationSvg,
* @param e Mouse down event.
*/
protected onMouseDown_(e: Event) {
if (!this.sourceBlock_ || !this.sourceBlock_.workspace) {
if (!this.sourceBlock_ || this.sourceBlock_.disposed) {
return;
}
const gesture = (this.sourceBlock_.workspace as WorkspaceSvg).getGesture(e);

View File

@@ -139,7 +139,7 @@ export class FieldVariable extends FieldDropdown {
return; // Initialization already happened.
}
const variable = Variables.getOrCreateVariablePackage(
this.sourceBlock_.workspace!, null, this.defaultVariableName,
this.sourceBlock_.workspace, null, this.defaultVariableName,
this.defaultType_);
// Don't call setValue because we don't want to cause a rerender.
this.doValueUpdate_(variable.getId());
@@ -167,7 +167,7 @@ export class FieldVariable extends FieldDropdown {
// AnyDuringMigration because: Argument of type 'string | null' is not
// assignable to parameter of type 'string | undefined'.
const variable = Variables.getOrCreateVariablePackage(
this.sourceBlock_.workspace!, id, variableName as AnyDuringMigration,
this.sourceBlock_.workspace, id, variableName as AnyDuringMigration,
variableType);
// This should never happen :)
@@ -234,7 +234,7 @@ export class FieldVariable extends FieldDropdown {
}
// This is necessary so that blocks in the flyout can have custom var names.
const variable = Variables.getOrCreateVariablePackage(
this.sourceBlock_.workspace!, state['id'] || null, state['name'],
this.sourceBlock_.workspace, state['id'] || null, state['name'],
state['type'] || '');
this.setValue(variable.getId());
}
@@ -306,7 +306,7 @@ export class FieldVariable extends FieldDropdown {
return null;
}
const newId = opt_newValue as string;
const variable = Variables.getVariable(this.sourceBlock_.workspace!, newId);
const variable = Variables.getVariable(this.sourceBlock_.workspace, newId);
if (!variable) {
console.warn(
'Variable id doesn\'t point to a real variable! ' +
@@ -332,7 +332,7 @@ export class FieldVariable extends FieldDropdown {
*/
protected override doValueUpdate_(newId: AnyDuringMigration) {
this.variable_ =
Variables.getVariable(this.sourceBlock_.workspace!, newId as string);
Variables.getVariable(this.sourceBlock_.workspace, newId as string);
super.doValueUpdate_(newId);
}
@@ -364,7 +364,7 @@ export class FieldVariable extends FieldDropdown {
let variableTypes = this.variableTypes;
if (variableTypes === null) {
// If variableTypes is null, return all variable types.
if (this.sourceBlock_ && this.sourceBlock_.workspace) {
if (this.sourceBlock_ && !this.sourceBlock_.disposed) {
return this.sourceBlock_.workspace.getVariableTypes();
}
}
@@ -440,7 +440,7 @@ export class FieldVariable extends FieldDropdown {
protected override onItemSelected_(menu: Menu, menuItem: MenuItem) {
const id = menuItem.getValue();
// Handle special cases.
if (this.sourceBlock_ && this.sourceBlock_.workspace) {
if (this.sourceBlock_ && !this.sourceBlock_.disposed) {
if (id === internalConstants.RENAME_VARIABLE_ID) {
// Rename variable.
Variables.renameVariable(
@@ -495,7 +495,7 @@ export class FieldVariable extends FieldDropdown {
}
const name = this.getText();
let variableModelList: AnyDuringMigration[] = [];
if (this.sourceBlock_ && this.sourceBlock_.workspace) {
if (this.sourceBlock_ && !this.sourceBlock_.disposed) {
const variableTypes = this.getVariableTypes_();
// Get a copy of the list, so that adding rename and new variable options
// doesn't modify the workspace's list.

View File

@@ -581,7 +581,7 @@ export class Gesture {
handleRightClick(e: Event) {
if (this.targetBlock_) {
this.bringBlockToFront_();
this.targetBlock_.workspace!.hideChaff(!!this.flyout_);
this.targetBlock_.workspace.hideChaff(!!this.flyout_);
this.targetBlock_.showContextMenu(e);
} else if (this.startBubble_) {
this.startBubble_.showContextMenu(e);

View File

@@ -111,7 +111,7 @@ export abstract class Icon {
* @param e Mouse click event.
*/
protected iconClick_(e: Event) {
if (this.block_.workspace!.isDragging()) {
if (this.block_.workspace.isDragging()) {
// Drag operation is concluding. Don't open the editor.
return;
}

View File

@@ -271,7 +271,7 @@ export class Input {
/** Initialize the fields on this input. */
init() {
if (!this.sourceBlock_.workspace!.rendered) {
if (!this.sourceBlock_.workspace.rendered) {
return; // Headless blocks don't need fields initialized.
}
for (let i = 0; i < this.fieldRow.length; i++) {

View File

@@ -133,7 +133,7 @@ export class InsertionMarkerManager {
* The workspace on which these connections are being dragged.
* Does not change during a drag.
*/
this.workspace_ = block.workspace!;
this.workspace_ = block.workspace;
/**
* The insertion marker that shows up between blocks to show where a block

View File

@@ -268,11 +268,11 @@ export class ASTNode {
// TODO(#6097): Use instanceof checks to exit early for values of
// curLocation that don't make sense.
const curLocationAsBlock = curLocation as Block;
if (!curLocationAsBlock || !curLocationAsBlock.workspace) {
if (!curLocationAsBlock || curLocationAsBlock.disposed) {
return null;
}
const curRoot = curLocationAsBlock.getRootBlock();
const topBlocks = curRoot.workspace?.getTopBlocks(true) ?? [];
const topBlocks = curRoot.workspace.getTopBlocks(true);
for (let i = 0; i < topBlocks.length; i++) {
const topBlock = topBlocks[i];
if (curRoot.id === topBlock.id) {

View File

@@ -178,11 +178,11 @@ export class Mutator extends Icon {
// event filter from workspaceChanged_ .
'disable': false,
'parentWorkspace': this.block_.workspace,
'media': this.block_.workspace!.options.pathToMedia,
'media': this.block_.workspace.options.pathToMedia,
'rtl': this.block_.RTL,
'horizontalLayout': false,
'renderer': this.block_.workspace!.options.renderer,
'rendererOverrides': this.block_.workspace!.options.rendererOverrides,
'renderer': this.block_.workspace.options.renderer,
'rendererOverrides': this.block_.workspace.options.rendererOverrides,
} as BlocklyOptions));
workspaceOptions.toolboxPosition =
this.block_.RTL ? toolbox.Position.RIGHT : toolbox.Position.LEFT;
@@ -353,7 +353,7 @@ export class Mutator extends Icon {
this.block_.saveConnections(thisRootBlock);
}
};
this.block_.workspace!.addChangeListener(this.sourceListener_);
this.block_.workspace.addChangeListener(this.sourceListener_);
}
this.resizeBubble_();
// When the mutator's workspace changes, update the source block.
@@ -372,7 +372,7 @@ export class Mutator extends Icon {
this.workspaceWidth_ = 0;
this.workspaceHeight_ = 0;
if (this.sourceListener_) {
this.block_.workspace!.removeChangeListener(this.sourceListener_);
this.block_.workspace.removeChangeListener(this.sourceListener_);
this.sourceListener_ = null;
}
}

View File

@@ -111,7 +111,7 @@ export function findLegalName(name: string, block: Block): string {
return name;
}
name = name || Msg['UNNAMED_KEY'] || 'unnamed';
while (!isLegalName(name, block.workspace!, block)) {
while (!isLegalName(name, block.workspace, block)) {
// Collision with another procedure.
const r = name.match(/^(.*?)(\d+)$/);
if (!r) {
@@ -179,7 +179,7 @@ export function rename(this: Field, name: string): string {
const oldName = this.getValue();
if (oldName !== name && oldName !== legalName) {
// Rename any callers.
const blocks = this.getSourceBlock().workspace!.getAllBlocks(false);
const blocks = this.getSourceBlock().workspace.getAllBlocks(false);
for (let i = 0; i < blocks.length; i++) {
// Assume it is a procedure so we can check.
const procedureBlock = blocks[i] as unknown as ProcedureBlock;
@@ -396,7 +396,7 @@ export function mutateCallers(defBlock: Block) {
const procedureBlock = defBlock as unknown as ProcedureBlock;
const name = procedureBlock.getProcedureDef()[0];
const xmlElement = defBlock.mutationToDom!(true);
const callers = getCallers(name, defBlock.workspace!);
const callers = getCallers(name, defBlock.workspace);
for (let i = 0, caller; caller = callers[i]; i++) {
const oldMutationDom = caller.mutationToDom!();
const oldMutation = oldMutationDom && Xml.domToText(oldMutationDom);

View File

@@ -70,14 +70,14 @@ export class RenderedConnection extends Connection {
* Connection database for connections of this type on the current
* workspace.
*/
this.db_ = source.workspace!.connectionDBList[type];
this.db_ = source.workspace.connectionDBList[type];
/**
* Connection database for connections compatible with this type on the
* current workspace.
*/
this.dbOpposite_ =
source.workspace!
source.workspace
.connectionDBList[internalConstants.OPPOSITE_TYPE[type]];
/** Workspace units, (0, 0) is top left of block. */
@@ -134,7 +134,7 @@ export class RenderedConnection extends Connection {
* @internal
*/
bumpAwayFrom(staticConnection: RenderedConnection) {
if (this.sourceBlock_.workspace!.isDragging()) {
if (this.sourceBlock_.workspace.isDragging()) {
// Don't move blocks around while the user is doing the same.
return;
}
@@ -271,7 +271,7 @@ export class RenderedConnection extends Connection {
let steps;
const sourceBlockSvg = (this.sourceBlock_);
const renderConstants =
sourceBlockSvg.workspace!.getRenderer().getConstants();
sourceBlockSvg.workspace.getRenderer().getConstants();
const shape = renderConstants.shapeFor(this);
if (this.type === ConnectionType.INPUT_VALUE ||
this.type === ConnectionType.OUTPUT_VALUE) {

View File

@@ -162,7 +162,7 @@ function saveAttributes(block: Block, state: State) {
* @param state The state object to append to.
*/
function saveCoords(block: Block, state: State) {
const workspace = block.workspace!;
const workspace = block.workspace;
const xy = block.getRelativeToSurfaceXY();
state['x'] = Math.round(workspace.RTL ? workspace.getWidth() - xy.x : xy.x);
state['y'] = Math.round(xy.y);
@@ -416,7 +416,7 @@ function loadCoords(block: Block, state: State) {
let x = state['x'] === undefined ? 0 : state['x'];
const y = state['y'] === undefined ? 0 : state['y'];
const workspace = block.workspace!;
const workspace = block.workspace;
x = workspace.RTL ? workspace.getWidth() - x : x;
block.moveBy(x, y);
@@ -492,7 +492,7 @@ function tryToConnectParent(
}
if (!connected) {
const checker = child.workspace!.connectionChecker;
const checker = child.workspace.connectionChecker;
throw new BadConnectionCheck(
checker.getErrorMessage(
checker.canConnectWithReason(
@@ -606,7 +606,7 @@ function loadConnection(
}
if (connectionState['block']) {
appendPrivate(
connectionState['block'], connection.getSourceBlock().workspace!,
connectionState['block'], connection.getSourceBlock().workspace,
{parentConnection: connection});
}
}

View File

@@ -142,7 +142,7 @@ export function registerCut() {
return !!(
!workspace.options.readOnly && !Gesture.inProgress() && selected &&
selected instanceof BlockSvg && selected.isDeletable() &&
selected.isMovable() && !selected.workspace!.isFlyout);
selected.isMovable() && !selected.workspace.isFlyout);
},
callback() {
const selected = common.getSelected();

View File

@@ -109,7 +109,7 @@ export function blockToDomWithXY(block: Block, opt_noId?: boolean): Element|
}
let width = 0; // Not used in LTR.
if (block.workspace?.RTL) {
if (block.workspace.RTL) {
width = block.workspace.getWidth();
}
@@ -118,8 +118,7 @@ export function blockToDomWithXY(block: Block, opt_noId?: boolean): Element|
// AnyDuringMigration because: Property 'setAttribute' does not exist on type
// 'Element | DocumentFragment'.
(element as AnyDuringMigration)
.setAttribute(
'x', Math.round(block.workspace?.RTL ? width - xy.x : xy.x));
.setAttribute('x', Math.round(block.workspace.RTL ? width - xy.x : xy.x));
// AnyDuringMigration because: Property 'setAttribute' does not exist on type
// 'Element | DocumentFragment'.
(element as AnyDuringMigration).setAttribute('y', Math.round(xy.y));