Alternative to try, catch, finally in Haxe - haxe

In AS3 I could try/catch/finally a JSON file as follows:
try{
myJSON = JSON.parse(_fileReference.data.toString());
}
catch (e:TypeError){ //String?
_se.log.trace(e); //Never got called
}
finally{
if (null == myJSON){
_se.log.trace("SyntaxError: Error #1132: Invalid JSON parse input.");
return;
}
}
Is there a way to reproduce the Finally stage in Haxe? Finally was quite important to me, I liked the way it worked in this given scenario, it stopped the application from crashing or pausing with a window pop-up of the error.
Preferably looking for a raw solution that works for both AS3 and Haxe.

There is the scopes haxelib which I believe provides similar functionality to try/catch/finally with scope guards and protected blocks. See: https://bitbucket.org/parensoft/scopes
From the primitive protected/cleanup expressions example in their readme:
import scopes.Protect;
Protect.protect(PROT, CLEAN);
CLEAN will always be executed when PROT exits. This includes normal
completion or an abrupt exit with an exception, or a return, break or
continue statement.
Any abrupt exit from the CLEAN expression will shadow the previous
abrupt exit from the PROT expression, if any.
The value of the Protect.protect(PROT, CLEAN) expression is the value
of the PROT expression if it completes; otherwise it's unspecified
(and unreachable as well).
Actually adding the finally keyword to Haxe has been discussed before: https://github.com/HaxeFoundation/haxe/issues/3335 - however it looks like it is pending further discussion.

Related

Catching and recovering from error in C++ function called from Duktape

I have created a plugin for the OpenCPN marine navigation program that incorporates Duktape to provide a scripting capability. OpenCPN uses wxWidgets.
Basically, the plugin presents the user with a console comprising a script window, an output window and various buttons. The user enters their script (or loads it from a .js file) and clicks on Run. The script is run using duk_peval. On return I display the result, destroy the context and wait for the user to run again, perhaps after modifying the script. All this works well. However, consider the following test script:
add(2, 3);
function add(a, b){
if (a == b) throw("args match");
return(a + b);
}
If the two arguments in the call to add are equal. The script throws an error and the user can try again. This all works.
Now I can implement add as a c++ function thus:
static duk_ret_t add(duk_context *ctx){
int a, b;
a = duk_get_int(ctx, 0);
b = duk_get_int(ctx, 1);
if (a == b){
duk_error(ctx, DUK_ERR_TYPE_ERROR, "args match");
}
duk_pop_2(ctx);
duk_push_int(ctx, a+b);
return (1);
}
As written, this passes the error to the fatal error handler. I know I must not try and use Duktape further but I can display the error OK. However, I have no way back to the plugin.
The prescribed action is to exit or abort but these both terminate the hosting application, which is absolutely unacceptable. Ideally, I need to be able to return from the duk_peval call with the error.
I have tried running the add function using duk_pcall from an outer C++ function. This catches the error and I can display it from that outer function. But when I return from that outer function, the script carries on when it should not and the eventual return from the duk_peval call has no knowledge of the error.
I know I could use try/catch in the script but with maybe dozens of calls to the OpenCPN APIs this is unrealistic. Percolating an error return code all the way back, maybe through several C++ functions and then to the top-level script would also be very cumbersome as the scripts and functions can be quite complex.
Can anyone please suggest a way of passing control back to my invoking plugin - preferably by returning from the duk_peval?
I have cracked this at last.
Firstly, I use the following in error situations:
if (a == b){
duk_push_error_object(ctx, DUK_ERR_ERROR, "args match");
duk_thow(ctx);
}
If an error has been thrown, the returned values from duk_peval and duk_pcall are non-zero and the error object is on the stack - as documented
It is all working nicely for me now.

spockframework: check expected result after every feature

I am using spockframework and geb for test automation. I would like to execute after every feature a simple check to be sure that no error dialogs are shown, I have added the following cleanup() method:
def cleanup() {
expect:
$('.myErrrorDialogClass').isEmpty()
}
The code is executed after every feature but it does not throw any error when the dialog is shown.
Spock uses AST transforms to wire in the functionality for each test label (when, expect, etc); they may not run the transformations on the cleanup method. They are either not expecting or not encouraging assertions in cleanup, so that code may run but not actually assert anything.
You can get around this by using a standard Groovy assert call without the expect block.
Summarized from our comment discussion above - in case you want to accept it as an answer ;-)

