Skip to content

Commit 6d53629

Browse files
authored
Merge pull request #3568 from Joeclinton1/fix/angle-field-double-unbind
Fix: clear angle field event wrappers to prevent double-unbind
2 parents 5cafbaf + 3416849 commit 6d53629

2 files changed

Lines changed: 48 additions & 0 deletions

File tree

src/fields/scratch_field_angle.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,12 +140,15 @@ class ScratchFieldAngle extends Blockly.FieldNumber {
140140
this.gauge = undefined
141141
if (this.mouseDownWrapper_) {
142142
Blockly.browserEvents.unbind(this.mouseDownWrapper_)
143+
this.mouseDownWrapper_ = undefined
143144
}
144145
if (this.mouseUpWrapper) {
145146
Blockly.browserEvents.unbind(this.mouseUpWrapper)
147+
this.mouseUpWrapper = undefined
146148
}
147149
if (this.mouseMoveWrapper) {
148150
Blockly.browserEvents.unbind(this.mouseMoveWrapper)
151+
this.mouseMoveWrapper = undefined
149152
}
150153
}
151154

@@ -298,9 +301,11 @@ class ScratchFieldAngle extends Blockly.FieldNumber {
298301
onMouseUp() {
299302
if (this.mouseMoveWrapper) {
300303
Blockly.browserEvents.unbind(this.mouseMoveWrapper)
304+
this.mouseMoveWrapper = undefined
301305
}
302306
if (this.mouseUpWrapper) {
303307
Blockly.browserEvents.unbind(this.mouseUpWrapper)
308+
this.mouseUpWrapper = undefined
304309
}
305310
}
306311

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/**
2+
* Copyright 2026 Scratch Foundation
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
import * as Blockly from 'blockly/core'
6+
import { afterEach, beforeAll, describe, expect, it, vi } from 'vitest'
7+
import { registerScratchFieldAngle } from '../../src/fields/scratch_field_angle'
8+
9+
type ScratchFieldAngleForTest = Blockly.FieldNumber & {
10+
mouseMoveWrapper?: Blockly.browserEvents.Data
11+
mouseUpWrapper?: Blockly.browserEvents.Data
12+
onMouseUp(): void
13+
}
14+
15+
beforeAll(() => {
16+
registerScratchFieldAngle()
17+
})
18+
19+
afterEach(() => {
20+
vi.restoreAllMocks()
21+
})
22+
23+
describe('ScratchFieldAngle', () => {
24+
it('does not unbind drag listeners again after mouseup', () => {
25+
const field = Blockly.fieldRegistry.TEST_ONLY.fromJsonInternal({
26+
type: 'field_angle',
27+
angle: 90,
28+
}) as ScratchFieldAngleForTest
29+
const mouseMoveWrapper = [{}] as Blockly.browserEvents.Data
30+
const mouseUpWrapper = [{}] as Blockly.browserEvents.Data
31+
field.mouseMoveWrapper = mouseMoveWrapper
32+
field.mouseUpWrapper = mouseUpWrapper
33+
34+
const unbind = vi.spyOn(Blockly.browserEvents, 'unbind').mockImplementation(() => {})
35+
36+
field.onMouseUp()
37+
field.dispose()
38+
39+
expect(unbind).toHaveBeenCalledTimes(2)
40+
expect(unbind).toHaveBeenCalledWith(mouseMoveWrapper)
41+
expect(unbind).toHaveBeenCalledWith(mouseUpWrapper)
42+
})
43+
})

0 commit comments

Comments
 (0)