-
Notifications
You must be signed in to change notification settings - Fork 35
Error Handling
Any errors happened in ReoScript will be thrown as following exceptions.
ReoScriptException
+- ReoScriptRuntimeException
+- ReoScriptAssertionException
+- CallStackOverflowException
+- ReoScriptCompilingException
ReoScript support to pre-interpret a script in text and converts it into a syntax-tree in memory (like compiling). During this operation, all the syntax errors can be detected and handled.
There is three ways to get errors at compiling-time.
-
Catch error instantly
When the syntax-error is detected, ReoScript throws the ReoScriptCompilingException and terminates the compiling operation instantly.
ScriptRunningMachine srm = new ScriptRunningMachine(); CompiledScript cs = null; try { cs = srm.Compile("console.log('a);"); // string end without ' } catch (ReoScriptCompilingException ex) { MessageBox.Show(ex.Message); }
The message displayed as below:
syntax error at char 16 on line 1, unexpected token <EOF>
-
Try to compile the entire script, get the errors from a list after compiling is finished
By passing the second parameter as true to
srm.Compile
indicates that ReoScript putting any errors in a list.cs = srm.Compile(@" var hello = function() { console.log('hello'); } /* error: missing ; */ hello(); function fun1() { return function() { /* error: missing } */ }; fun1(); ", true);
When the compiling is finished, enumerate over the list to get errors.
foreach (ErrorObject e in cs.CompilingErrors) { Console.WriteLine(e.Message); }
The errors will be printed out like:
syntax error at char 1 on line 6, missing SEMI syntax error at char 0 on line 14, expect RCURLY
Some errors does not effect the script execution even it detected in compile-time. ReoScript try to complete the syntax-tree after an error happening. In the above example the script still can be executed.
-
Try to compile the entire script, and get the error instantly
By passing the second parameter as CompilingErrorHandler anonymous function to handle the error once it happened.
srm.Compile(script, e=>{ MessageBox.Show(e.GetFullErrorInfo()); });
All ReoScript exceptions may contains an ErrorObject which used in both .NET and script. ErrorObject contains error information such as line number, char position in the line and call-stack information.
StringBuilder sb = new StringBuilder();
foreach (ErrorObject e in cs.CompilingErrors)
{
sb.AppendLine(string.Format("Message : {0}", e.Message));
sb.AppendLine(string.Format("Char Index : {0}", e.CharIndex));
sb.AppendLine(string.Format("Line : {0}", e.Line));
sb.AppendLine();
}
Console.WriteLine(sb.ToString());
The output is:
Message : syntax error at char 1 on line 6, missing SEMI
Char Index : 1
Line : 6
Message : syntax error at char 0 on line 14, expect RCURLY
Char Index : 0
Line : 14
Call-stack information stored in ErrorObject only script is running. The full call-stack information can be displayed using GetAllErrorInfo()
or DumpCallStack()
. For example:
try
{
srm.Run(@"
function get_system_path(key) {
get_env('path=' + key); // throw exception: get_env is not defined
}
function get_current_instance() {
get_system_path('startup-path');
}
function get_login_user() {
get_system_path();
}
get_login_user();
");
}
catch (ReoScriptException ex)
{
ErrorObject e = ex.ErrorObject;
if (e != null)
{
Console.WriteLine(e.GetFullErrorInfo());
}
}
The error information will be printed out with call-stack information:
Error: Function is not defined: get_env
at get_system_path (4:2)
at get_login_user (12:2)
at __entry__ (15:0)
Standard ECMAScript try/catch/finally/throw are supported by ReoScript.
Any errors could be caught using try catch syntax:
try {
// calling non-existent function causes a run-time error
undefinedfunc();
} catch(e) {
// e is instance of Error function
alert(e.message);
}
Does not matter what is the result of try block, run the finally block anyway.
allocMemory();
try {
// do something and error here
undefinedfunc();
} catch(e) {
console.log(e);
} finally {
releaseMemory();
}
You may throw a customize error with message.
try {
if (true) {
throw new Error('error anyway');
}
} catch(e) {
alert(e.message) // 'error anyway'
}
Errors could be thrown again, or with new one instead of old.
try {
try {
throw 'inner error';
} catch(e) {
if(e == 'inner error') {
throw 'outer error';
}
}
} catch(e) {
// e is 'outer error'
}