Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

[Twine 2.1.1][SugarCube 2.14]this.error propagation in JavaScript, how do you do this the right way?

edited March 2017 in Help! with 2.0
Hey there!

So, I got one of those questions about coding.

I have the following problem:
Say, you have two JS functions, where one JS function calls (not mutually of course) the other function and a SugarCube macro that calls one of these JS functions.

So you get a call stack of:
// Use case 1
<<mySC2Macro>> -> func1() -> func2()

now, both func1() and func2() use the this.error() to output exceptions when an error occurs. This happens because sometimes func2() is called in some of my macros as is and not through func1(). So, we get the following scenario:
// Use case 2
<<myOtherSC2Macro>> -> func2()

Now, the problem is that, if we go through use case 1 (or use case 2, it doesn't matter, since the macro context is not passed) and an error occurs in func2 and we have not passed the macro's context (this) over to func1() and then over to func2(), we get an error message that says "this.error()" is undefined. Which does not help at all to find out what went wrong, even if you try to print the error prior to return this.error() that console.error() for some reason doesn't get executed (yeah, sounds like an anomally, I haven't got the slightest clue why that happens. It maybe has something to do with how the broswer executes JS and finds the error (missing error() function in 'this') before executing the actual script.).

My question is, how do you throw exceptions properly in SugarCube 2? Do you carry the macro context (this) over all your functions or do you use something fancy like "throw new Error()"? Or maybe something completely different?

Also, does anyone know a good lexer or any kind of context aware code editor for JS? I'm sometimes driven crazy by the type failures that I do while editing my code and tend to pass the wrong variables to my arguments, causing all kinds of errors that takes me hours to debug using console.error() and console.log().

Comments

  • edited March 2017
    Disane wrote: »
    Now, the problem is that, if we go through use case 1 (or use case 2, it doesn't matter, since the macro context is not passed) and an error occurs in func2 and we have not passed the macro's context (this) over to func1() and then over to func2(), we get an error message that says "this.error()" is undefined. Which does not help at all to find out what went wrong, even if you try to print the error prior to return this.error() that console.error() for some reason doesn't get executed (yeah, sounds like an anomally, I haven't got the slightest clue why that happens. It maybe has something to do with how the broswer executes JS and finds the error (missing error() function in 'this') before executing the actual script.).
    Exceptions are interrupts. When they occur, they immediately terminate the current execution, unwinding the call stack until they're either caught or unwind the entire stack.

    You haven't shown the code in question, so I can't say much more than that, save to point out that attempting to invoke an undefined function/method will throw an exception.

    Disane wrote: »
    My question is, how do you throw exceptions properly in SugarCube 2? Do you carry the macro context (this) over all your functions or do you use something fancy like "throw new Error()"? Or maybe something completely different?
    A bit of clarification first. The <MacroContext>.error() method is the prescribed way for macro handlers to return an error message to the user—whether that's you during testing or players in the wild. It has nothing to do with thrown exceptions, save for the fact that they're both ways of signaling errors.

    In your case, your macro's handler is what needs to return with a call to this.error(). You cannot do that from within your functions as that would only return control to the handler, not to the macro processor. So, I'd suggest writing your utility functions to throw exceptions, then wrapping the calls to said functions within a try/catch block and having the catch return a call to this.error().

    For example, in your macro handlers:
    Macro.add('mycustommacro', {
    	handler() {
    		// […]
    
    		try {
    			myUtilityFunctionWhichMayThrowExceptions();
    		}
    		catch (ex) {
    			return this.error(ex.message);
    		}
    
    		// […]
    	}
    });
    
    And within your utility functions to signal that an error has occurred:
    throw new Error('some descriptive error message');
    


    The other advantage to doing it this way is that if your utility functions throw exceptions for other reasons, they'll also get handled nicely.

    Disane wrote: »
    Also, does anyone know a good lexer or any kind of context aware code editor for JS? I'm sometimes driven crazy by the type failures that I do while editing my code and tend to pass the wrong variables to my arguments, causing all kinds of errors that takes me hours to debug using console.error() and console.log().
    You're not going to be able to catch most type errors at compile time since JavaScript is a dynamically typed language.

    As far as a linter to catch static syntax errors and other basic mistakes, ESLint is the current gold standard.
Sign In or Register to comment.