Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate ControllerEngine to QJSEngine + improve error handling #1795

Closed

Conversation

ferranpujolcamins
Copy link
Contributor

@ferranpujolcamins ferranpujolcamins commented Aug 30, 2018

To do

  • Testing
  • Add unit tests?
    • Test availability of exposed methods to JS
  • Install svg extension manually
  • Replace QByteArray
  • Completely remove QtScript classes
  • Check TODOs
  • Update strings & translations if needed
  • Update to Qt 5.12
  • Document JS api
  • Make error messages translatable
  • Add ControllerEngine version field on mappings
  • Write Controller Engine versions wiki page

Copy link
Contributor

@Be-ing Be-ing left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for getting started on this!

build/depends.py Outdated Show resolved Hide resolved
src/controllers/controller.h Outdated Show resolved Hide resolved
src/controllers/controllerengine.cpp Outdated Show resolved Hide resolved
src/controllers/controllerengine.cpp Outdated Show resolved Hide resolved
src/controllers/controllerengine.cpp Outdated Show resolved Hide resolved
src/controllers/engine/controllerengine.cpp Outdated Show resolved Hide resolved
src/controllers/engine/controllerengine.cpp Outdated Show resolved Hide resolved
src/controllers/engine/controllerengine.cpp Outdated Show resolved Hide resolved
src/controllers/engine/controllerengine.cpp Outdated Show resolved Hide resolved
src/controllers/engine/controllerengine.cpp Outdated Show resolved Hide resolved
@Be-ing
Copy link
Contributor

Be-ing commented Nov 22, 2018

I made a pull request to update scripts now that ControllerEngine::getThisObjectInFunctionCall is not available with QJSEngine.

@Be-ing
Copy link
Contributor

Be-ing commented Nov 23, 2018

