Complete
over 4 years ago

Custom Exceptions are broken or mis-documented (Monkey C, SDK and/or documentation bug)

Hello,

I just wanted to write a custom exception and stumbled across this bug.

Starting with the documentation here: https://developer.garmin.com/connect-iq/monkey-c/exceptions-and-errors/#creatinganexception

Code example from there:

class AppSpecificException extends Lang.Exception {
    //! Constructor
    //! @param msg Message explaining cause
    function initalize(msg) {
        Exception.initialize();
        self.mMessage = msg;
    }
}

(great code formatting works neither here nor there. please fix that)
Problems with the above code:
  1. It misses the import for `Toybox.Lang`, so it does not work properly out of the box. Please fix.
  2. It triggers a build warning: `Class 'AppSpecificException' does not initialize its super class, 'Exception'`
    Which can neither be fixed by calling `Lang.Exception.initialize();` instead of `Exception.initialize();`.
    Please fix.
  3. When the exception is used with a message (`throw new AppSpecificException("foo");`) it triggers this error:
     
    Error: Too Many Arguments Error
    Details: Failed invoking <symbol>
    Stack: 
      - initalize() at AppSpecificException.mc:8 0x1000133b 

    This one only disappears if you initialize the exception without a message (`throw new Lang.AppSpecificException();`), which kinda defeats the purpose of it all.
    Please fix.
  4. If you just deleted the body of the custom exception in hope of the parent have the correct default behavior, the code goes completely rouge and shows the "Too many arguments" error with a backtrace, that starts right, but the triggering file for the error might be some code, that is not even called or included anywhere.

This also is true, if you do not extend `Toybox.Lang.Exception`, but an exception that already has multiple constructor arguments like `Toybox.Lang.UnexpectedTypeException`.
Also if you call `new Toybox.Lang.UnexpectedTypeException("ss")`, so with too less arguments, the same error is triggered, although there are not **too many**, but **less than needed** arguments given. This is just confusing. Please fix.

Also hard-coded user path in error messages? I'll talk to that rayburn guy ;)

Error: Not Enough Arguments Error
Details: Failed invoking <symbol>
Stack: 
  - initialize() at /Users/rayburn/projects/toolchain5/mbsimulator/submodules/technology/monkeybrains/virtual-machine/api/Lang.mb:1457 0x30002cc4

Another thing, that is besides the point, but also a problem: it is not possible to have exception factories, because `throw` seems to want to have a fresh `class definition`, with `new` and everything.

Example:

using Toybox.Lang;

class UnknownTypesException extends Lang.Exception {
    public static function create() {
    	return new self();
    }
}

throw UnknownTypesException.create();

So the TL;DR:

  1. Please update the documentation
  2. SDK does not trigger wrong warnings for parents of exception not being initialized
  3. Custom Exceptions can not have messages
  4. Compiler goes rouge if custom exception does not have an initializer
  5. (after the above) Please make exception factories a thing :)

If you need anything, please feel free to contact me :)

--- Update 1

Correct the error message in Number 2

Former Member
Former Member
Parents
  • Former Member
    Former Member over 4 years ago in reply to jim_m_58

    > I've been scratching my head all day trying to figure out what you want to do, and finally found the base code for what you are trying in the programmer's guide.  This is likely really old and updated).

    This is why I posted the link for the documentation I was referring to :D

    I wanted to give as much context as possible.

    If by "API Guide" you mean this site: https://developer.garmin.com/connect-iq/api-docs/Toybox/Lang/Exception.html

    and by

    > Notice the examples are blank.

    There is no actual javascript to toggle the code examples, then I am with you. I am having them both (Programmers guide and API Docs) open all the time.

    The problem with the hidden examples on the API docs page above is, that the `<code>` has a class `source_code` which has `display: none` by default.

    I am using the API docs that came with the SDK 3.2.2-2020-08-28 for Windows right now, because the bug is already fixed there (no toggles, just showing the examples).

    As for

    > What is it you want to do?

    I am potentially writing a Barrel, to determine the native type of a value (string, number etc.). As far as I saw there is a construct for `instanceof`, but not something like `typeof`(JS).
    For that I want to have an exception if the type can not be determined.
    The exception can be handle by the app developer who uses the Barrel so there is no crash or something.

    Please point me in the right direction, if I have missed something that might already exist.

    If you have further questions, please, let me know :)

Comment
  • Former Member
    Former Member over 4 years ago in reply to jim_m_58

    > I've been scratching my head all day trying to figure out what you want to do, and finally found the base code for what you are trying in the programmer's guide.  This is likely really old and updated).

    This is why I posted the link for the documentation I was referring to :D

    I wanted to give as much context as possible.

    If by "API Guide" you mean this site: https://developer.garmin.com/connect-iq/api-docs/Toybox/Lang/Exception.html

    and by

    > Notice the examples are blank.

    There is no actual javascript to toggle the code examples, then I am with you. I am having them both (Programmers guide and API Docs) open all the time.

    The problem with the hidden examples on the API docs page above is, that the `<code>` has a class `source_code` which has `display: none` by default.

    I am using the API docs that came with the SDK 3.2.2-2020-08-28 for Windows right now, because the bug is already fixed there (no toggles, just showing the examples).

    As for

    > What is it you want to do?

    I am potentially writing a Barrel, to determine the native type of a value (string, number etc.). As far as I saw there is a construct for `instanceof`, but not something like `typeof`(JS).
    For that I want to have an exception if the type can not be determined.
    The exception can be handle by the app developer who uses the Barrel so there is no crash or something.

    Please point me in the right direction, if I have missed something that might already exist.

    If you have further questions, please, let me know :)

Children
  • There is no actual javascript to toggle the code examples

    Yeah, there was a bug and we haven't pushed updated documentation.

  • I'm pretty sure Travis has posted code in the past the does the checking with instanceOf to determine the object type.  You could just do something with an enum to return the type and not mess with exceptions, and have a "TypeUnknown" enum if you all through all the if() {} else if() {} conditions.

    I use instanceOf in a number of thing, but there it's to insure a type, or possibly follow a different code path based on the type.

    "If I see data is an InstanceOf Number in onBackgroundData, it's an error code, else it's real data"