phetsims / buoyancy

"Buoyancy" is an educational simulation in HTML5, by PhET Interactive Simulations.
GNU General Public License v3.0
2 stars 2 forks source link

CT tried to removeListener on something that wasn't a listener #67

Closed KatieWoe closed 3 months ago

KatieWoe commented 1 year ago
buoyancy : fuzz : unbuilt
https://bayes.colorado.edu/continuous-testing/ct-snapshots/1654295157038/buoyancy/buoyancy_en.html?continuousTest=%7B%22test%22%3A%5B%22buoyancy%22%2C%22fuzz%22%2C%22unbuilt%22%5D%2C%22snapshotName%22%3A%22snapshot-1654295157038%22%2C%22timestamp%22%3A1654306543783%7D&brand=phet&ea&fuzz&memoryLimit=1000
Query: brand=phet&ea&fuzz&memoryLimit=1000
Uncaught Error: Assertion failed: tried to removeListener on something that wasn't a listener
Error: Assertion failed: tried to removeListener on something that wasn't a listener
at window.assertions.assertFunction (https://bayes.colorado.edu/continuous-testing/ct-snapshots/1654295157038/assert/js/assert.js:28:13)
at assert (TinyEmitter.ts:139:6)
at removeListener (TinyProperty.ts:155:9)
at unlink (AbstractProperty.ts:379:22)
at unlink (DynamicProperty.ts:247:38)
at listener (TinyEmitter.ts:94:8)
at emit (AbstractProperty.ts:255:22)
at _notifyListeners (AbstractProperty.ts:206:13)
at set (Property.ts:67:10)
at set (Property.ts:53:9)
id: Bayes Puppeteer
Snapshot from 6/3/2022, 4:25:57 PM

----------------------------------

buoyancy : multitouch-fuzz : unbuilt
https://bayes.colorado.edu/continuous-testing/ct-snapshots/1654295157038/buoyancy/buoyancy_en.html?continuousTest=%7B%22test%22%3A%5B%22buoyancy%22%2C%22multitouch-fuzz%22%2C%22unbuilt%22%5D%2C%22snapshotName%22%3A%22snapshot-1654295157038%22%2C%22timestamp%22%3A1654527155349%7D&brand=phet&ea&fuzz&fuzzPointers=2&memoryLimit=1000&supportsPanAndZoom=false
Query: brand=phet&ea&fuzz&fuzzPointers=2&memoryLimit=1000&supportsPanAndZoom=false
Uncaught Error: Assertion failed: tried to removeListener on something that wasn't a listener
Error: Assertion failed: tried to removeListener on something that wasn't a listener
at window.assertions.assertFunction (https://bayes.colorado.edu/continuous-testing/ct-snapshots/1654295157038/assert/js/assert.js:28:13)
at assert (TinyEmitter.ts:139:6)
at removeListener (TinyProperty.ts:155:9)
at unlink (AbstractProperty.ts:379:22)
at unlink (DynamicProperty.ts:247:38)
at listener (TinyEmitter.ts:94:8)
at emit (AbstractProperty.ts:255:22)
at _notifyListeners (AbstractProperty.ts:206:13)
at set (Property.ts:67:10)
at set (Property.ts:53:9)
id: Bayes Puppeteer
Snapshot from 6/3/2022, 4:25:57 PM

----------------------------------

buoyancy : phet-io-fuzz : unbuilt
https://bayes.colorado.edu/continuous-testing/ct-snapshots/1654295157038/buoyancy/buoyancy_en.html?continuousTest=%7B%22test%22%3A%5B%22buoyancy%22%2C%22phet-io-fuzz%22%2C%22unbuilt%22%5D%2C%22snapshotName%22%3A%22snapshot-1654295157038%22%2C%22timestamp%22%3A1654339438249%7D&ea&brand=phet-io&phetioStandalone&fuzz&memoryLimit=1000
Query: ea&brand=phet-io&phetioStandalone&fuzz&memoryLimit=1000
Uncaught Error: Assertion failed: All descendants must be disposed by the next frame: buoyancy.shapesScreen.model.primaryMass.radiusProperty
Error: Assertion failed: All descendants must be disposed by the next frame: buoyancy.shapesScreen.model.primaryMass.radiusProperty
at window.assertions.assertFunction (https://bayes.colorado.edu/continuous-testing/ct-snapshots/1654295157038/assert/js/assert.js:28:13)
at assert (PhetioObject.ts:640:18)
at Array.forEach
at forEach (PhetioObject.ts:639:18)
at listener (Timer.ts:33:10)
at (TinyEmitter.ts:108:42)
at emit (Sim.ts:964:24)
id: Bayes Puppeteer
Snapshot from 6/3/2022, 4:25:57 PM

----------------------------------

buoyancy : phet-io-fuzz : unbuilt
https://bayes.colorado.edu/continuous-testing/ct-snapshots/1654295157038/buoyancy/buoyancy_en.html?continuousTest=%7B%22test%22%3A%5B%22buoyancy%22%2C%22phet-io-fuzz%22%2C%22unbuilt%22%5D%2C%22snapshotName%22%3A%22snapshot-1654295157038%22%2C%22timestamp%22%3A1654429775494%7D&ea&brand=phet-io&phetioStandalone&fuzz&memoryLimit=1000
Query: ea&brand=phet-io&phetioStandalone&fuzz&memoryLimit=1000
Uncaught Error: Assertion failed: All descendants must be disposed by the next frame: buoyancy.shapesScreen.model.primaryMass.radiusProperty
Error: Assertion failed: All descendants must be disposed by the next frame: buoyancy.shapesScreen.model.primaryMass.radiusProperty
at window.assertions.assertFunction (https://bayes.colorado.edu/continuous-testing/ct-snapshots/1654295157038/assert/js/assert.js:28:13)
at assert (PhetioObject.ts:640:18)
at Array.forEach
at forEach (PhetioObject.ts:639:18)
at listener (Timer.ts:33:10)
at (TinyEmitter.ts:108:42)
at emit (Sim.ts:964:24)
id: Bayes Puppeteer
Snapshot from 6/3/2022, 4:25:57 PM

----------------------------------

buoyancy : phet-io-fuzz : unbuilt
https://bayes.colorado.edu/continuous-testing/ct-snapshots/1654295157038/buoyancy/buoyancy_en.html?continuousTest=%7B%22test%22%3A%5B%22buoyancy%22%2C%22phet-io-fuzz%22%2C%22unbuilt%22%5D%2C%22snapshotName%22%3A%22snapshot-1654295157038%22%2C%22timestamp%22%3A1654452264856%7D&ea&brand=phet-io&phetioStandalone&fuzz&memoryLimit=1000
Query: ea&brand=phet-io&phetioStandalone&fuzz&memoryLimit=1000
Uncaught Error: Assertion failed: All descendants must be disposed by the next frame: buoyancy.shapesScreen.model.primaryMass.radiusProperty
Error: Assertion failed: All descendants must be disposed by the next frame: buoyancy.shapesScreen.model.primaryMass.radiusProperty
at window.assertions.assertFunction (https://bayes.colorado.edu/continuous-testing/ct-snapshots/1654295157038/assert/js/assert.js:28:13)
at assert (PhetioObject.ts:640:18)
at Array.forEach
at forEach (PhetioObject.ts:639:18)
at listener (Timer.ts:33:10)
at listener (TinyEmitter.ts:94:8)
at emit (Sim.ts:964:24)
id: Bayes Puppeteer
Snapshot from 6/3/2022, 4:25:57 PM

----------------------------------

buoyancy : phet-io-fuzz : unbuilt
https://bayes.colorado.edu/continuous-testing/ct-snapshots/1654295157038/buoyancy/buoyancy_en.html?continuousTest=%7B%22test%22%3A%5B%22buoyancy%22%2C%22phet-io-fuzz%22%2C%22unbuilt%22%5D%2C%22snapshotName%22%3A%22snapshot-1654295157038%22%2C%22timestamp%22%3A1654503193520%7D&ea&brand=phet-io&phetioStandalone&fuzz&memoryLimit=1000
Query: ea&brand=phet-io&phetioStandalone&fuzz&memoryLimit=1000
Uncaught Error: Assertion failed: All descendants must be disposed by the next frame: buoyancy.shapesScreen.model.primaryMass.radiusProperty
Error: Assertion failed: All descendants must be disposed by the next frame: buoyancy.shapesScreen.model.primaryMass.radiusProperty
at window.assertions.assertFunction (https://bayes.colorado.edu/continuous-testing/ct-snapshots/1654295157038/assert/js/assert.js:28:13)
at assert (PhetioObject.ts:640:18)
at Array.forEach
at forEach (PhetioObject.ts:639:18)
at listener (Timer.ts:33:10)
at listener (TinyEmitter.ts:94:8)
at emit (Sim.ts:964:24)
id: Bayes Puppeteer
Snapshot from 6/3/2022, 4:25:57 PM

----------------------------------

buoyancy : phet-io-fuzz : unbuilt
https://bayes.colorado.edu/continuous-testing/ct-snapshots/1654295157038/buoyancy/buoyancy_en.html?continuousTest=%7B%22test%22%3A%5B%22buoyancy%22%2C%22phet-io-fuzz%22%2C%22unbuilt%22%5D%2C%22snapshotName%22%3A%22snapshot-1654295157038%22%2C%22timestamp%22%3A1654527565209%7D&ea&brand=phet-io&phetioStandalone&fuzz&memoryLimit=1000
Query: ea&brand=phet-io&phetioStandalone&fuzz&memoryLimit=1000
Uncaught Error: Assertion failed: empty volume should be non-negative
Error: Assertion failed: empty volume should be non-negative
at window.assertions.assertFunction (https://bayes.colorado.edu/continuous-testing/ct-snapshots/1654295157038/assert/js/assert.js:28:13)
at assert (Basin.ts:140:14)
at getEmptyVolume (BoatView.ts:150:39)
at callback (Multilink.ts:111:10)
at listener (TinyEmitter.ts:94:8)
at emit (AbstractProperty.ts:255:22)
at _notifyListeners (AbstractProperty.ts:206:13)
at set (Property.ts:67:10)
at set (Property.ts:53:9)
at (DensityBuoyancyModel.ts:401:8)
id: Bayes Puppeteer
Snapshot from 6/3/2022, 4:25:57 PM

----------------------------------

buoyancy : phet-io-state-fuzz : unbuilt
https://bayes.colorado.edu/continuous-testing/ct-snapshots/1654295157038/phet-io-wrappers/state/?sim=buoyancy&phetioDebug=true&fuzz&wrapperContinuousTest=%7B%22test%22%3A%5B%22buoyancy%22%2C%22phet-io-state-fuzz%22%2C%22unbuilt%22%5D%2C%22snapshotName%22%3A%22snapshot-1654295157038%22%2C%22timestamp%22%3A1654297854811%7D
Uncaught Error: Uncaught Error: Assertion failed: Impossible set state from iterate; unset state:
[object Object]
Error: Assertion failed: Impossible set state from iterate; unset state:
at window.assertions.assertFunction (https://bayes.colorado.edu/continuous-testing/ct-snapshots/1654295157038/assert/js/assert.js:28:13)
at assert (PhetioStateEngine.js:333:18)
at iterate (PhetioStateEngine.js:246:30)
at setState (PhetioStateEngine.js:263:9)
at setFullState (phetioEngine.js:1105:31)
at apply (phetioCommandProcessor.js:304:50)
at processCommand (phetioCommandProcessor.js:179:35)
at getReturn (phetioCommandProcessor.js:183:15)
at Array.map
at map (phetioCommandProcessor.js:177:29)
id: Bayes Puppeteer
Snapshot from 6/3/2022, 4:25:57 PM

----------------------------------

buoyancy : phet-io-state-fuzz : unbuilt
https://bayes.colorado.edu/continuous-testing/ct-snapshots/1654295157038/phet-io-wrappers/state/?sim=buoyancy&phetioDebug=true&fuzz&wrapperContinuousTest=%7B%22test%22%3A%5B%22buoyancy%22%2C%22phet-io-state-fuzz%22%2C%22unbuilt%22%5D%2C%22snapshotName%22%3A%22snapshot-1654295157038%22%2C%22timestamp%22%3A1654311876243%7D
Uncaught Error: Uncaught Error: Assertion failed: Impossible set state from iterate; unset state:
[object Object]
Error: Assertion failed: Impossible set state from iterate; unset state:
at window.assertions.assertFunction (https://bayes.colorado.edu/continuous-testing/ct-snapshots/1654295157038/assert/js/assert.js:28:13)
at assert (PhetioStateEngine.js:333:18)
at iterate (PhetioStateEngine.js:246:30)
at setState (PhetioStateEngine.js:263:9)
at setFullState (phetioEngine.js:1105:31)
at apply (phetioCommandProcessor.js:304:50)
at processCommand (phetioCommandProcessor.js:179:35)
at getReturn (phetioCommandProcessor.js:183:15)
at Array.map
at map (phetioCommandProcessor.js:177:29)
id: Bayes Puppeteer
Snapshot from 6/3/2022, 4:25:57 PM

----------------------------------

buoyancy : phet-io-state-fuzz : unbuilt
https://bayes.colorado.edu/continuous-testing/ct-snapshots/1654295157038/phet-io-wrappers/state/?sim=buoyancy&phetioDebug=true&fuzz&wrapperContinuousTest=%7B%22test%22%3A%5B%22buoyancy%22%2C%22phet-io-state-fuzz%22%2C%22unbuilt%22%5D%2C%22snapshotName%22%3A%22snapshot-1654295157038%22%2C%22timestamp%22%3A1654324967154%7D
Uncaught Error: Uncaught Error: Assertion failed: Impossible set state from iterate; unset state:
[object Object]
Error: Assertion failed: Impossible set state from iterate; unset state:
at window.assertions.assertFunction (https://bayes.colorado.edu/continuous-testing/ct-snapshots/1654295157038/assert/js/assert.js:28:13)
at assert (PhetioStateEngine.js:333:18)
at iterate (PhetioStateEngine.js:246:30)
at setState (PhetioStateEngine.js:263:9)
at setFullState (phetioEngine.js:1105:31)
at apply (phetioCommandProcessor.js:304:50)
at processCommand (phetioCommandProcessor.js:179:35)
at getReturn (phetioCommandProcessor.js:183:15)
at Array.map
at map (phetioCommandProcessor.js:177:29)
id: Bayes Puppeteer
Snapshot from 6/3/2022, 4:25:57 PM

----------------------------------

buoyancy : phet-io-state-fuzz : unbuilt
https://bayes.colorado.edu/continuous-testing/ct-snapshots/1654295157038/phet-io-wrappers/state/?sim=buoyancy&phetioDebug=true&fuzz&wrapperContinuousTest=%7B%22test%22%3A%5B%22buoyancy%22%2C%22phet-io-state-fuzz%22%2C%22unbuilt%22%5D%2C%22snapshotName%22%3A%22snapshot-1654295157038%22%2C%22timestamp%22%3A1654341820023%7D
Uncaught Error: Uncaught Error: Assertion failed: cannot set state while setting state
Error: Assertion failed: cannot set state while setting state
at window.assertions.assertFunction (https://bayes.colorado.edu/continuous-testing/ct-snapshots/1654295157038/assert/js/assert.js:28:13)
at assert (PhetioStateEngine.js:224:14)
at setState (PhetioStateEngine.js:263:9)
at setFullState (phetioEngine.js:1105:31)
at apply (phetioCommandProcessor.js:304:50)
at processCommand (phetioCommandProcessor.js:179:35)
at getReturn (phetioCommandProcessor.js:183:15)
at Array.map
at map (phetioCommandProcessor.js:177:29)
at processCommands (phetioCommandProcessor.js:113:15)
id: Bayes Puppeteer
Snapshot from 6/3/2022, 4:25:57 PM

----------------------------------

buoyancy : phet-io-state-fuzz : unbuilt
https://bayes.colorado.edu/continuous-testing/ct-snapshots/1654295157038/phet-io-wrappers/state/?sim=buoyancy&phetioDebug=true&fuzz&wrapperContinuousTest=%7B%22test%22%3A%5B%22buoyancy%22%2C%22phet-io-state-fuzz%22%2C%22unbuilt%22%5D%2C%22snapshotName%22%3A%22snapshot-1654295157038%22%2C%22timestamp%22%3A1654354028997%7D
Uncaught Error: Uncaught Error: Assertion failed: Impossible set state from iterate; unset state:
[object Object]
Error: Assertion failed: Impossible set state from iterate; unset state:
at window.assertions.assertFunction (https://bayes.colorado.edu/continuous-testing/ct-snapshots/1654295157038/assert/js/assert.js:28:13)
at assert (PhetioStateEngine.js:333:18)
at iterate (PhetioStateEngine.js:246:30)
at setState (PhetioStateEngine.js:263:9)
at setFullState (phetioEngine.js:1105:31)
at apply (phetioCommandProcessor.js:304:50)
at processCommand (phetioCommandProcessor.js:179:35)
at getReturn (phetioCommandProcessor.js:183:15)
at Array.map
at map (phetioCommandProcessor.js:177:29)
id: Bayes Puppeteer
Snapshot from 6/3/2022, 4:25:57 PM

----------------------------------

buoyancy : phet-io-state-fuzz : unbuilt
https://bayes.colorado.edu/continuous-testing/ct-snapshots/1654295157038/phet-io-wrappers/state/?sim=buoyancy&phetioDebug=true&fuzz&wrapperContinuousTest=%7B%22test%22%3A%5B%22buoyancy%22%2C%22phet-io-state-fuzz%22%2C%22unbuilt%22%5D%2C%22snapshotName%22%3A%22snapshot-1654295157038%22%2C%22timestamp%22%3A1654370801959%7D
Uncaught Error: Uncaught Error: Assertion failed: Impossible set state from iterate; unset state:
[object Object]
Error: Assertion failed: Impossible set state from iterate; unset state:
at window.assertions.assertFunction (https://bayes.colorado.edu/continuous-testing/ct-snapshots/1654295157038/assert/js/assert.js:28:13)
at assert (PhetioStateEngine.js:333:18)
at iterate (PhetioStateEngine.js:246:30)
at setState (PhetioStateEngine.js:263:9)
at setFullState (phetioEngine.js:1105:31)
at apply (phetioCommandProcessor.js:304:50)
at processCommand (phetioCommandProcessor.js:179:35)
at getReturn (phetioCommandProcessor.js:183:15)
at Array.map
at map (phetioCommandProcessor.js:177:29)
id: Bayes Puppeteer
Snapshot from 6/3/2022, 4:25:57 PM

----------------------------------

buoyancy : phet-io-state-fuzz : unbuilt
https://bayes.colorado.edu/continuous-testing/ct-snapshots/1654295157038/phet-io-wrappers/state/?sim=buoyancy&phetioDebug=true&fuzz&wrapperContinuousTest=%7B%22test%22%3A%5B%22buoyancy%22%2C%22phet-io-state-fuzz%22%2C%22unbuilt%22%5D%2C%22snapshotName%22%3A%22snapshot-1654295157038%22%2C%22timestamp%22%3A1654384082501%7D
Uncaught Error: Uncaught Error: Assertion failed: Impossible set state from iterate; unset state:
[object Object]
Error: Assertion failed: Impossible set state from iterate; unset state:
at window.assertions.assertFunction (https://bayes.colorado.edu/continuous-testing/ct-snapshots/1654295157038/assert/js/assert.js:28:13)
at assert (PhetioStateEngine.js:333:18)
at iterate (PhetioStateEngine.js:246:30)
at setState (PhetioStateEngine.js:263:9)
at setFullState (phetioEngine.js:1105:31)
at apply (phetioCommandProcessor.js:304:50)
at processCommand (phetioCommandProcessor.js:179:35)
at getReturn (phetioCommandProcessor.js:183:15)
at Array.map
at map (phetioCommandProcessor.js:177:29)
id: Bayes Puppeteer
Snapshot from 6/3/2022, 4:25:57 PM

----------------------------------

buoyancy : phet-io-state-fuzz : unbuilt
https://bayes.colorado.edu/continuous-testing/ct-snapshots/1654295157038/phet-io-wrappers/state/?sim=buoyancy&phetioDebug=true&fuzz&wrapperContinuousTest=%7B%22test%22%3A%5B%22buoyancy%22%2C%22phet-io-state-fuzz%22%2C%22unbuilt%22%5D%2C%22snapshotName%22%3A%22snapshot-1654295157038%22%2C%22timestamp%22%3A1654396840512%7D
Uncaught Error: Uncaught Error: Assertion failed: Impossible set state from iterate; unset state:
[object Object]
Error: Assertion failed: Impossible set state from iterate; unset state:
at window.assertions.assertFunction (https://bayes.colorado.edu/continuous-testing/ct-snapshots/1654295157038/assert/js/assert.js:28:13)
at assert (PhetioStateEngine.js:333:18)
at iterate (PhetioStateEngine.js:246:30)
at setState (PhetioStateEngine.js:263:9)
at setFullState (phetioEngine.js:1105:31)
at apply (phetioCommandProcessor.js:304:50)
at processCommand (phetioCommandProcessor.js:179:35)
at getReturn (phetioCommandProcessor.js:183:15)
at Array.map
at map (phetioCommandProcessor.js:177:29)
id: Bayes Puppeteer
Snapshot from 6/3/2022, 4:25:57 PM

----------------------------------

buoyancy : phet-io-state-fuzz : unbuilt
https://bayes.colorado.edu/continuous-testing/ct-snapshots/1654295157038/phet-io-wrappers/state/?sim=buoyancy&phetioDebug=true&fuzz&wrapperContinuousTest=%7B%22test%22%3A%5B%22buoyancy%22%2C%22phet-io-state-fuzz%22%2C%22unbuilt%22%5D%2C%22snapshotName%22%3A%22snapshot-1654295157038%22%2C%22timestamp%22%3A1654412052138%7D
Uncaught Error: Uncaught Error: Assertion failed: cannot set state while setting state
Error: Assertion failed: cannot set state while setting state
at window.assertions.assertFunction (https://bayes.colorado.edu/continuous-testing/ct-snapshots/1654295157038/assert/js/assert.js:28:13)
at assert (PhetioStateEngine.js:224:14)
at setState (PhetioStateEngine.js:263:9)
at setFullState (phetioEngine.js:1105:31)
at apply (phetioCommandProcessor.js:304:50)
at processCommand (phetioCommandProcessor.js:179:35)
at getReturn (phetioCommandProcessor.js:183:15)
at Array.map
at map (phetioCommandProcessor.js:177:29)
at processCommands (phetioCommandProcessor.js:113:15)
id: Bayes Puppeteer
Snapshot from 6/3/2022, 4:25:57 PM

----------------------------------

buoyancy : phet-io-state-fuzz : unbuilt
https://bayes.colorado.edu/continuous-testing/ct-snapshots/1654295157038/phet-io-wrappers/state/?sim=buoyancy&phetioDebug=true&fuzz&wrapperContinuousTest=%7B%22test%22%3A%5B%22buoyancy%22%2C%22phet-io-state-fuzz%22%2C%22unbuilt%22%5D%2C%22snapshotName%22%3A%22snapshot-1654295157038%22%2C%22timestamp%22%3A1654433259741%7D
Uncaught Error: Uncaught Error: Assertion failed: Impossible set state from iterate; unset state:
[object Object]
Error: Assertion failed: Impossible set state from iterate; unset state:
at window.assertions.assertFunction (https://bayes.colorado.edu/continuous-testing/ct-snapshots/1654295157038/assert/js/assert.js:28:13)
at assert (PhetioStateEngine.js:333:18)
at iterate (PhetioStateEngine.js:246:30)
at setState (PhetioStateEngine.js:263:9)
at setFullState (phetioEngine.js:1105:31)
at apply (phetioCommandProcessor.js:304:50)
at processCommand (phetioCommandProcessor.js:179:35)
at getReturn (phetioCommandProcessor.js:183:15)
at Array.map
at map (phetioCommandProcessor.js:177:29)
id: Bayes Puppeteer
Snapshot from 6/3/2022, 4:25:57 PM

----------------------------------

buoyancy : phet-io-state-fuzz : unbuilt
https://bayes.colorado.edu/continuous-testing/ct-snapshots/1654295157038/phet-io-wrappers/state/?sim=buoyancy&phetioDebug=true&fuzz&wrapperContinuousTest=%7B%22test%22%3A%5B%22buoyancy%22%2C%22phet-io-state-fuzz%22%2C%22unbuilt%22%5D%2C%22snapshotName%22%3A%22snapshot-1654295157038%22%2C%22timestamp%22%3A1654450435293%7D
Uncaught Error: Uncaught Error: Assertion failed: Impossible set state from iterate; unset state:
[object Object]
Error: Assertion failed: Impossible set state from iterate; unset state:
at window.assertions.assertFunction (https://bayes.colorado.edu/continuous-testing/ct-snapshots/1654295157038/assert/js/assert.js:28:13)
at assert (PhetioStateEngine.js:333:18)
at iterate (PhetioStateEngine.js:246:30)
at setState (PhetioStateEngine.js:263:9)
at setFullState (phetioEngine.js:1105:31)
at apply (phetioCommandProcessor.js:304:50)
at processCommand (phetioCommandProcessor.js:179:35)
at getReturn (phetioCommandProcessor.js:183:15)
at Array.map
at map (phetioCommandProcessor.js:177:29)
id: Bayes Puppeteer
Snapshot from 6/3/2022, 4:25:57 PM

----------------------------------

buoyancy : phet-io-state-fuzz : unbuilt
https://bayes.colorado.edu/continuous-testing/ct-snapshots/1654295157038/phet-io-wrappers/state/?sim=buoyancy&phetioDebug=true&fuzz&wrapperContinuousTest=%7B%22test%22%3A%5B%22buoyancy%22%2C%22phet-io-state-fuzz%22%2C%22unbuilt%22%5D%2C%22snapshotName%22%3A%22snapshot-1654295157038%22%2C%22timestamp%22%3A1654492643740%7D
Uncaught Error: Uncaught Error: Assertion failed: cannot set state while setting state
Error: Assertion failed: cannot set state while setting state
at window.assertions.assertFunction (https://bayes.colorado.edu/continuous-testing/ct-snapshots/1654295157038/assert/js/assert.js:28:13)
at assert (PhetioStateEngine.js:224:14)
at setState (PhetioStateEngine.js:263:9)
at setFullState (phetioEngine.js:1105:31)
at apply (phetioCommandProcessor.js:304:50)
at processCommand (phetioCommandProcessor.js:179:35)
at getReturn (phetioCommandProcessor.js:183:15)
at Array.map
at map (phetioCommandProcessor.js:177:29)
at processCommands (phetioCommandProcessor.js:113:15)
id: Bayes Puppeteer
Snapshot from 6/3/2022, 4:25:57 PM

----------------------------------

buoyancy : phet-io-state-fuzz : unbuilt
https://bayes.colorado.edu/continuous-testing/ct-snapshots/1654295157038/phet-io-wrappers/state/?sim=buoyancy&phetioDebug=true&fuzz&wrapperContinuousTest=%7B%22test%22%3A%5B%22buoyancy%22%2C%22phet-io-state-fuzz%22%2C%22unbuilt%22%5D%2C%22snapshotName%22%3A%22snapshot-1654295157038%22%2C%22timestamp%22%3A1654504185026%7D
Uncaught Error: Uncaught Error: Assertion failed: cannot set state while setting state
Error: Assertion failed: cannot set state while setting state
at window.assertions.assertFunction (https://bayes.colorado.edu/continuous-testing/ct-snapshots/1654295157038/assert/js/assert.js:28:13)
at assert (PhetioStateEngine.js:224:14)
at setState (PhetioStateEngine.js:263:9)
at setFullState (phetioEngine.js:1105:31)
at apply (phetioCommandProcessor.js:304:50)
at processCommand (phetioCommandProcessor.js:179:35)
at getReturn (phetioCommandProcessor.js:183:15)
at Array.map
at map (phetioCommandProcessor.js:177:29)
at processCommands (phetioCommandProcessor.js:113:15)
id: Bayes Puppeteer
Snapshot from 6/3/2022, 4:25:57 PM

----------------------------------

buoyancy : phet-io-state-fuzz : unbuilt
https://bayes.colorado.edu/continuous-testing/ct-snapshots/1654295157038/phet-io-wrappers/state/?sim=buoyancy&phetioDebug=true&fuzz&wrapperContinuousTest=%7B%22test%22%3A%5B%22buoyancy%22%2C%22phet-io-state-fuzz%22%2C%22unbuilt%22%5D%2C%22snapshotName%22%3A%22snapshot-1654295157038%22%2C%22timestamp%22%3A1654516876098%7D
Uncaught Error: Uncaught Error: Assertion failed: cannot set state while setting state
Error: Assertion failed: cannot set state while setting state
at window.assertions.assertFunction (https://bayes.colorado.edu/continuous-testing/ct-snapshots/1654295157038/assert/js/assert.js:28:13)
at assert (PhetioStateEngine.js:224:14)
at setState (PhetioStateEngine.js:263:9)
at setFullState (phetioEngine.js:1105:31)
at apply (phetioCommandProcessor.js:304:50)
at processCommand (phetioCommandProcessor.js:179:35)
at getReturn (phetioCommandProcessor.js:183:15)
at Array.map
at map (phetioCommandProcessor.js:177:29)
at processCommands (phetioCommandProcessor.js:113:15)
id: Bayes Puppeteer
Snapshot from 6/3/2022, 4:25:57 PM

----------------------------------

buoyancy : phet-io-state-fuzz : unbuilt
https://bayes.colorado.edu/continuous-testing/ct-snapshots/1654295157038/phet-io-wrappers/state/?sim=buoyancy&phetioDebug=true&fuzz&wrapperContinuousTest=%7B%22test%22%3A%5B%22buoyancy%22%2C%22phet-io-state-fuzz%22%2C%22unbuilt%22%5D%2C%22snapshotName%22%3A%22snapshot-1654295157038%22%2C%22timestamp%22%3A1654527294900%7D
Uncaught Error: Uncaught Error: Assertion failed: Impossible set state from iterate; unset state:
[object Object]
Error: Assertion failed: Impossible set state from iterate; unset state:
at window.assertions.assertFunction (https://bayes.colorado.edu/continuous-testing/ct-snapshots/1654295157038/assert/js/assert.js:28:13)
at assert (PhetioStateEngine.js:333:18)
at iterate (PhetioStateEngine.js:246:30)
at setState (PhetioStateEngine.js:263:9)
at setFullState (phetioEngine.js:1105:31)
at apply (phetioCommandProcessor.js:304:50)
at processCommand (phetioCommandProcessor.js:179:35)
at getReturn (phetioCommandProcessor.js:183:15)
at Array.map
at map (phetioCommandProcessor.js:177:29)
id: Bayes Puppeteer
Snapshot from 6/3/2022, 4:25:57 PM
KatieWoe commented 1 year ago

Seeing this again

buoyancy : fuzz : unbuilt
http://127.0.0.1/continuous-testing/ct-snapshots/1683626850194/buoyancy/buoyancy_en.html?continuousTest=%7B%22test%22%3A%5B%22buoyancy%22%2C%22fuzz%22%2C%22unbuilt%22%5D%2C%22snapshotName%22%3A%22snapshot-1683626850194%22%2C%22timestamp%22%3A1683627329248%7D&brand=phet&ea&fuzz
Query: brand=phet&ea&fuzz
Error: Assertion failed: tried to removeListener on something that wasn't a listener
window.assertions.assertFunction<@http://127.0.0.1/continuous-testing/ct-snapshots/1683626850194/assert/js/assert.js:28:13
at window.assertions.assertFunction< (http://127.0.0.1/continuous-testing/ct-snapshots/1683626850194/assert/js/assert.js:28:13)
at (TinyEmitter.ts:170:14)
at removeListener (TinyProperty.ts:150:9)
at unlink (ReadOnlyProperty.ts:429:22)
at unlink (DynamicProperty.ts:246:38)
at (TinyEmitter.ts:119:18)
at emit (ReadOnlyProperty.ts:315:22)
at _notifyListeners (ReadOnlyProperty.ts:266:13)
at unguardedSet (ReadOnlyProperty.ts:250:11)
at set (Property.ts:54:10)
at inverseMap (DynamicProperty.ts:273:68)
at (TinyEmitter.ts:119:18)
at emit (ReadOnlyProperty.ts:315:22)
at _notifyListeners (ReadOnlyProperty.ts:266:13)
at unguardedSet (ReadOnlyProperty.ts:250:11)
at set (DynamicProperty.ts:311:10)
at set (DynamicProperty.ts:329:9)
at property (ComboBoxListBox.ts:104:6)
at apply (PhetioAction.ts:158:16)
at execute (ComboBoxListBox.ts:126:19)
at inputEvent (Input.ts:1899:69)
at dispatchToListeners (Input.ts:1939:11)
at dispatchToTargets (Input.ts:1851:9)
at dispatchEvent (Input.ts:1653:9)
at upEvent (Input.ts:518:13)
at apply (PhetioAction.ts:158:16)
at execute (Input.ts:1291:24)
at touchEnd (InputFuzzer.js:242:24)
at touchEnd (InputFuzzer.js:55:11)
at action (InputFuzzer.js:107:6)
at fuzzEvents (SimDisplay.ts:211:23)
at fuzzInputEvents (Sim.ts:998:44)
at requestAnimationFrame (Sim.ts:990:11)
at requestAnimationFrame (Sim.ts:990:11)
at requestAnimationFrame (Sim.ts:990:11)
at requestAnimationFrame (Sim.ts:990:11)
at requestAnimationFrame (Sim.ts:990:11)
at requestAnimationFrame (Sim.ts:990:11)
at requestAnimationFrame (Sim.ts:990:11)
at requestAnimationFrame (Sim.ts:990:11)
at requestAnimationFrame (Sim.ts:990:11)
at requestAnimationFrame (Sim.ts:990:11)
at requestAnimationFrame (Sim.ts:990:11)
at requestAnimationFrame (Sim.ts:990:11)
at requestAnimationFrame (Sim.ts:990:11)
at requestAnimationFrame (Sim.ts:990:11)
at requestAnimationFrame (Sim.ts:990:11)
at requestAnimationFrame (Sim.ts:990:11)
at requestAnimationFrame (Sim.ts:990:11)
at requestAnimationFrame (Sim.ts:990:11)
at requestAnimationFrame (Sim.ts:990:11)
at requestAnimationFrame (Sim.ts:990:11)
at requestAnimationFrame (Sim.ts:990:11)
at requestAnimationFrame (Sim.ts:990:11)
at requestAnimationFrame (Sim.ts:990:11)
at requestAnimationFrame (Sim.ts:990:11)
at requestAnimationFrame (Sim.ts:990:11)
at requestAnimationFrame (Sim.ts:990:11)
at requestAnimationFrame (Sim.ts:990:11)
at requestAnimationFrame (Sim.ts:990:11)
at requestAnimationFrame (Sim.ts:990:11)
at requestAnimationFrame (Sim.ts:990:11)
at requestAnimationFrame (Sim.ts:990:11)
at requestAnimationFrame (Sim.ts:990:11)
at requestAnimationFrame (Sim.ts:990:11)
at requestAnimationFrame (Sim.ts:990:11)
at requestAnimationFrame (Sim.ts:990:11)
at requestAnimationFrame (Sim.ts:990:11)
at requestAnimationFrame (Sim.ts:990:11)
at requestAnimationFrame (Sim.ts:990:11)
at requestAnimationFrame (Sim.ts:990:11)
at requestAnimationFrame (Sim.ts:990:11)
at requestAnimationFrame (Sim.ts:990:11)
at requestAnimationFrame (Sim.ts:990:11)
at requestAnimationFrame (Sim.ts:990:11)
at requestAnimationFrame (Sim.ts:990:11)
at requestAnimationFrame (Sim.ts:990:11)
at requestAnimationFrame (Sim.ts:990:11)
id: Sparky Playwright Firefox
Snapshot from 5/9/2023, 4:07:30 AM

----------------------------------

buoyancy : multitouch-fuzz : unbuilt
http://127.0.0.1/continuous-testing/ct-snapshots/1683626850194/buoyancy/buoyancy_en.html?continuousTest=%7B%22test%22%3A%5B%22buoyancy%22%2C%22multitouch-fuzz%22%2C%22unbuilt%22%5D%2C%22snapshotName%22%3A%22snapshot-1683626850194%22%2C%22timestamp%22%3A1683628425725%7D&brand=phet&ea&fuzz&fuzzPointers=2&supportsPanAndZoom=false
Query: brand=phet&ea&fuzz&fuzzPointers=2&supportsPanAndZoom=false
Error: Assertion failed: tried to removeListener on something that wasn't a listener
window.assertions.assertFunction<@http://127.0.0.1/continuous-testing/ct-snapshots/1683626850194/assert/js/assert.js:28:13
at window.assertions.assertFunction< (http://127.0.0.1/continuous-testing/ct-snapshots/1683626850194/assert/js/assert.js:28:13)
at (TinyEmitter.ts:170:14)
at removeListener (TinyProperty.ts:150:9)
at unlink (ReadOnlyProperty.ts:429:22)
at unlink (DynamicProperty.ts:246:38)
at (TinyEmitter.ts:119:18)
at emit (ReadOnlyProperty.ts:315:22)
at _notifyListeners (ReadOnlyProperty.ts:266:13)
at unguardedSet (ReadOnlyProperty.ts:250:11)
at set (Property.ts:54:10)
at createCustomSolidMaterial (MaterialMassVolumeControlNode.ts:208:44)
at (TinyEmitter.ts:119:18)
at emit (ReadOnlyProperty.ts:315:22)
at _notifyListeners (ReadOnlyProperty.ts:266:13)
at unguardedSet (ReadOnlyProperty.ts:250:11)
at set (Property.ts:65:10)
at set (Slider.ts:463:24)
at (TinyEmitter.ts:119:18)
at emit (ReadOnlyProperty.ts:315:22)
at _notifyListeners (ReadOnlyProperty.ts:266:13)
at unguardedSet (ReadOnlyProperty.ts:250:11)
at set (DerivedProperty.ts:158:12)
at (TinyEmitter.ts:119:18)
at emit (ReadOnlyProperty.ts:315:22)
at _notifyListeners (ReadOnlyProperty.ts:266:13)
at unguardedSet (ReadOnlyProperty.ts:250:11)
at set (Property.ts:54:10)
at inverseMap (DynamicProperty.ts:273:68)
at (TinyEmitter.ts:119:18)
at emit (ReadOnlyProperty.ts:315:22)
at _notifyListeners (ReadOnlyProperty.ts:266:13)
at unguardedSet (ReadOnlyProperty.ts:250:11)
at set (DynamicProperty.ts:311:10)
at set (DynamicProperty.ts:329:9)
at property (ComboBoxListBox.ts:104:6)
at apply (PhetioAction.ts:158:16)
at execute (ComboBoxListBox.ts:126:19)
at inputEvent (Input.ts:1899:69)
at dispatchToListeners (Input.ts:1939:11)
at dispatchToTargets (Input.ts:1851:9)
at dispatchEvent (Input.ts:1653:9)
at upEvent (Input.ts:401:11)
at apply (PhetioAction.ts:158:16)
at execute (Input.ts:1219:23)
at mouseUp (InputFuzzer.js:275:26)
at mouseToggle (InputFuzzer.js:40:11)
at action (InputFuzzer.js:107:6)
at fuzzEvents (SimDisplay.ts:211:23)
at fuzzInputEvents (Sim.ts:998:44)
at requestAnimationFrame (Sim.ts:990:11)
at requestAnimationFrame (Sim.ts:990:11)
at requestAnimationFrame (Sim.ts:990:11)
at requestAnimationFrame (Sim.ts:990:11)
at requestAnimationFrame (Sim.ts:990:11)
at requestAnimationFrame (Sim.ts:990:11)
at requestAnimationFrame (Sim.ts:990:11)
at requestAnimationFrame (Sim.ts:990:11)
at requestAnimationFrame (Sim.ts:990:11)
at requestAnimationFrame (Sim.ts:990:11)
at requestAnimationFrame (Sim.ts:990:11)
at requestAnimationFrame (Sim.ts:990:11)
at requestAnimationFrame (Sim.ts:990:11)
at requestAnimationFrame (Sim.ts:990:11)
at requestAnimationFrame (Sim.ts:990:11)
at requestAnimationFrame (Sim.ts:990:11)
at requestAnimationFrame (Sim.ts:990:11)
at requestAnimationFrame (Sim.ts:990:11)
at requestAnimationFrame (Sim.ts:990:11)
at requestAnimationFrame (Sim.ts:990:11)
at requestAnimationFrame (Sim.ts:990:11)
at requestAnimationFrame (Sim.ts:990:11)
at requestAnimationFrame (Sim.ts:990:11)
at requestAnimationFrame (Sim.ts:990:11)
at requestAnimationFrame (Sim.ts:990:11)
at requestAnimationFrame (Sim.ts:990:11)
at requestAnimationFrame (Sim.ts:990:11)
at requestAnimationFrame (Sim.ts:990:11)
at requestAnimationFrame (Sim.ts:990:11)
at requestAnimationFrame (Sim.ts:990:11)
at requestAnimationFrame (Sim.ts:990:11)
at requestAnimationFrame (Sim.ts:990:11)
at requestAnimationFrame (Sim.ts:990:11)
at requestAnimationFrame (Sim.ts:990:11)
at requestAnimationFrame (Sim.ts:990:11)
at requestAnimationFrame (Sim.ts:990:11)
at requestAnimationFrame (Sim.ts:990:11)
at requestAnimationFrame (Sim.ts:990:11)
at requestAnimationFrame (Sim.ts:990:11)
at requestAnimationFrame (Sim.ts:990:11)
at requestAnimationFrame (Sim.ts:990:11)
id: Sparky Playwright Firefox
Snapshot from 5/9/2023, 4:07:30 AM
KatieWoe commented 1 year ago

May be related:

buoyancy : multitouch-fuzz : unbuilt
http://127.0.0.1/continuous-testing/ct-snapshots/1684762546721/buoyancy/buoyancy_en.html?continuousTest=%7B%22test%22%3A%5B%22buoyancy%22%2C%22multitouch-fuzz%22%2C%22unbuilt%22%5D%2C%22snapshotName%22%3A%22snapshot-1684762546721%22%2C%22timestamp%22%3A1684763878935%7D&brand=phet&ea&fuzz&fuzzPointers=2&supportsPanAndZoom=false
Query: brand=phet&ea&fuzz&fuzzPointers=2&supportsPanAndZoom=false
Uncaught Error: Assertion failed
Error: Assertion failed
at window.assertions.assertFunction (http://127.0.0.1/continuous-testing/ct-snapshots/1684762546721/assert/js/assert.js:28:13)
at assert (Material.ts:101:14)
at (Material.ts:118:11)
at createCustomMaterial (Material.ts:138:20)
at createCustomSolidMaterial (MaterialMassVolumeControlNode.ts:208:44)
at listener (TinyEmitter.ts:119:8)
at emit (ReadOnlyProperty.ts:315:22)
at _notifyListeners (ReadOnlyProperty.ts:266:13)
at unguardedSet (ReadOnlyProperty.ts:250:11)
at set (Property.ts:65:10)
[URL] http://127.0.0.1/continuous-testing/aqua/html/sim-test.html?url=..%2F..%2Fct-snapshots%2F1684762546721%2Fbuoyancy%2Fbuoyancy_en.html&simQueryParameters=brand%3Dphet%26ea%26fuzz%26fuzzPointers%3D2%26supportsPanAndZoom%3Dfalse&testInfo=%7B%22test%22%3A%5B%22buoyancy%22%2C%22multitouch-fuzz%22%2C%22unbuilt%22%5D%2C%22snapshotName%22%3A%22snapshot-1684762546721%22%2C%22timestamp%22%3A1684763878935%7D
[NAVIGATED] http://127.0.0.1/continuous-testing/aqua/html/sim-test.html?url=..%2F..%2Fct-snapshots%2F1684762546721%2Fbuoyancy%2Fbuoyancy_en.html&simQueryParameters=brand%3Dphet%26ea%26fuzz%26fuzzPointers%3D2%26supportsPanAndZoom%3Dfalse&testInfo=%7B%22test%22%3A%5B%22buoyancy%22%2C%22multitouch-fuzz%22%2C%22unbuilt%22%5D%2C%22snapshotName%22%3A%22snapshot-1684762546721%22%2C%22timestamp%22%3A1684763878935%7D
[NAVIGATED] about:blank
[NAVIGATED] http://127.0.0.1/continuous-testing/ct-snapshots/1684762546721/buoyancy/buoyancy_en.html?continuousTest=%7B%22test%22%3A%5B%22buoyancy%22%2C%22multitouch-fuzz%22%2C%22unbuilt%22%5D%2C%22snapshotName%22%3A%22snapshot-1684762546721%22%2C%22timestamp%22%3A1684763878935%7D&brand=phet&ea&fuzz&fuzzPointers=2&supportsPanAndZoom=false
[CONSOLE] enabling assert
[CONSOLE] continuous-test-load
[CONSOLE] Assertion failed
[PAGE ERROR] Error: Error: Assertion failed
at window.assertions.assertFunction (http://127.0.0.1/continuous-testing/ct-snapshots/1684762546721/assert/js/assert.js:28:13)
at new Material (http://127.0.0.1/continuous-testing/ct-snapshots/1684762546721/chipper/dist/js/density-buoyancy-common/js/common/model/Material.js:40:15)
at Material.createCustomMaterial (http://127.0.0.1/continuous-testing/ct-snapshots/1684762546721/chipper/dist/js/density-buoyancy-common/js/common/model/Material.js:56:12)
at Material.createCustomSolidMaterial (http://127.0.0.1/continuous-testing/ct-snapshots/1684762546721/chipper/dist/js/density-buoyancy-common/js/common/model/Material.js:76:21)
at http://127.0.0.1/continuous-testing/ct-snapshots/1684762546721/chipper/dist/js/density-buoyancy-common/js/common/view/MaterialMassVolumeControlNode.js:166:45
at TinyProperty.emit (http://127.0.0.1/continuous-testing/ct-snapshots/1684762546721/chipper/dist/js/axon/js/TinyEmitter.js:95:9)
at NumberProperty._notifyListeners (http://127.0.0.1/continuous-testing/ct-snapshots/1684762546721/chipper/dist/js/axon/js/ReadOnlyProperty.js:237:23)
at NumberProperty.unguardedSet (http://127.0.0.1/continuous-testing/ct-snapshots/1684762546721/chipper/dist/js/axon/js/ReadOnlyProperty.js:189:14)
at NumberProperty.set (http://127.0.0.1/continuous-testing/ct-snapshots/1684762546721/chipper/dist/js/axon/js/ReadOnlyProperty.js:174:12)
at NumberProperty.set (http://127.0.0.1/continuous-testing/ct-snapshots/1684762546721/chipper/dist/js/axon/js/Property.js:58:11)
[CONSOLE] continuous-test-error

id: "Sparky Node Puppeteer"
Snapshot from 5/22/2023, 7:35:46 AM

----------------------------------

buoyancy : pan-and-zoom-fuzz : unbuilt
http://127.0.0.1/continuous-testing/ct-snapshots/1684762546721/buoyancy/buoyancy_en.html?continuousTest=%7B%22test%22%3A%5B%22buoyancy%22%2C%22pan-and-zoom-fuzz%22%2C%22unbuilt%22%5D%2C%22snapshotName%22%3A%22snapshot-1684762546721%22%2C%22timestamp%22%3A1684767650400%7D&brand=phet&ea&fuzz&fuzzPointers=2&supportsPanAndZoom=true
Query: brand=phet&ea&fuzz&fuzzPointers=2&supportsPanAndZoom=true
Uncaught Error: Assertion failed: tried to removeListener on something that wasn't a listener
Error: Assertion failed: tried to removeListener on something that wasn't a listener
at window.assertions.assertFunction (http://127.0.0.1/continuous-testing/ct-snapshots/1684762546721/assert/js/assert.js:28:13)
at assert (TinyEmitter.ts:170:6)
at removeListener (TinyProperty.ts:150:9)
at unlink (ReadOnlyProperty.ts:429:22)
at unlink (DynamicProperty.ts:246:38)
at listener (TinyEmitter.ts:119:8)
at emit (ReadOnlyProperty.ts:315:22)
at _notifyListeners (ReadOnlyProperty.ts:266:13)
at unguardedSet (ReadOnlyProperty.ts:250:11)
at set (Property.ts:54:10)
[URL] http://127.0.0.1/continuous-testing/aqua/html/sim-test.html?url=..%2F..%2Fct-snapshots%2F1684762546721%2Fbuoyancy%2Fbuoyancy_en.html&simQueryParameters=brand%3Dphet%26ea%26fuzz%26fuzzPointers%3D2%26supportsPanAndZoom%3Dtrue&testInfo=%7B%22test%22%3A%5B%22buoyancy%22%2C%22pan-and-zoom-fuzz%22%2C%22unbuilt%22%5D%2C%22snapshotName%22%3A%22snapshot-1684762546721%22%2C%22timestamp%22%3A1684767650400%7D
[NAVIGATED] http://127.0.0.1/continuous-testing/aqua/html/sim-test.html?url=..%2F..%2Fct-snapshots%2F1684762546721%2Fbuoyancy%2Fbuoyancy_en.html&simQueryParameters=brand%3Dphet%26ea%26fuzz%26fuzzPointers%3D2%26supportsPanAndZoom%3Dtrue&testInfo=%7B%22test%22%3A%5B%22buoyancy%22%2C%22pan-and-zoom-fuzz%22%2C%22unbuilt%22%5D%2C%22snapshotName%22%3A%22snapshot-1684762546721%22%2C%22timestamp%22%3A1684767650400%7D
[NAVIGATED] about:blank
[NAVIGATED] http://127.0.0.1/continuous-testing/ct-snapshots/1684762546721/buoyancy/buoyancy_en.html?continuousTest=%7B%22test%22%3A%5B%22buoyancy%22%2C%22pan-and-zoom-fuzz%22%2C%22unbuilt%22%5D%2C%22snapshotName%22%3A%22snapshot-1684762546721%22%2C%22timestamp%22%3A1684767650400%7D&brand=phet&ea&fuzz&fuzzPointers=2&supportsPanAndZoom=true
[CONSOLE] enabling assert
[CONSOLE] continuous-test-load
[CONSOLE] Assertion failed: tried to removeListener on something that wasn't a listener
[PAGE ERROR] Error: Error: Assertion failed: tried to removeListener on something that wasn't a listener
at window.assertions.assertFunction (http://127.0.0.1/continuous-testing/ct-snapshots/1684762546721/assert/js/assert.js:28:13)
at TinyProperty.removeListener (http://127.0.0.1/continuous-testing/ct-snapshots/1684762546721/chipper/dist/js/axon/js/TinyEmitter.js:143:7)
at TinyProperty.unlink (http://127.0.0.1/continuous-testing/ct-snapshots/1684762546721/chipper/dist/js/axon/js/TinyProperty.js:133:10)
at LocalizedStringProperty.unlink (http://127.0.0.1/continuous-testing/ct-snapshots/1684762546721/chipper/dist/js/axon/js/ReadOnlyProperty.js:344:23)
at DynamicProperty.onPropertyChange (http://127.0.0.1/continuous-testing/ct-snapshots/1684762546721/chipper/dist/js/axon/js/DynamicProperty.js:194:37)
at TinyProperty.emit (http://127.0.0.1/continuous-testing/ct-snapshots/1684762546721/chipper/dist/js/axon/js/TinyEmitter.js:95:9)
at Property._notifyListeners (http://127.0.0.1/continuous-testing/ct-snapshots/1684762546721/chipper/dist/js/axon/js/ReadOnlyProperty.js:237:23)
at Property.unguardedSet (http://127.0.0.1/continuous-testing/ct-snapshots/1684762546721/chipper/dist/js/axon/js/ReadOnlyProperty.js:189:14)
at Property.set (http://127.0.0.1/continuous-testing/ct-snapshots/1684762546721/chipper/dist/js/axon/js/ReadOnlyProperty.js:174:12)
at set value [as value] (http://127.0.0.1/continuous-testing/ct-snapshots/1684762546721/chipper/dist/js/axon/js/Property.js:48:11)
[CONSOLE] continuous-test-error
[CONSOLE] Assertion failed: tried to removeListener on something that wasn't a listener
[PAGE ERROR] Error: Error: Assertion failed: tried to removeListener on something that wasn't a listener
at window.assertions.assertFunction (http://127.0.0.1/continuous-testing/ct-snapshots/1684762546721/assert/js/assert.js:28:13)
at TinyProperty.removeListener (http://127.0.0.1/continuous-testing/ct-snapshots/1684762546721/chipper/dist/js/axon/js/TinyEmitter.js:143:7)
at TinyProperty.unlink (http://127.0.0.1/continuous-testing/ct-snapshots/1684762546721/chipper/dist/js/axon/js/TinyProperty.js:133:10)
at LocalizedStringProperty.unlink (http://127.0.0.1/continuous-testing/ct-snapshots/1684762546721/chipper/dist/js/axon/js/ReadOnlyProperty.js:344:23)
at DynamicProperty.onPropertyChange (http://127.0.0.1/continuous-testing/ct-snapshots/1684762546721/chipper/dist/js/axon/js/DynamicProperty.js:194:37)
at TinyProperty.emit (http://127.0.0.1/continuous-testing/ct-snapshots/1684762546721/chipper/dist/js/axon/js/TinyEmitter.js:95:9)
at Property._notifyListeners (http://127.0.0.1/continuous-testing/ct-snapshots/1684762546721/chipper/dist/js/axon/js/ReadOnlyProperty.js:237:23)
at Property.unguardedSet (http://127.0.0.1/continuous-testing/ct-snapshots/1684762546721/chipper/dist/js/axon/js/ReadOnlyProperty.js:189:14)
at Property.set (http://127.0.0.1/continuous-testing/ct-snapshots/1684762546721/chipper/dist/js/axon/js/ReadOnlyProperty.js:174:12)
at set value [as value] (http://127.0.0.1/continuous-testing/ct-snapshots/1684762546721/chipper/dist/js/axon/js/Property.js:48:11)
[CONSOLE] continuous-test-error

id: "Sparky Node Puppeteer"
Snapshot from 5/22/2023, 7:35:46 AM
samreid commented 8 months ago

@jonathanolson @zepumph and I reproduced this problem by:

Buoyancy => Application screen => Cement => set volume and mass to 0 => select "custom"

samreid commented 8 months ago

@jonathanolson and @zepumph and I looked into this, and it seems the problem is:

  1. The material changes to "custom" via the user selection
  2. This changes the enabled range property on one of the sliders
  3. This changes the material again to a new "custom" value (different than step 1)

The Material derives a name Property in this code: https://github.com/phetsims/density-buoyancy-common/blob/d0336128a3743915cee7e99a4e57471f5b475f9e/js/buoyancy/view/DensityReadoutListNode.ts#L29-L38

@jonathanolson hypothesizes that when a re-entrant Property changes from A=>B then B=>C we do not have the correct "oldValue" or miss it somehow.

@jonathanolson was reminded of a scenery case where there was something similar in rendering SVG gradients, where we had to track the oldValue ourselves because it was showing incorrectly in the axon notifications.

@jonathanolson and @zepumph agree we need a unit test to exercise this case and see if there is an incorrect or missing oldValue in this re-entrant case.

samreid commented 8 months ago

Patch from discoveries with @jbphet and @marlitas :

```diff Subject: [PATCH] Restore density testing, see https://github.com/phetsims/phet-io-wrappers/issues/551 --- Index: axon/js/DynamicProperty.ts IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/axon/js/DynamicProperty.ts b/axon/js/DynamicProperty.ts --- a/axon/js/DynamicProperty.ts (revision 2c5d217ca16faaa5be669b3a1b804027ce0bafc6) +++ b/axon/js/DynamicProperty.ts (date 1695749935550) @@ -241,13 +241,17 @@ * undefined. */ private onPropertyChange( newPropertyValue: OuterValueType | null, oldPropertyValue: OuterValueType | null | undefined ): void { + // console.log( 'new = ', newPropertyValue, 'old', oldPropertyValue ); if ( oldPropertyValue ) { + console.log( this.id, 'unlinking from ', oldPropertyValue ); this.derive( oldPropertyValue ).unlink( this.propertyPropertyListener ); } if ( newPropertyValue ) { + console.log( this.id, 'linking to ', newPropertyValue ); this.derive( newPropertyValue ).link( this.propertyPropertyListener ); } else { + console.log( 'null???' ); // Switch to null when our Property's value is null. this.onPropertyPropertyChange( this.defaultValue, null, null ); } Index: axon/js/PropertyTests.ts IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/axon/js/PropertyTests.ts b/axon/js/PropertyTests.ts --- a/axon/js/PropertyTests.ts (revision 2c5d217ca16faaa5be669b3a1b804027ce0bafc6) +++ b/axon/js/PropertyTests.ts (date 1695751222840) @@ -311,4 +311,30 @@ thirdProperty.dispose(); } ); -} \ No newline at end of file +} + +QUnit.test( 'TEST HELLO', assert => { + const myProperty = new Property( 'a',{ + reentrant: true + } ); + myProperty.link( value => { + if ( value === 'b' ) { + myProperty.value = 'c'; + } + } ); + + myProperty.link( ( value, oldValue ) => console.log( `link result: ${oldValue} => ${value}` ) ); + myProperty.value = 'b'; + + assert.ok( true, 'first test' ); + + // We hope: + // null => a + // a => b + // b => c + + // We think since it is buggy we will instead get: + // null=>a + // b=>c + // a=>b +} ); \ No newline at end of file Index: axon/js/TinyEmitter.ts IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/axon/js/TinyEmitter.ts b/axon/js/TinyEmitter.ts --- a/axon/js/TinyEmitter.ts (revision 2c5d217ca16faaa5be669b3a1b804027ce0bafc6) +++ b/axon/js/TinyEmitter.ts (date 1695750540343) @@ -171,7 +171,10 @@ // Throw an error when removing a non-listener (except when the Emitter has already been disposed, see // https://github.com/phetsims/sun/issues/394#issuecomment-419998231 if ( assert && !this.isDisposed ) { - assert( this.listeners.has( listener ), 'tried to removeListener on something that wasn\'t a listener' ); + if ( !this.listeners.has( listener ) ) { + console.log( this.listeners.has( listener ), 'tried to removeListener on something that wasn\'t a listener' ); + return; + } } this.guardListeners(); this.listeners.delete( listener ); Index: density-buoyancy-common/js/buoyancy/view/BoatView.ts IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/density-buoyancy-common/js/buoyancy/view/BoatView.ts b/density-buoyancy-common/js/buoyancy/view/BoatView.ts --- a/density-buoyancy-common/js/buoyancy/view/BoatView.ts (revision e3e1c677c4b60789c7a497f772567a3de905ca67) +++ b/density-buoyancy-common/js/buoyancy/view/BoatView.ts (date 1695746335194) @@ -142,6 +142,17 @@ boat.displacementVolumeProperty, boat.basin.liquidVolumeProperty ], ( boatLiquidY, boatDisplacement, boatLiquidVolume ) => { + + setTimeout( () => updateItAll(), 0 ); + + } ); + + const updateItAll = () => { + + const boatLiquidY = boat.basin.liquidYInterpolatedProperty.value; + const boatDisplacement = boat.displacementVolumeProperty.value; + const boatLiquidVolume = boat.basin.liquidVolumeProperty.value; + const poolLiquidY = liquidYInterpolatedProperty.value; const liters = boatDisplacement / 0.001; @@ -169,7 +180,7 @@ } bottomPoolClipPlane.constant = poolLiquidY; topPoolClipPlane.constant = -poolLiquidY; - } ); + }; Material.linkLiquidColor( boat.liquidMaterialProperty, topLiquidMaterial ); Material.linkLiquidColor( boat.liquidMaterialProperty, backMiddleMaterial ); Index: density-buoyancy-common/js/buoyancy/view/DensityReadoutListNode.ts IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/density-buoyancy-common/js/buoyancy/view/DensityReadoutListNode.ts b/density-buoyancy-common/js/buoyancy/view/DensityReadoutListNode.ts --- a/density-buoyancy-common/js/buoyancy/view/DensityReadoutListNode.ts (revision e3e1c677c4b60789c7a497f772567a3de905ca67) +++ b/density-buoyancy-common/js/buoyancy/view/DensityReadoutListNode.ts (date 1695750122003) @@ -26,8 +26,11 @@ align: 'center' } ); - this.children = materialProperties.map( materialProperty => { + this.children = [ materialProperties[ 0 ] ].map( materialProperty => { // Exists for the lifetime of a sim, so disposal patterns not needed. + const dynamicProperty = new DynamicProperty( materialProperty, { derive: material => material.nameProperty } ); + + console.log( 'making dynamic property material=>nameProperty', dynamicProperty.id ); return new RichText( new PatternStringProperty( new DerivedProperty( [ DensityBuoyancyCommonPreferences.volumeUnitsProperty, DensityBuoyancyCommonStrings.densityReadoutPatternStringProperty, @@ -35,7 +38,7 @@ ], ( units, litersString, decimetersCubedString ) => { return units === 'liters' ? litersString : decimetersCubedString; } ), { - material: new DynamicProperty( materialProperty, { derive: material => material.nameProperty } ), + material: dynamicProperty, density: new DerivedProperty( [ materialProperty ], material => material.density / 1000 ) }, { tandem: Tandem.OPT_OUT, ```

Indeed we saw the incorrect order in a listener test:

QUnit.test( 'TEST HELLO', assert => {
  const myProperty = new Property( 'a',{
    reentrant: true
  } );
  myProperty.link( value => {
    if ( value === 'b' ) {
      myProperty.value = 'c';
    }
  } );

  myProperty.link( ( value, oldValue ) => console.log( `link result: ${oldValue} => ${value}` ) );
  myProperty.value = 'b';

  assert.ok( true, 'first test' );

  // We hope:
  // null => a
  // a => b
  // b => c

  // We think since it is buggy we will instead get:
  // null=>a
  // b=>c
  // a=>b
} );
samreid commented 8 months ago

We proposed a fix for that problem above that has the correct behavior and doesn't use setTimeout. That is working well. However, when we tried to generalize to N levels of re-entrancy, it had very broken behavior:

```diff Subject: [PATCH] Restore density testing, see https://github.com/phetsims/phet-io-wrappers/issues/551 --- Index: axon/js/DynamicProperty.ts IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/axon/js/DynamicProperty.ts b/axon/js/DynamicProperty.ts --- a/axon/js/DynamicProperty.ts (revision 2c5d217ca16faaa5be669b3a1b804027ce0bafc6) +++ b/axon/js/DynamicProperty.ts (date 1695749935550) @@ -241,13 +241,17 @@ * undefined. */ private onPropertyChange( newPropertyValue: OuterValueType | null, oldPropertyValue: OuterValueType | null | undefined ): void { + // console.log( 'new = ', newPropertyValue, 'old', oldPropertyValue ); if ( oldPropertyValue ) { + console.log( this.id, 'unlinking from ', oldPropertyValue ); this.derive( oldPropertyValue ).unlink( this.propertyPropertyListener ); } if ( newPropertyValue ) { + console.log( this.id, 'linking to ', newPropertyValue ); this.derive( newPropertyValue ).link( this.propertyPropertyListener ); } else { + console.log( 'null???' ); // Switch to null when our Property's value is null. this.onPropertyPropertyChange( this.defaultValue, null, null ); } Index: axon/js/PropertyTests.ts IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/axon/js/PropertyTests.ts b/axon/js/PropertyTests.ts --- a/axon/js/PropertyTests.ts (revision 2c5d217ca16faaa5be669b3a1b804027ce0bafc6) +++ b/axon/js/PropertyTests.ts (date 1695752519473) @@ -311,4 +311,62 @@ thirdProperty.dispose(); } ); -} \ No newline at end of file +} + +QUnit.test( 'TEST HELLO', assert => { + const myProperty = new Property( 'a', { + reentrant: true + } ); + myProperty.link( value => { + if ( value === 'b' ) { + myProperty.value = 'c'; + } + } ); + + myProperty.link( ( value, oldValue ) => console.log( `link result: ${oldValue} => ${value}` ) ); + myProperty.value = 'b'; + + assert.ok( true, 'first test' ); + + // We hope: + // null => a + // a => b + // b => c + + // We think since it is buggy we will instead get: + // null=>a + // b=>c + // a=>b +} ); + +QUnit.test( 'TEST Property reentrant multi levels ', assert => { + const myProperty = new Property( 'a', { + reentrant: true + } ); + myProperty.link( value => { + if ( value === 'b' ) { + myProperty.value = 'c'; + } + else if ( value === 'c' ) { + myProperty.value = 'd'; + } + else if ( value === 'd' ) { + myProperty.value = 'e'; + } + } ); + + myProperty.link( ( value, oldValue ) => console.log( `link result: ${oldValue} => ${value}` ) ); + myProperty.value = 'b'; + + assert.ok( true, 'first test' ); + + // We hope: + // null => a + // a => b + // b => c + + // We think since it is buggy we will instead get: + // null=>a + // b=>c + // a=>b +} ); \ No newline at end of file Index: density-buoyancy-common/js/buoyancy/view/BoatView.ts IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/density-buoyancy-common/js/buoyancy/view/BoatView.ts b/density-buoyancy-common/js/buoyancy/view/BoatView.ts --- a/density-buoyancy-common/js/buoyancy/view/BoatView.ts (revision e3e1c677c4b60789c7a497f772567a3de905ca67) +++ b/density-buoyancy-common/js/buoyancy/view/BoatView.ts (date 1695746335194) @@ -142,6 +142,17 @@ boat.displacementVolumeProperty, boat.basin.liquidVolumeProperty ], ( boatLiquidY, boatDisplacement, boatLiquidVolume ) => { + + setTimeout( () => updateItAll(), 0 ); + + } ); + + const updateItAll = () => { + + const boatLiquidY = boat.basin.liquidYInterpolatedProperty.value; + const boatDisplacement = boat.displacementVolumeProperty.value; + const boatLiquidVolume = boat.basin.liquidVolumeProperty.value; + const poolLiquidY = liquidYInterpolatedProperty.value; const liters = boatDisplacement / 0.001; @@ -169,7 +180,7 @@ } bottomPoolClipPlane.constant = poolLiquidY; topPoolClipPlane.constant = -poolLiquidY; - } ); + }; Material.linkLiquidColor( boat.liquidMaterialProperty, topLiquidMaterial ); Material.linkLiquidColor( boat.liquidMaterialProperty, backMiddleMaterial ); Index: axon/js/ReadOnlyProperty.ts IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/axon/js/ReadOnlyProperty.ts b/axon/js/ReadOnlyProperty.ts --- a/axon/js/ReadOnlyProperty.ts (revision 2c5d217ca16faaa5be669b3a1b804027ce0bafc6) +++ b/axon/js/ReadOnlyProperty.ts (date 1695753423326) @@ -94,7 +94,7 @@ private tinyProperty: TinyProperty; // whether we are in the process of notifying listeners; changed in some Property test files with @ts-expect-error - private notifying: boolean; + private notifying: number; // whether to allow reentry of calls to set private readonly reentrant: boolean; @@ -113,6 +113,8 @@ protected readonly valueValidator: Validator; public static readonly TANDEM_NAME_SUFFIX: string = 'Property'; + private thingsToDoLater: Array<() => void> = []; + /** * This is protected to indicate to clients that subclasses should be used instead. * @param value - the initial value of the property @@ -176,7 +178,7 @@ // Since we are already in the heavyweight Property, we always assign TinyProperty.useDeepEquality for clarity. // @ts-expect-error this.tinyProperty.useDeepEquality = options.valueComparisonStrategy && options.valueComparisonStrategy === 'equalsFunction'; - this.notifying = false; + this.notifying = 0; this.reentrant = options.reentrant; this.isDeferred = false; this.deferredValue = null; @@ -259,7 +261,7 @@ else if ( !this.equalsValue( value ) ) { const oldValue = this.get(); this.setPropertyValue( value ); - this._notifyListeners( oldValue ); + this._notifyListeners( oldValue, value ); } } } @@ -289,8 +291,8 @@ /** * NOTE: a few sims are calling this even though they shouldn't */ - private _notifyListeners( oldValue: T | null ): void { - const newValue = this.get(); + private _notifyListeners( oldValue: T | null, newValue: T ): void { + // const newValue = this.get(); // validate the before notifying listeners assert && validate( newValue, this.valueValidator, VALIDATE_OPTIONS_FALSE ); @@ -308,12 +310,37 @@ } ); // notify listeners, optionally detect loops where this Property is set again before this completes. - assert && assert( !this.notifying || this.reentrant, + assert && assert( this.notifying === 0 || this.reentrant, `reentry detected, value=${newValue}, oldValue=${oldValue}` ); - this.notifying = true; + + const later = this.notifying > 0; - this.tinyProperty.emit( newValue, oldValue, this ); // cannot use tinyProperty.notifyListeners because it uses the wrong this - this.notifying = false; + console.log( 'incrementing notifying = ' + this.notifying, 'oldvalue = ' + oldValue, 'newValue = ', newValue ); + if ( oldValue === 'e' ) { + debugger; + } + + this.notifying++; + + if ( later ) { + + console.log( 'pushing one for later that has oldValue = ' + oldValue, 'newValue', newValue ); + + debugger; + this.thingsToDoLater.unshift( () => { + this.tinyProperty.emit( newValue, oldValue, this ); // cannot use tinyProperty.notifyListeners because it uses the wrong this + } ); + } + else { + this.tinyProperty.emit( newValue, oldValue, this ); // cannot use tinyProperty.notifyListeners because it uses the wrong this + } + + this.notifying--; + + if ( this.notifying === 0 ) { + this.thingsToDoLater.forEach( action => action() ); + this.thingsToDoLater.length = 0; + } Tandem.PHET_IO_ENABLED && this.isPhetioInstrumented() && this.phetioEndEvent(); } Index: density-buoyancy-common/js/buoyancy/view/DensityReadoutListNode.ts IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/density-buoyancy-common/js/buoyancy/view/DensityReadoutListNode.ts b/density-buoyancy-common/js/buoyancy/view/DensityReadoutListNode.ts --- a/density-buoyancy-common/js/buoyancy/view/DensityReadoutListNode.ts (revision e3e1c677c4b60789c7a497f772567a3de905ca67) +++ b/density-buoyancy-common/js/buoyancy/view/DensityReadoutListNode.ts (date 1695750122003) @@ -26,8 +26,11 @@ align: 'center' } ); - this.children = materialProperties.map( materialProperty => { + this.children = [ materialProperties[ 0 ] ].map( materialProperty => { // Exists for the lifetime of a sim, so disposal patterns not needed. + const dynamicProperty = new DynamicProperty( materialProperty, { derive: material => material.nameProperty } ); + + console.log( 'making dynamic property material=>nameProperty', dynamicProperty.id ); return new RichText( new PatternStringProperty( new DerivedProperty( [ DensityBuoyancyCommonPreferences.volumeUnitsProperty, DensityBuoyancyCommonStrings.densityReadoutPatternStringProperty, @@ -35,7 +38,7 @@ ], ( units, litersString, decimetersCubedString ) => { return units === 'liters' ? litersString : decimetersCubedString; } ), { - material: new DynamicProperty( materialProperty, { derive: material => material.nameProperty } ), + material: dynamicProperty, density: new DerivedProperty( [ materialProperty ], material => material.density / 1000 ) }, { tandem: Tandem.OPT_OUT, ```

We feel it overlaps with the intermediate states listed in https://github.com/phetsims/axon/issues/303

We saw that queueMicrotask for all callbacks did have the correct listener order. But that is a scary change.

Here is the one that uses queueMicrotask at every level:

```diff Subject: [PATCH] Restore density testing, see https://github.com/phetsims/phet-io-wrappers/issues/551 --- Index: axon/js/DynamicProperty.ts IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/axon/js/DynamicProperty.ts b/axon/js/DynamicProperty.ts --- a/axon/js/DynamicProperty.ts (revision 2c5d217ca16faaa5be669b3a1b804027ce0bafc6) +++ b/axon/js/DynamicProperty.ts (date 1695749935550) @@ -241,13 +241,17 @@ * undefined. */ private onPropertyChange( newPropertyValue: OuterValueType | null, oldPropertyValue: OuterValueType | null | undefined ): void { + // console.log( 'new = ', newPropertyValue, 'old', oldPropertyValue ); if ( oldPropertyValue ) { + console.log( this.id, 'unlinking from ', oldPropertyValue ); this.derive( oldPropertyValue ).unlink( this.propertyPropertyListener ); } if ( newPropertyValue ) { + console.log( this.id, 'linking to ', newPropertyValue ); this.derive( newPropertyValue ).link( this.propertyPropertyListener ); } else { + console.log( 'null???' ); // Switch to null when our Property's value is null. this.onPropertyPropertyChange( this.defaultValue, null, null ); } Index: axon/js/PropertyTests.ts IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/axon/js/PropertyTests.ts b/axon/js/PropertyTests.ts --- a/axon/js/PropertyTests.ts (revision 2c5d217ca16faaa5be669b3a1b804027ce0bafc6) +++ b/axon/js/PropertyTests.ts (date 1695752519473) @@ -311,4 +311,62 @@ thirdProperty.dispose(); } ); -} \ No newline at end of file +} + +QUnit.test( 'TEST HELLO', assert => { + const myProperty = new Property( 'a', { + reentrant: true + } ); + myProperty.link( value => { + if ( value === 'b' ) { + myProperty.value = 'c'; + } + } ); + + myProperty.link( ( value, oldValue ) => console.log( `link result: ${oldValue} => ${value}` ) ); + myProperty.value = 'b'; + + assert.ok( true, 'first test' ); + + // We hope: + // null => a + // a => b + // b => c + + // We think since it is buggy we will instead get: + // null=>a + // b=>c + // a=>b +} ); + +QUnit.test( 'TEST Property reentrant multi levels ', assert => { + const myProperty = new Property( 'a', { + reentrant: true + } ); + myProperty.link( value => { + if ( value === 'b' ) { + myProperty.value = 'c'; + } + else if ( value === 'c' ) { + myProperty.value = 'd'; + } + else if ( value === 'd' ) { + myProperty.value = 'e'; + } + } ); + + myProperty.link( ( value, oldValue ) => console.log( `link result: ${oldValue} => ${value}` ) ); + myProperty.value = 'b'; + + assert.ok( true, 'first test' ); + + // We hope: + // null => a + // a => b + // b => c + + // We think since it is buggy we will instead get: + // null=>a + // b=>c + // a=>b +} ); \ No newline at end of file Index: density-buoyancy-common/js/buoyancy/view/BoatView.ts IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/density-buoyancy-common/js/buoyancy/view/BoatView.ts b/density-buoyancy-common/js/buoyancy/view/BoatView.ts --- a/density-buoyancy-common/js/buoyancy/view/BoatView.ts (revision e3e1c677c4b60789c7a497f772567a3de905ca67) +++ b/density-buoyancy-common/js/buoyancy/view/BoatView.ts (date 1695746335194) @@ -142,6 +142,17 @@ boat.displacementVolumeProperty, boat.basin.liquidVolumeProperty ], ( boatLiquidY, boatDisplacement, boatLiquidVolume ) => { + + setTimeout( () => updateItAll(), 0 ); + + } ); + + const updateItAll = () => { + + const boatLiquidY = boat.basin.liquidYInterpolatedProperty.value; + const boatDisplacement = boat.displacementVolumeProperty.value; + const boatLiquidVolume = boat.basin.liquidVolumeProperty.value; + const poolLiquidY = liquidYInterpolatedProperty.value; const liters = boatDisplacement / 0.001; @@ -169,7 +180,7 @@ } bottomPoolClipPlane.constant = poolLiquidY; topPoolClipPlane.constant = -poolLiquidY; - } ); + }; Material.linkLiquidColor( boat.liquidMaterialProperty, topLiquidMaterial ); Material.linkLiquidColor( boat.liquidMaterialProperty, backMiddleMaterial ); Index: axon/js/ReadOnlyProperty.ts IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/axon/js/ReadOnlyProperty.ts b/axon/js/ReadOnlyProperty.ts --- a/axon/js/ReadOnlyProperty.ts (revision 2c5d217ca16faaa5be669b3a1b804027ce0bafc6) +++ b/axon/js/ReadOnlyProperty.ts (date 1695753747505) @@ -94,7 +94,7 @@ private tinyProperty: TinyProperty; // whether we are in the process of notifying listeners; changed in some Property test files with @ts-expect-error - private notifying: boolean; + private notifying: number; // whether to allow reentry of calls to set private readonly reentrant: boolean; @@ -113,6 +113,8 @@ protected readonly valueValidator: Validator; public static readonly TANDEM_NAME_SUFFIX: string = 'Property'; + // private thingsToDoLater: Array<() => void> = []; + /** * This is protected to indicate to clients that subclasses should be used instead. * @param value - the initial value of the property @@ -176,7 +178,7 @@ // Since we are already in the heavyweight Property, we always assign TinyProperty.useDeepEquality for clarity. // @ts-expect-error this.tinyProperty.useDeepEquality = options.valueComparisonStrategy && options.valueComparisonStrategy === 'equalsFunction'; - this.notifying = false; + this.notifying = 0; this.reentrant = options.reentrant; this.isDeferred = false; this.deferredValue = null; @@ -259,7 +261,7 @@ else if ( !this.equalsValue( value ) ) { const oldValue = this.get(); this.setPropertyValue( value ); - this._notifyListeners( oldValue ); + this._notifyListeners( oldValue, value ); } } } @@ -289,7 +291,7 @@ /** * NOTE: a few sims are calling this even though they shouldn't */ - private _notifyListeners( oldValue: T | null ): void { + private _notifyListeners( oldValue: T | null): void { const newValue = this.get(); // validate the before notifying listeners @@ -308,12 +310,37 @@ } ); // notify listeners, optionally detect loops where this Property is set again before this completes. - assert && assert( !this.notifying || this.reentrant, + assert && assert( this.notifying === 0 || this.reentrant, `reentry detected, value=${newValue}, oldValue=${oldValue}` ); - this.notifying = true; + + const later = this.notifying > 0; - this.tinyProperty.emit( newValue, oldValue, this ); // cannot use tinyProperty.notifyListeners because it uses the wrong this - this.notifying = false; + console.log( 'incrementing notifying = ' + this.notifying, 'oldvalue = ' + oldValue, 'newValue = ', newValue ); + // if ( oldValue === 'e' ) { + // debugger; + // } + + this.notifying++; + + // if ( later ) { + + console.log( 'pushing one for later that has oldValue = ' + oldValue, 'newValue', newValue ); + + // debugger; + window.queueMicrotask( () => { + this.tinyProperty.emit( newValue, oldValue, this ); // cannot use tinyProperty.notifyListeners because it uses the wrong this + } ); + // } + // else { + // this.tinyProperty.emit( newValue, oldValue, this ); // cannot use tinyProperty.notifyListeners because it uses the wrong this + // } + + this.notifying--; + + // if ( this.notifying === 0 ) { + // this.thingsToDoLater.forEach( action => action() ); + // this.thingsToDoLater.length = 0; + // } Tandem.PHET_IO_ENABLED && this.isPhetioInstrumented() && this.phetioEndEvent(); } Index: density-buoyancy-common/js/buoyancy/view/DensityReadoutListNode.ts IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/density-buoyancy-common/js/buoyancy/view/DensityReadoutListNode.ts b/density-buoyancy-common/js/buoyancy/view/DensityReadoutListNode.ts --- a/density-buoyancy-common/js/buoyancy/view/DensityReadoutListNode.ts (revision e3e1c677c4b60789c7a497f772567a3de905ca67) +++ b/density-buoyancy-common/js/buoyancy/view/DensityReadoutListNode.ts (date 1695750122003) @@ -26,8 +26,11 @@ align: 'center' } ); - this.children = materialProperties.map( materialProperty => { + this.children = [ materialProperties[ 0 ] ].map( materialProperty => { // Exists for the lifetime of a sim, so disposal patterns not needed. + const dynamicProperty = new DynamicProperty( materialProperty, { derive: material => material.nameProperty } ); + + console.log( 'making dynamic property material=>nameProperty', dynamicProperty.id ); return new RichText( new PatternStringProperty( new DerivedProperty( [ DensityBuoyancyCommonPreferences.volumeUnitsProperty, DensityBuoyancyCommonStrings.densityReadoutPatternStringProperty, @@ -35,7 +38,7 @@ ], ( units, litersString, decimetersCubedString ) => { return units === 'liters' ? litersString : decimetersCubedString; } ), { - material: new DynamicProperty( materialProperty, { derive: material => material.nameProperty } ), + material: dynamicProperty, density: new DerivedProperty( [ materialProperty ], material => material.density / 1000 ) }, { tandem: Tandem.OPT_OUT, ```
samreid commented 8 months ago

@zepumph and I worked out a pattern in TinyEmitter so that re-entrant emits are scheduled in order. It is working really well and resolves this problem. We are wondering if it should be the default behavior and if we can implement it in a way that has low risk for performance or memory problems in the non-re-entrant cases.

zepumph commented 8 months ago

I'd like to add that ?stringTest=dynamic causes an infinite loop in the patch. I'm nervous about what it would take to go "all in" on this, and would probably prefer to just have an option for cases we need it to (even a mutable option for a DynamicProperty to set/assert onto its provided parameter propertyProperty. Still more to think about. I think bringing @jonathanolson into the loop would be helpful from here.

I also added unit tests to Property to show how that fixed things up.

```diff Subject: [PATCH] update dependencies for chains test, https://github.com/phetsims/perennial/issues/334 --- Index: js/TinyEmitterTests.ts IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/js/TinyEmitterTests.ts b/js/TinyEmitterTests.ts --- a/js/TinyEmitterTests.ts (revision 2c5d217ca16faaa5be669b3a1b804027ce0bafc6) +++ b/js/TinyEmitterTests.ts (date 1695760327497) @@ -204,4 +204,63 @@ // Check these values when running with ?listenerOrder=reverse or ?listenerOrder=random or ?listenerOrder=random(123) console.log( values.join( '' ) ); +} ); + + +class FakeEmitter { + listeners = []; + notifyingCount = 0; + notifyingCountListeners = []; + emitContexts = []; + + constructor() {} + + addListener( listener ) { + this.listeners.push( listener ); + } + + emit( arg: number ) { + this.emitContexts.push( { + listeners: this.listeners, + arg: arg + } ); + if ( this.emitContexts.length === 1 ) { + while ( this.emitContexts.length > 0 ) { + const emitContext = this.emitContexts[ 0 ]; + for ( let i = 0; i < emitContext.listeners.length; i++ ) { + const listener = emitContext.listeners[ i ]; + listener( emitContext.arg ); + } + this.emitContexts.shift(); } + } + } + + handleSelf() { + + } +} + + +QUnit.test( 'TinyEmitter listener order bugz', assert => { + assert.ok( true ); + const emitter = new TinyEmitter(); + emitter.addListener( number => { + if ( number < 10 ) { + emitter.emit( number + 1 ); + } + } ); + emitter.addListener( number => console.log( number ) ); + emitter.emit( 1 ); + + /* + expect: + 2 + 1 + 3 + + desire: + 1 + 2 + 3 + */ } ); \ No newline at end of file Index: js/TinyEmitter.ts IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/js/TinyEmitter.ts b/js/TinyEmitter.ts --- a/js/TinyEmitter.ts (revision 2c5d217ca16faaa5be669b3a1b804027ce0bafc6) +++ b/js/TinyEmitter.ts (date 1695762396344) @@ -31,6 +31,7 @@ type EmitContext = { index: number; listenerArray?: TEmitterListener[]; + args: T; }; // Store the number of listeners from the single TinyEmitter instance that has the most listeners in the whole runtime. @@ -114,30 +115,37 @@ if ( this.listeners.size > 0 ) { const emitContext: EmitContext = { - index: 0 + index: 0, + args: args // listenerArray: [] // {Array.|undefined} assigned if a mutation is made during emit }; this.emitContexts.push( emitContext ); + // assert && assert( this.emitContexts.length <= 1000, 'reentrant depth of 1000 seems like a bug to me!' ); - for ( const listener of this.listeners ) { - listener( ...args ); - emitContext.index++; - - // If a listener was added or removed, we cannot continue processing the mutated Set, we must switch to - // iterate over the guarded array - if ( emitContext.listenerArray ) { - break; - } - } + if ( this.emitContexts.length === 1 ) { + while ( this.emitContexts.length > 0 ) { + const emitContext = this.emitContexts[ 0 ]; + const listeners = emitContext.listenerArray || Array.from( this.listeners ); + const hadListenerArray = !!emitContext.listenerArray; + for ( let i = 0; i < listeners.length; i++ ) { + const listener = listeners[ i ]; + listener( ...emitContext.args ); + emitContext.index++; + } - // If the listeners were guarded during emit, we bailed out on the for..of and continue iterating over the original - // listeners in order from where we left off. - if ( emitContext.listenerArray ) { - for ( let i = emitContext.index; i < emitContext.listenerArray.length; i++ ) { - emitContext.listenerArray[ i ]( ...args ); + // If the listeners were guarded during emit, we bailed out on the for..of and continue iterating over the original + // listeners in order from where we left off. + if ( emitContext.listenerArray ) { + for ( let i = emitContext.index; i < emitContext.listenerArray.length; i++ ) { + emitContext.listenerArray[ i ]( ...args ); + } + } + this.emitContexts.shift(); } } - this.emitContexts.pop(); + else { + console.log( this.emitContexts.length ); + } } } ```
zepumph commented 8 months ago

We met with @jonathanolson today and things seemed really promising. We found an infinite loop in Buoyancy with these changes when switching the "Volume units" simulation preference, this patch comments out the maxWidth setter in NumberDisplay to show that that is the bug. @jonathanolson wanted to take a look at that. There is also still that infinite loop to investigate with dynamic stringTest.

```diff Subject: [PATCH] so hard, so bad --- Index: axon/js/TinyEmitterTests.ts IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/axon/js/TinyEmitterTests.ts b/axon/js/TinyEmitterTests.ts --- a/axon/js/TinyEmitterTests.ts (revision 2c5d217ca16faaa5be669b3a1b804027ce0bafc6) +++ b/axon/js/TinyEmitterTests.ts (date 1695850084702) @@ -204,4 +204,19 @@ // Check these values when running with ?listenerOrder=reverse or ?listenerOrder=random or ?listenerOrder=random(123) console.log( values.join( '' ) ); +} ); + +QUnit.test( 'TinyEmitter listener order bugz', assert => { + const emitter = new TinyEmitter<[ number ]>(); + let count = 1; + emitter.addListener( number => { + if ( number < 10 ) { + emitter.emit( number + 1 ); + } + } ); + emitter.addListener( number => { + console.log( number ); + assert.ok( number === count++, `should go in order of emitting: ${number}` ); + } ); + emitter.emit( count ); } ); \ No newline at end of file Index: axon/js/TinyPropertyTests.ts IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/axon/js/TinyPropertyTests.ts b/axon/js/TinyPropertyTests.ts --- a/axon/js/TinyPropertyTests.ts (revision 2c5d217ca16faaa5be669b3a1b804027ce0bafc6) +++ b/axon/js/TinyPropertyTests.ts (date 1695849980490) @@ -21,6 +21,35 @@ assert.ok( true, 'one test' ); } ); +QUnit.test( 'TinyProperty notify in value-change order', assert => { + let count = 2; // starts as a value of 1, so 2 is the first value we change to. + + const myProperty = new TinyProperty( 1 ); + + myProperty.lazyLink( value => { + if ( value < 10 ) { + myProperty.value = value + 1; + } + } ); + + myProperty.lazyLink( ( value, oldValue ) => { + console.log( `asserts ${oldValue} => ${value}` ); + assert.ok( value === oldValue + 1, `increment each time: ${oldValue} -> ${value}` ); + assert.ok( value === count++, `increment in order expected: ${count - 2}->${count - 1}, received: ${oldValue} -> ${value}` ); + } ); + myProperty.value = count; + + // We hope: + // null => a + // a => b + // b => c + + // We think since it is buggy we will instead get: + // null=>a + // b=>c + // a=>b +} ); + QUnit.test( 'TinyProperty onBeforeNotify', assert => { class MyObservedObject { Index: axon/js/TinyEmitter.ts IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/axon/js/TinyEmitter.ts b/axon/js/TinyEmitter.ts --- a/axon/js/TinyEmitter.ts (revision 2c5d217ca16faaa5be669b3a1b804027ce0bafc6) +++ b/axon/js/TinyEmitter.ts (date 1695850084680) @@ -31,6 +31,7 @@ type EmitContext = { index: number; listenerArray?: TEmitterListener[]; + args: T; }; // Store the number of listeners from the single TinyEmitter instance that has the most listeners in the whole runtime. @@ -114,30 +115,36 @@ if ( this.listeners.size > 0 ) { const emitContext: EmitContext = { - index: 0 + index: 0, + args: args //.slice() as T // TODO: do we need to slice? https://github.com/phetsims/buoyancy/issues/67 // listenerArray: [] // {Array.|undefined} assigned if a mutation is made during emit }; this.emitContexts.push( emitContext ); + // assert && assert( this.emitContexts.length <= 1000, 'reentrant depth of 1000 seems like a bug to me!' ); - for ( const listener of this.listeners ) { - listener( ...args ); - emitContext.index++; - - // If a listener was added or removed, we cannot continue processing the mutated Set, we must switch to - // iterate over the guarded array - if ( emitContext.listenerArray ) { - break; - } - } + if ( this.emitContexts.length === 1 ) { + while ( this.emitContexts.length > 0 ) { + const emitContext = this.emitContexts[ 0 ]; + const listeners = emitContext.listenerArray || Array.from( this.listeners ); + for ( let i = 0; i < listeners.length; i++ ) { + listeners[ i ]( ...emitContext.args ); + emitContext.index++; + } - // If the listeners were guarded during emit, we bailed out on the for..of and continue iterating over the original - // listeners in order from where we left off. - if ( emitContext.listenerArray ) { - for ( let i = emitContext.index; i < emitContext.listenerArray.length; i++ ) { - emitContext.listenerArray[ i ]( ...args ); + // If the listeners were guarded during emit, we bailed out on the for..of and continue iterating over the original + // listeners in order from where we left off. + if ( emitContext.listenerArray ) { + for ( let i = emitContext.index; i < emitContext.listenerArray.length; i++ ) { + emitContext.listenerArray[ i ]( ...args ); + } + } + this.emitContexts.shift(); } } - this.emitContexts.pop(); + else { + // TODO: delete or assert out? "too many levels deep, it must be an infinite loop" 1000 worked well in testing, https://github.com/phetsims/buoyancy/issues/67 + console.log( 'this.emitContexts.length', this.emitContexts.length ); + } } } Index: scenery/js/nodes/Node.ts IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/scenery/js/nodes/Node.ts b/scenery/js/nodes/Node.ts --- a/scenery/js/nodes/Node.ts (revision 93246e46f9a0072ae8a8e05c04ddfbc110af7b5d) +++ b/scenery/js/nodes/Node.ts (date 1695850084698) @@ -3072,6 +3072,9 @@ public setCenterY( y: number ): this { const currentCenterY = this.getCenterY(); if ( isFinite( currentCenterY ) ) { + if ( this.constructor.name === 'RichText' ) { + console.log( 'y', y, currentCenterY ); + } this.translate( 0, y - currentCenterY, true ); } Index: scenery-phet/js/NumberDisplay.ts IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/scenery-phet/js/NumberDisplay.ts b/scenery-phet/js/NumberDisplay.ts --- a/scenery-phet/js/NumberDisplay.ts (revision 9d90b2325a590021ba74b585d1c110288a38292d) +++ b/scenery-phet/js/NumberDisplay.ts (date 1695850084707) @@ -244,8 +244,9 @@ longestStringProperty.link( longestString => { const demoText = new Constructor( longestString, _.omit( valueTextOptions, 'tandem' ) ); - valueText.maxWidth = ( options.textOptions.maxWidth !== null ) ? options.textOptions.maxWidth! : - ( demoText.width !== 0 ) ? demoText.width : null; + // TODO: This maxWidth causes a bug with "breadth first" listener order https://github.com/phetsims/buoyancy/issues/67 + // valueText.maxWidth = ( options.textOptions.maxWidth !== null ) ? options.textOptions.maxWidth! : + // ( demoText.width !== 0 ) ? demoText.width : null; demoText.maxWidth = valueText.maxWidth; backgroundNode.rectWidth = Math.max( options.minBackgroundWidth, demoText.width + 2 * options.xMargin ); @@ -260,6 +261,11 @@ this.valueText = valueText; this.backgroundNode = backgroundNode; + this.valueText.transformEmitter.listeners = new Set( [ () => { + debugger; + console.log( new Error().stack ); + }, ...Array.from( this.valueText.transformEmitter.listeners ) ] ); + // Align the value in the background. ManualConstraint.create( this, [ valueText, backgroundNode ], ( valueTextProxy, backgroundNodeProxy ) => {
zepumph commented 3 months ago

Since fixing #73, this issue is breaking CT just about every snapshot.

zepumph commented 3 months ago

Just catching up on this issue right now, it seems like there are two problems, and both feel like they are worth @jonathanolson's time in investigating. Co-assigning.

zepumph commented 3 months ago

Lots of great investigation here today. @jonathanolson and @AgustinVallejo and I were able to reproduce with steps in https://github.com/phetsims/buoyancy/issues/67#issuecomment-1735930418. This is far from the first time that reentrancy has meant that we can't trust the "oldValue" of the Property. For example, it was worked around in https://github.com/phetsims/scenery/commit/3f1cd688. So above @jonathanolson added another workaround that doesn't solve the underlying problem, but does solve the assertion we were getting by keeping track of the actually last set Property (old value) instead of trusting the value that comes from the Property listener callback parameter.

@jonathanolson and I were still worried about how this is quite buggy for DynamicProperty still in cases where the reentrant cases need to take precedent as the listened-to Property, since it will be swapped out for a previous propertyProperty. Basically this won't be solved until we have a general solution in https://github.com/phetsims/axon/issues/447.

BUT, it doesn't effect this case in buoyancy. This is because all the reentrant cases just HAPPEN to be mapping to the same value (all new instance of a custom Material have the same value for the nameProperty and the density as the combobox settles on the new value). This is totally happen stance, but at least we can close this issue. CT is clear, and we know how to proceed generally. Closing