Calling a Delphi side function from a script that raises an exception raises a generic EDelphi exception on the script side. This hides the exception class of the actual Delphi side exception. I tried to investigate the implementation of the EDelphi Ijaddajadda interface but am lacking skills to see a way to extract the Delphi side class or at least the class name. The truth has to be out there...
Example, script side
Try
MyDelphiSideFunction; // May raise EOutOfmemory
Except on E:Exception do
PrintLn(E.ClassName);
End;
This always prints "EDelphi", no matter the actual Delphi side exception class (EOutOfmemory in this example).
How to get the "real" class or class name from E?
You cannot directly get the exception class type as the DWScript exception handler doesn't store that information anywhere and the Delphi side type wouldn't make sense inside the script anyway. You can however easily get the class name from the EDelphi script side exception object via the EDelphi.ExceptionClass property. Like this:
try
var x := 1/0;
except
on E: EDelphi do
WriteLn('Error: ' + E.Message + ' (' + E.ExceptionClass + ')');
on E: Exception do
WriteLn('Error: ' + E.Message);
else
WriteLn('Unknown exception type');
end;
Error: Floating point division by zero (EZeroDivide)
You can see the DWScript source code that transforms a Delphi side exception to a script side EDelphi exception here:
https://github.com/EricGrange/DWScript/blob/2d61c8a95fb4a2aab328f3cc84bb9f243c927286/Source/dwsExprs.pas#L2244
I simply searched the source on Github (the search on the main Bitbucket repo sucks) for "EDelphi": https://github.com/search?q=repo%3AEricGrange%2FDWScript%20EDelphi&type=code
This gave me this piece of code:
// A Delphi exception. Transform it to a EDelphi-dws exception
exceptObj:=CreateEDelphiObj(mainException.ClassName, mainException.Message);
I then looked at the CreateEDelphiObj method:
function TdwsProgramExecution.CreateEDelphiObj(const ClassName : String;
const Message : String) : IScriptObj;
begin
Result := IScriptObj(IUnknown(
ProgramInfo.Vars[SYS_EDELPHI].Method[SYS_TOBJECT_CREATE].Call([ClassName, Message]).Value));
(Result.ExternalObject as TdwsExceptionContext).ReplaceTop(LastScriptError); // temporary constructor expression
end;
This looks like a call to a script side constructor, passing the ClassName and Message strings as parameters. That's fine, but what happens to the ClassName value?
Again, looking at the search result I noticed the Delphi side implementation of the EDelphi constructor:
procedure TDelphiExceptionCreateMethod.Execute(info : TProgramInfo; var ExternalObject: TObject);
begin
inherited;
Info.ValueAsVariant[SYS_EDELPHI_EXCEPTIONCLASS_FIELD]:=Info.ValueAsVariant['Cls']
end;
So the constructor calls the inherited constructor and then stores the ClassName value in the FExceptionClass (the value of the SYS_EDELPHI_EXCEPTIONCLASS_FIELD constant) field.
At this point I could guess that the property would be called ExceptionClass so I used my DWScriptStudio IDE/debugger to write the example and verify the result.
