Skip to content

Commit 1ba0e55

Browse files
authored
Merge pull request #7789 from google/rc/v10.3.1
release: v10.3.1
2 parents 26ee8cf + 498fc2c commit 1ba0e55

File tree

5 files changed

+100
-17
lines changed

5 files changed

+100
-17
lines changed

core/flyout_base.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -649,7 +649,7 @@ export abstract class Flyout
649649
const parsedContent = toolbox.convertFlyoutDefToJsonArray(flyoutDef);
650650
const flyoutInfo = this.createFlyoutInfo(parsedContent);
651651

652-
renderManagement.triggerQueuedRenders();
652+
renderManagement.triggerQueuedRenders(this.workspace_);
653653

654654
this.layout_(flyoutInfo.contents, flyoutInfo.gaps);
655655

@@ -1235,8 +1235,7 @@ export abstract class Flyout
12351235
}
12361236

12371237
// Clone the block.
1238-
// TODO(#7432): Add a saveIds parameter to `save`.
1239-
const json = blocks.save(oldBlock, {saveIds: false}) as blocks.State;
1238+
const json = blocks.save(oldBlock) as blocks.State;
12401239
// Normallly this resizes leading to weird jumps. Save it for terminateDrag.
12411240
targetWorkspace.setResizesEnabled(false);
12421241
const block = blocks.append(json, targetWorkspace) as BlockSvg;

core/render_management.ts

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,13 @@
66

77
import {BlockSvg} from './block_svg.js';
88
import * as userAgent from './utils/useragent.js';
9+
import type {WorkspaceSvg} from './workspace_svg.js';
910

1011
/** The set of all blocks in need of rendering which don't have parents. */
1112
const rootBlocks = new Set<BlockSvg>();
1213

1314
/** The set of all blocks in need of rendering. */
14-
let dirtyBlocks = new WeakSet<BlockSvg>();
15+
const dirtyBlocks = new WeakSet<BlockSvg>();
1516

1617
/**
1718
* The promise which resolves after the current set of renders is completed. Or
@@ -75,12 +76,14 @@ export function finishQueuedRenders(): Promise<void> {
7576
* cases where queueing renders breaks functionality + backwards compatibility
7677
* (such as rendering icons).
7778
*
79+
* @param workspace If provided, only rerender blocks in this workspace.
80+
*
7881
* @internal
7982
*/
80-
export function triggerQueuedRenders() {
81-
window.cancelAnimationFrame(animationRequestId);
82-
doRenders();
83-
if (afterRendersResolver) afterRendersResolver();
83+
export function triggerQueuedRenders(workspace?: WorkspaceSvg) {
84+
if (!workspace) window.cancelAnimationFrame(animationRequestId);
85+
doRenders(workspace);
86+
if (!workspace && afterRendersResolver) afterRendersResolver();
8487
}
8588

8689
/**
@@ -110,10 +113,16 @@ function queueBlock(block: BlockSvg) {
110113

111114
/**
112115
* Rerenders all of the blocks in the queue.
116+
*
117+
* @param workspace If provided, only rerender blocks in this workspace.
113118
*/
114-
function doRenders() {
115-
const workspaces = new Set([...rootBlocks].map((block) => block.workspace));
116-
const blocks = [...rootBlocks].filter(shouldRenderRootBlock);
119+
function doRenders(workspace?: WorkspaceSvg) {
120+
const workspaces = workspace
121+
? new Set([workspace])
122+
: new Set([...rootBlocks].map((block) => block.workspace));
123+
const blocks = [...rootBlocks]
124+
.filter(shouldRenderRootBlock)
125+
.filter((b) => workspaces.has(b.workspace));
117126
for (const block of blocks) {
118127
renderBlock(block);
119128
}
@@ -125,9 +134,19 @@ function doRenders() {
125134
block.updateComponentLocations(blockOrigin);
126135
}
127136

128-
rootBlocks.clear();
129-
dirtyBlocks = new Set();
130-
afterRendersPromise = null;
137+
for (const block of blocks) {
138+
dequeueBlock(block);
139+
}
140+
if (!workspace) afterRendersPromise = null;
141+
}
142+
143+
/** Removes the given block and children from the render queue. */
144+
function dequeueBlock(block: BlockSvg) {
145+
rootBlocks.delete(block);
146+
dirtyBlocks.delete(block);
147+
for (const child of block.getChildren(false)) {
148+
dequeueBlock(child);
149+
}
131150
}
132151

133152
/**

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "blockly",
3-
"version": "10.3.0",
3+
"version": "10.3.1",
44
"description": "Blockly is a library for building visual programming editors.",
55
"keywords": [
66
"blockly"

tests/mocha/render_management_test.js

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,4 +57,69 @@ suite('Render Management', function () {
5757
return promise;
5858
});
5959
});
60+
61+
suite('triggering queued renders', function () {
62+
function createMockBlock(ws) {
63+
return {
64+
hasRendered: false,
65+
renderEfficiently: function () {
66+
this.hasRendered = true;
67+
},
68+
69+
// All of the APIs the render management system needs.
70+
getParent: () => null,
71+
getChildren: () => [],
72+
isDisposed: () => false,
73+
getRelativeToSurfaceXY: () => ({x: 0, y: 0}),
74+
updateComponentLocations: () => {},
75+
workspace: ws || createMockWorkspace(),
76+
};
77+
}
78+
79+
function createMockWorkspace() {
80+
return {
81+
resizeContents: () => {},
82+
};
83+
}
84+
85+
test('triggering queued renders rerenders blocks', function () {
86+
const block = createMockBlock();
87+
Blockly.renderManagement.queueRender(block);
88+
89+
Blockly.renderManagement.triggerQueuedRenders();
90+
91+
chai.assert.isTrue(block.hasRendered, 'Expected block to be rendered');
92+
});
93+
94+
test('triggering queued renders rerenders blocks in all workspaces', function () {
95+
const workspace1 = createMockWorkspace();
96+
const workspace2 = createMockWorkspace();
97+
const block1 = createMockBlock(workspace1);
98+
const block2 = createMockBlock(workspace2);
99+
Blockly.renderManagement.queueRender(block1);
100+
Blockly.renderManagement.queueRender(block2);
101+
102+
Blockly.renderManagement.triggerQueuedRenders();
103+
104+
chai.assert.isTrue(block1.hasRendered, 'Expected block1 to be rendered');
105+
chai.assert.isTrue(block2.hasRendered, 'Expected block2 to be rendered');
106+
});
107+
108+
test('triggering queued renders in one workspace does not rerender blocks in another workspace', function () {
109+
const workspace1 = createMockWorkspace();
110+
const workspace2 = createMockWorkspace();
111+
const block1 = createMockBlock(workspace1);
112+
const block2 = createMockBlock(workspace2);
113+
Blockly.renderManagement.queueRender(block1);
114+
Blockly.renderManagement.queueRender(block2);
115+
116+
Blockly.renderManagement.triggerQueuedRenders(workspace1);
117+
118+
chai.assert.isTrue(block1.hasRendered, 'Expected block1 to be rendered');
119+
chai.assert.isFalse(
120+
block2.hasRendered,
121+
'Expected block2 to not be rendered',
122+
);
123+
});
124+
});
60125
});

0 commit comments

Comments
 (0)