GCHandle, AppDomains managed code and 3rd party dll

I have looking at many threads about the exception "cannot pass a GCHandle across AppDomains" but I still don't get it....
I'm working with an RFID Reader which is driven by a DLL. I don't have source code for this DLL but only a sample to show how to use it.
The sample works great but I have to copy some code in another project to add the reader to the middleware Microsoft Biztalk.
The problem is that the process of Microsoft Biztalk works in another AppDomain. The reader handle events when a tag is read. But when I run it under Microsoft Biztalk I got this annoying exception.
I can't see any solution on how to make it work...
Here is some code that may be interesting :
// Let's connecting the result handlers.
// The reader calls a command-specific result handler if a command is done and the answer is ready to send.
// So let's tell the reader which functions should be called if a result is ready to send.
// result handler for reading EPCs synchronous
Reader.KSRWSetResultHandlerSyncGetEPCs(ResultHandlerSyncGetEPCs);
[...]
var readerErrorCode = Reader.KSRWSyncGetEPCs();
if (readerErrorCode == tKSRWReaderErrorCode.KSRW_REC_NoError)
{
// No error occurs while sending the command to the reader. Let's wait until the result handler was called.
if (ResultHandlerEvent.WaitOne(TimeSpan.FromSeconds(10)))
{
// The reader's work is done and the result handler was called. Let's check the result flag to make sure everything is ok.
if (_readerResultFlag == tKSRWResultFlag.KSRW_RF_NoError)
{
// The command was successfully processed by the reader.
// We'll display the result in the result handler.
}
else
{
// The command can't be proccessed by the reader. To know why check the result flag.
logger.error("Command \"KSRWSyncGetEPCs\" returns with error {0}", _readerResultFlag);
}
}
else
{
// We're getting no answer from the reader within 10 seconds.
logger.error("Command \"KSRWSyncGetEPCs\" timed out");
}
}
[...]
private static void ResultHandlerSyncGetEPCs(object sender, tKSRWResultFlag resultFlag, tKSRWExtendedResultFlag extendedResultFlag, tKSRWEPCListEntry[] epcList)
{
if (Reader == sender)
{
// Let's store the result flag in a global variable to get access from everywhere.
_readerResultFlag = resultFlag;
// Display all available epcs in the antenna field.
Console.ForegroundColor = ConsoleColor.White;
foreach (var resultListEntry in epcList)
{
handleTagEvent(resultListEntry);
}
// Let's set the event so that the calling process knows the command was processed by reader and the result is ready to get processed.
ResultHandlerEvent.Set();
}
}
You are having a problem with the gcroot<> helper class. It is used in the code that nobody can see, inside that DLL. It is frequently used by C++ code that was designed to interop with managed code, gcroot<> stores a reference to a managed object. The class uses the GCHandle type to add the reference. The GCHandle.ToIntPtr() method returns a pointer that the C++ code can store. The operation that fails is GCHandle.FromIntPtr(), used by the C++ code to recover the reference to the object.
There are two basic explanations for getting this exception:
It can be accurate. Which will happen when you initialized the code in the DLL from one AppDomain and use it in another. It isn't clear from the snippet where the Reader class object gets initialized so there are non-zero odds that this is the explanation. Be sure to keep it close to the code that uses the Reader class.
It can be caused by another bug, present in the C++ code inside the DLL. Unmanaged code often suffers from pointer bugs, the kind of bug that can accidentally overwrite memory. If that happens with the field that stores the gcroot<> object then nothing goes wrong for a while. Until the code tries to recover the object reference again. At that point the CLR notices that the corrupted pointer value no longer matches an actual object handle and generates this exception. This is certainly the hard kind of bug to solve since this happens in code you cannot fix and showing the programmer that worked on it a repro for the bug is very difficult, such memory corruption problems never repro well.
Chase bullet #1 first. There are decent odds that Biztalk runs your C# code in a separate AppDomain. And that the DLL gets loaded too soon, before or while the AppDomain is created. Something you can see with SysInternals' ProcMon. Create a repro of this by writing a little test program that creates an AppDomain and runs the test code. If that reproduces the crash then you'll have a very good way to demonstrate the issue to the RFID vendor and some hope that they'll use it and work on a fix.
Having a good working relationship with the RFID reader vendor to get to a resolution is going to be very important. That's never not a problem, always a good reason to go shopping elsewhere.