I have been thinking about whether it's a good idea to introduce C++ exceptions here, which AFAIK are not used anywhere else in Mixxx. I know many developers advise against ever using exceptions, or at least avoid them in C++. I don't have enough experience with them to have much of an opinion about that (although Rust's Result enum seems much better because always it forces the caller to deal with potential problems), but I don't think C++ exceptions are necessary or helpful in this code.

I understand it intuitively corresponds to JS Error objects, but I think it compounds the problem of this code being overcomplicated with inconsistent behavior. The overcomplicated code was there before you started working on it, but I think it would be wise to clean it up while working on this code. There are many different places in ControllerEngine where JS code is evaluated. Each of these have subtly different behavior when an error occurs. Sometimes an annoying dialog is shown, sometimes it just logs a warning, and it's not clear if the possibility of JS errors is properly handled every time they may happen.

I think it would be better to wrap all calls to QJSEngine::evaluate in a single function that handles the possibility of errors. Throwing an exception from that function requires a bunch of redundant try-catch code every time the function is called, which kinda defeats the point of having a reusable function.

Don't bind "this" in beginTimer and makeConnection callbacks

Adapt ControllerEngine::checkException for QJSEngine

Rename checkException to handleEvaluationException
Since QJSEngine takes ownership of exposed QObjects it tried to delete
controller and controllerengine when QJSEngine was destroyed (i.e script reload
and mixxx shutdown). See https://bugreports.qt.io/browse/QTBUG-41171

This also has the benefit that we have a tighter control on what's exposed.
Since Signals and slots, properties and children of object are available
as properties of the created QJSValue, lots of undesired things were leaked
into the JS engine.
This helps inspecting the test results in eclipse test inspector.
Remove bytearrayclass since now QJSEngine has built in support for
QByteArray, which gets converted to a JS ArrayBuffer.
@Be-ing
Copy link
Contributor

Be-ing commented Nov 24, 2018

Please add new commits instead of rebasing. I cannot easily tell what you changed in the code since the last time I looked at it and now my PR does not cleanly merge. If we decide to clean up the history later, we can do that at the end before merging.

The old hacks for preserving the "this" object for
engine.makeConnection, engine.connectControl, and
engine.beginTimer do not work with QJSEngine, but QJSEngine
brings support for ES5, which supports Function.prototype.bind.
https://bugs.launchpad.net/mixxx/+bug/1733666
The old	hacks for preserving the "this" object for
engine.makeConnection, engine.connectControl, and
engine.beginTimer do not work with QJSEngine, but QJSEngine
brings support for ES5,	which supports Function.prototype.bind.
https://bugs.launchpad.net/mixxx/+bug/1733666
The old	hacks for preserving the "this" object for
engine.makeConnection, engine.connectControl, and
engine.beginTimer do not work with QJSEngine, but QJSEngine
brings support for ES5,	which supports Function.prototype.bind.
https://bugs.launchpad.net/mixxx/+bug/1733666
src/controllers/engine/controllerengine.cpp Outdated Show resolved Hide resolved
src/controllers/engine/controllerengine.cpp Outdated Show resolved Hide resolved
@ferranpujolcamins
Copy link
Contributor Author

fixing

Ferran Pujol Camins added 2 commits March 27, 2020 20:30
# Conflicts:
#	appveyor.yml
#	build/depends.py
#	res/controllers/midi-components-0.0.js
#	src/controllers/controller.h
#	src/controllers/controllerengine.h
#	src/controllers/engine/colorjsproxy.cpp
#	src/controllers/engine/controllerengine.cpp
#	src/controllers/hid/hidcontroller.cpp
#	src/preferences/dialog/dlgpreferences.cpp
#	src/preferences/dialog/dlgpreferences.h
#	src/skin/skincontext.cpp
#	src/skin/skincontext.h
#	src/test/controller_preset_validation_test.cpp
#	src/test/controllerengine_test.cpp
# Conflicts:
#	src/preferences/dialog/dlgpreferencesdlg.ui
@Be-ing
Copy link
Contributor

Be-ing commented Mar 27, 2020

Hmm there's still a merge conflict with src/preferences/dialog/dlgpreferencesdlg.ui

@ferranpujolcamins
Copy link
Contributor Author

I need to fix tests and do some manual testing

@Holzhaus
Copy link
Member

Holzhaus commented Apr 9, 2020

I already started resolving merge conflicts that emerged due to my recent controller related changes, but then I noticed that this doesn't build as-is. A fix can be found here: ferranpujolcamins#15

Also, the ControllerPresetValidationTest.MidiPresetsValid test fails. Apparently the ColorMapper class has been removed?

ControllerEngine: "Uncaught exception at line 1004 in file file:///data/jan/Projects/mixxx/res/controllers/Roland_DJ-505-scripts.js: ReferenceError: ColorMapper is not defined"
ControllerEngine shutting down...
/home/jan/Projects/mixxx/src/test/controller_preset_validation_test.cpp:131: Failure
Value of: testLoadPreset(preset)
  Actual: false
Expected: true
Error while validating /data/jan/Projects/mixxx/res/controllers/Roland_DJ-505.midi.xml

@Holzhaus
Copy link
Member

Also, the ControllerPresetValidationTest.MidiPresetsValid test fails. Apparently the ColorMapper class has been removed?

ControllerEngine: "Uncaught exception at line 1004 in file file:///data/jan/Projects/mixxx/res/controllers/Roland_DJ-505-scripts.js: ReferenceError: ColorMapper is not defined"
ControllerEngine shutting down...
/home/jan/Projects/mixxx/src/test/controller_preset_validation_test.cpp:131: Failure
Value of: testLoadPreset(preset)
  Actual: false
Expected: true
Error while validating /data/jan/Projects/mixxx/res/controllers/Roland_DJ-505.midi.xml

Ping. This still fails both with cmake and scons.

@Holzhaus
Copy link
Member

Conflicts resolved here: ferranpujolcamins#16
Since this branch is broken, I was unable to test it properly, so better double check if I missed something.

@Be-ing
Copy link
Contributor

Be-ing commented Apr 19, 2020

ColorMapper and ColorMapperJSProxy are fixed here: ferranpujolcamins#17

ControllerPresetValidationTest.MidiPresetsValid is failing in a strange way. It is saying there is an exception in Components when loading mappings that don't use Components??

LINT: "/home/be/sw/mixxx/res/controllers/Hercules DJControl Compact.midi.xml" has no forum link.
ControllerEngine: "Uncaught exception at line 126 in file /home/be/sw/mixxx/res/controllers/midi-components-0.0.js: TypeError: Result of expression 'this.output.bind' [undefined] is not a function."
src/test/controller_preset_validation_test.cpp:193: Failure
Value of: testLoadPreset(preset)
  Actual: false
Expected: true
...
LINT: "/home/be/sw/mixxx/res/controllers/Reloop Terminal Mix 2-4.midi.xml" has no forum link.
ControllerEngine: "Uncaught exception at line 126 in file /home/be/sw/mixxx/res/controllers/midi-components-0.0.js: TypeError: Result of expression 'this.output.bind' [undefined] is not a function."
src/test/controller_preset_validation_test.cpp:193: Failure
Value of: testLoadPreset(preset)
  Actual: false
Expected: true

@Be-ing
Copy link
Contributor

Be-ing commented Apr 19, 2020

Actually the tests do work. I got confused because CMake does not install the mixxx-test binary; it has to be run from the CMake build directory. I took the next step and implemented an API for scripts to work without XML mappings: #2682

@ferranpujolcamins
Copy link
Contributor Author

ferranpujolcamins commented Apr 22, 2020

@Holzhaus can you solve the merge conflicts you intoduced with #2588?

@Be-ing
Copy link
Contributor

Be-ing commented Apr 22, 2020

@ferranpujolcamins merge conflicts are already solved in #2682. I think we can close this PR without merging now.

Be-ing added a commit to Be-ing/mixxx that referenced this pull request May 22, 2020
This was introduced in PR mixxxdj#1795 when the migration to QJSEngine was
planned for a release when the latest Ubuntu version shipped Qt 5.9,
which did not support ES7. The purpose was to show users an error when
they loaded a script using ES7 if they were using a Qt version before
5.12. Since Mixxx 2.3 took so long, the QJSEngine migration will be
released when the latest Ubuntu LTS (20.04) ships Qt 5.12, so we do not
need to introduce this "controller engine version" concept anymore.

Mixxx will still build and run with Qt < 5.12 at the small cost of
keeping only one #if in ControllerEngine::throwJSError, but mappings
using ES7, which now includes any mapping using the Components library,
will not work.
Be-ing added a commit to Be-ing/mixxx that referenced this pull request May 27, 2020
This was introduced in PR mixxxdj#1795 when the migration to QJSEngine was
planned for a release when the latest Ubuntu version shipped Qt 5.9,
which did not support ES7. The purpose was to show users an error when
they loaded a script using ES7 if they were using a Qt version before
5.12. Since Mixxx 2.3 took so long, the QJSEngine migration will be
released when the latest Ubuntu LTS (20.04) ships Qt 5.12, so we do not
need to introduce this "controller engine version" concept anymore.

Mixxx will still build and run with Qt < 5.12 at the small cost of
keeping only one #if in ControllerEngine::throwJSError, but mappings
using ES7, which now includes any mapping using the Components library,
will not work.
@Be-ing Be-ing mentioned this pull request Sep 7, 2020
@ronso0 ronso0 removed this from the 2.4.0 milestone Nov 30, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

8 participants