CodeContracts: Invoking this method will always lead to an error

Still learning code contracts. When I create a small test, I get the following message from the checker: CodeContracts: Invoking this method will always lead to an error. If this is wanted, consider adding Contract.Requires(false) to document it.
I don't understand what it is try to tell me. How would I add Contract.Requires(false) to this example so the warning is not shown?
This is the code. Note that this is a contrived example solely for the purpose of learning CC.
void DoSomething(object test) {
Contract.Requires(test != null);
MessageBox.Show(test.ToString());
}
void InvokeDoSomething() {
DoSomething(null);
}
Code Contracts have discovered that you
Require a parameter to a method to never be null
Literally call it with null
CC is basically telling you that your code will always fail. The contract seems fine, but your call is bad. The solution is of course not to add Contract.Requires(false) but to not call the method with null.

XSD validation with XML reader, collecting validation errors. (C#)

I'm currently fighting with using an XMLSerializer to execute XSD validation and collect the validation errors in the files. The task is the validation of the file, based on custom XSD-s containing valueset information, presence information etc.
My problem is the following: when using the XMLReader it stops at the first error, if we attach a listener to the ValidationEvents of the reader (through XMLReaderSettings). So I simply catch the exception where I log the error. So far everything is fine, the problems start to appear after logging the exception. Right after that the XMLReader goes to the end tag of the failed field, but I cannot validate the next field due to an unexplained exception.
To put it in practice, here's my code where I catch the exception:
private bool TryDeserialize(XmlSerializer ser, XmlReader read,out object item)
{
string Itemname = read.Name;
XmlReader read2 = read.ReadSubtree();
try
{
item= ser.Deserialize(read2);
return true;
}
catch (Exception e)
{
_ErrorList.Add("XSD error at " + Itemname + ": " + e.InnerException.Message);
item = null;
return false;
}
}
This routine works well, but what follows is problematic. Assume I pass the following XML snippet to this code:
<a>2885</a>
<b>ABC</b>
<c>5</c>
Assume that 'b' may not have 'ABC' as a value, so I get an XSD error. At the end of this, the xmlreader will be at
'EndElement, Name=b'
from which I simply cannot move unless I get an exception. If I do xmlreader.read, then I get the following exception (cut the namespace here):
"e = {"The element 'urn:iso:.....b' cannot contain child element 'urn:iso:.....:c' because the parent element's content model is text only."}"
After this the xmlreader is at 'Element, Name=c', so it seems good, but when trying to deserialize it with the code above, I get the following exception:
'_message = "The transition from the 'ValidateElement' method to the 'ValidateText' method is not allowed."'
I don't really see how I may go over it. I tried without a second reader reading the subtree, but I have the same problem. Please suggest me something, I really am stuck. Thanks a lot in advance!
Greets
You may have to consider the following things:
In general, it is not always possible to "collect" all the errors, simply because validating parsers are free to abandon the validation process when certain types of errors occur, particularly those that put the validator in a state where it can't reliably recover. For e.g., a validator may still continue after running into a constraining facet violation for a simple type, but it'll skip a whole section if it runs in unexpected content.
Unlike parsing into a DOM, where the loading of a DOM is not affected by a validating reader failing validation, deserializing into an object is (or at least should be) totally different: DOM is about being well formed; deserializing, i.e. strong typing is about being valid.
Intuitively I would think that if you get a validation error, what is the point in continuing with the deserialization, and further validation?
Try validating your XML independent of deserialization. If indeed you get more errors flagged with this approach, then the above should explain why. If not, then you're chasing something else.

Resources