Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Match runtime error numbers and descriptions to VB6 / VBA #56

Open
WaynePhillipsEA opened this issue Apr 17, 2021 · 32 comments
Open

Match runtime error numbers and descriptions to VB6 / VBA #56

WaynePhillipsEA opened this issue Apr 17, 2021 · 32 comments
Labels
bug Something isn't working confirmed the issue has been verified

Comments

@WaynePhillipsEA
Copy link
Collaborator

Describe the bug
At the moment, runtime error numbers and descriptions often do not match VB6 / VBA.

Expected behavior
For backwards compatibility reasons, error numbers and descriptions should match VB6 / VBA

Desktop (please complete the following information):

  • OS: Windows 10
  • twinBASIC compiler version 0.9.1666

Additional context
Often, twinBASIC just reports a generic E_FAIL error code (0x80004005). All error points need to be reviewed and matched appropriately.

@WaynePhillipsEA WaynePhillipsEA added bug Something isn't working confirmed the issue has been verified labels Apr 17, 2021
@WaynePhillipsEA
Copy link
Collaborator Author

This is a known limitation with the preview release. Reported here so that we can track it.

@mburns08109
Copy link

mburns08109 commented Sep 17, 2021

I can understand the desire to do this from a backwards compatibility POV, but frankly some of the VBx error message didn't make much sense.
One example - error 5 is thrown when an collection.item("SomeItemhere") looks for an item not found in the collection.
There REALLY should be a separate, different "item not found in collection" error rather than the generic error 5.

Perhaps we could as some future enhancements in error handling - add an OPTION ENHANCED ERRORS mode or something to tB so that some better, more precise errors can be thrown for new code built to expect them?

...and also PLEASE - enhance the future documentation for errors AND for built-in Functions & parameters!

It used to drive me nuts to try and find WHAT THE DANGED TYPE IS of some function's return value because they forgot to mention it in the docs. (perhaps this was more of a problem with ActiveX libraries then core language functions, and I'm ranting at the wrong thing for the wrong reasons here, but I surely remember the frustration of it!)

@DaveInCaz
Copy link

Would the VSCode tools for tB have the ability to tell you the entire specification of a function automatically? (Types of args, return, etc.)?

@WaynePhillipsEA
Copy link
Collaborator Author

@mburns08109 yes, I've got some vague ideas on how I'm going to handle that. Indeed, this will be an opt-in feature as we must ensure backwards compatibility is the priority foremost.

@DaveInCaz yes, the intellisense/signature-help should give you the full function signature info. Many of the built-in functions use/return Variants though, so it will be the job of the documentation to highlight the possible accepted or return types. The documentation is also shown alongside the signature-help in VS code, which you can see in the MsgBox function (though none of the other builtin functions have associated documentation just yet).

@mburns08109
Copy link

mburns08109 commented Sep 17, 2021

Speaking of all that, I also used to long for a section in the documentation listing:
"Known possible Error values arising from this Function:"
followed by a list of the known/built-in errors that the function itself is able to throw - i.e. those errors that the implementation code will test for and throw...as opposed to errors that underlying/called function things may throw.

Such info in the docs would have made building error handlers MUCH easier (and much more competent).
"Oh! I didn't realize that my code may need to handle a full disk here..."

@Kr00l
Copy link
Collaborator

Kr00l commented Sep 17, 2021

The downside of an opt-in "extended" error functionality could cause a mess in the generic codebase.

For example you find code snippets that rely on certain error codes. (Classic error codes)

Then those will not work anymore as you have that opt-in selected, because you have already code that rely on the "new extended" ones.

So my 2 cents for that. :)
I pledge to live with the error codes as is and that's it.

@mburns08109
Copy link

Kr00l,
Perhaps if it were implemented as a module-based OPTION, the effect of that type of issue could be greatly minimized?
(the default value being OFF, of course)

@Kr00l
Copy link
Collaborator

Kr00l commented Sep 17, 2021

Kr00l,
Perhaps if it were implemented as a module-based OPTION, the effect of that type of issue could be greatly minimized?
(the default value being OFF, of course)

That would be a solution..

Downside would be more complexity. (more "choices", bloatage)

@mburns08109
Copy link

IMO that downside might well be acceptable - if the benefit (especially to the casual/"beginning" developer) is clearer and more meaningful error messages for some things.
(Of course, that's not "my call" to make .) :-)

@Greedquest
Copy link

@mburns08109 would keeping the same error number but changing the error description be a satisfactory compromise? Current code should not be reflecting off the descriptions in error handlers so changing them shouldn't break current code. You could even use enums to alias error 5 in a collection to mean something different than error 5 in a message box, without changing the underlying value.

@mwolfe02
Copy link

Current code should not be reflecting off the descriptions in error handlers so changing them shouldn't break current code.

I strongly disagree. 100% compatible means 100% compatible, quirks (especially) and all. The difference between 99% compatible and 100% compatible is WAY more than 1%. It's the difference between taking your old code and having it Just Work™ and spending hours trying to track down and fix all the little things that are juuust a little bit different between the two versions.

If anything, this could be a module-based (or even a project-based) option (as @mburns08109 suggested).

I can't remember whether there has been a discussion about supporting a "Quirks" mode. "Quirks" mode could be a mode intended primarily for VB6 migrations where outright bugs in VB6 are re-implemented. If feasible, "Quirks" mode could be turned on in the project settings if you import a VB6 project (.vbp) but disabled by default for new development. If twinBASIC's goal is 100% VBx compatibility, then "Quirks" mode would provide--to quote many a sports coach--110% compatibility.

@mwolfe02
Copy link

I can't remember whether there has been a discussion about supporting a "Quirks" mode.

Quirks mode discussion is here: #215

@Greedquest
Copy link

Greedquest commented Oct 18, 2021

@mwolfe02 Yes, "shouldn't break current code" probably came across as a sweeping overstatement on my part. However what I meant was to contrast two options for implementing @mburns08109's suggested "enhanced errors":

  • using existing numbers + new messages + enum aliases.
  • changing the numbers themselves.

... and to say the first option would be preferable since it would break less code IMO. This was already assuming that any change to the VBx defaults would be implemented in a safe way that doesn't break backwards compatibility as you describe - e.g with option statements, quirk mode, alternative Error API etc. Hope that's more clear.

@LeslieMurphy
Copy link

The values from Err.Raise are not passed into the On Error handler.

From Err.Raise 1000, "openDB", "sqlite_open failed, res = " & res
I get errNumber= -2147023896 0x800703E8

Option Explicit

Module TestSQLite32bit

    ' sqlite3_open {
'Declare PtrSafe Function sqlite3_open Lib "sqlite3.dll" ( _
'     ByVal zFilename As String, _
'     ByRef ppDB As LongPtr _
') As LongPtr ' }

' sqlite3_close {
'Declare PtrSafe Function sqlite3_close Lib "sqlite3.dll" ( _
'     ByVal db As LongPtr _
') As LongPtr ' }

Public Const SQLITE_OK      = 0  ' Successful result
Public Const SQLITE_ERROR   = 1  ' Generic Error
Public Const SQLITE_BUSY    = 5  ' The database file is locked
Public Const SQLITE_TOOBIG  = 18  ' String or BLOB exceeds size limit
Public Const SQLITE_MISUSE  = 21  ' Library used incorrectly
Public Const SQLITE_ROW     = 100  ' sqlite3_step() has another row ready
Public Const SQLITE_DONE    = 101  ' sqlite3_step() has finished executing

Public Sub Main()

        Debug.Print "start"
        Debug.Print "Temp is " & Environ("temp") ' C:\Users\lesmu\AppData\Local\Temp

        On Error GoTo errHandler

        Dim db As LongPtr
        db = openDB(Environ("temp") & "\test.db")
        Debug.Print "opened DB!"
        
        Exit Sub
        
        errHandler:
            Debug.Print "errNumber= " & Err.Number & " 0x" & Hex(Err.Number) & " " & Err.Description
	
    End Sub
    
    Function openDB(fileName As String) As LongPtr 

        Dim res As LongPtr
        Debug.Print "attempt SQLITE DB open"
        res = SQLITE_ERROR ' force error
        ' res = sqlite3_open(fileName, openDB)
        If res <> SQLITE_OK Then
           Err.Raise 1000, "openDB", "sqlite_open failed, res = " & res
        End If
    
        Debug.Print ("SQLite db opened, db = " & openDB)
    
    End Function 
    
End Module

@Greedquest
Copy link

@LeslieMurphy Interestingly for me, it's incorrect by a constant offset so the +1000 error number makes it through (set it to a different value and take the difference).

@LeslieMurphy
Copy link

Confirmed! And for some values there is an associated error message, but it is not the text from the Err.Raise. The value is taken as a hex value, so it seems.

' 1000 errNumber= -2147023896 0x800703E8
' 2000 errNumber= -2147022896 0x800707D0 The pixel format is invalid.
' 2001 errNumber= -2147022895 0x800707D1 The specified driver is invalid.

https://docs.microsoft.com/en-us/office/vba/Language/Reference/user-interface-help/raise-method

The range 0–512 is reserved for system errors; the range 513–65535 is available for user-defined errors.

https://docs.microsoft.com/en-us/windows/win32/debug/system-error-codes--1700-3999-

ERROR_INVALID_PIXEL_FORMAT
2000 (0x7D0)

The pixel format is invalid.

ERROR_BAD_DRIVER
2001 (0x7D1)

The specified driver is invalid.

@WaynePhillipsEA
Copy link
Collaborator Author

Yes, this will be fixed as part of the work for this issue coming soon. For now you can ignore the upper 16-bits of the value, i.e. Err.Number and &HFFFF& should do it

@WaynePhillipsEA
Copy link
Collaborator Author

Some work has started on this now. From v0.13.42, external COM errors (i.e. from outside of tB) should now be more helpful:

tbExternalCOMErrors

@wqweto
Copy link

wqweto commented Dec 17, 2021

JFYI, this works in VBx

        Dim cn As New ADODB.Connection
    
        On Error GoTo EH
        cn.Open "Provider=Test"
        Exit Sub
    EH:
        Debug.Assert Err.Number = ADODB.ErrorValueEnum.adErrProviderNotFound

I.e. when methods on interfaces from a COM library are failing the retrieved error number in the built-in Err object can be matched against custom ErrorValueEnums provided by the same component already stripped of HRESULT-edness.

@LeslieMurphy
Copy link

LeslieMurphy commented Dec 17, 2021 via email

@WaynePhillipsEA
Copy link
Collaborator Author

Debug.Assert Err.Number = ADODB.ErrorValueEnum.adErrProviderNotFound

At the moment the HRESULTs are returned raw via Err.Number, but that will be resolved over the next few days.

@WaynePhillipsEA
Copy link
Collaborator Author

JFYI, this works in VBx

        Dim cn As New ADODB.Connection
    
        On Error GoTo EH
        cn.Open "Provider=Test"
        Exit Sub
    EH:
        Debug.Assert Err.Number = ADODB.ErrorValueEnum.adErrProviderNotFound

Now works as expected in tB, as of v0.13.45, thanks.

@WaynePhillipsEA
Copy link
Collaborator Author

WaynePhillipsEA commented Dec 20, 2021

With v0.13.48, errors thrown from twinBASIC will now include the correct error information to the COM caller (rather than the generic error message you used to get):
tbCOMErrors1

@WaynePhillipsEA
Copy link
Collaborator Author

In v0.13.63:

  • all VBA.Conversion module functions now throw errors matching VBx (ENGLISH ONLY FOR NOW)
  • all VBA.String module functions now throw errors matching VBx (ENGLISH ONLY FOR NOW)

@bclothier
Copy link
Collaborator

Nice! I do want to ask, though: aren't those messages contained in some resources in some DLL that can be harvested and imported as-is?

@WaynePhillipsEA
Copy link
Collaborator Author

WaynePhillipsEA commented Jan 6, 2022

Nice! I do want to ask, though: aren't those messages contained in some resources in some DLL that can be harvested and imported as-is?

We need a platform independent solution, and so we are embedding the string table ourselves into the resultant builds. The error messages themselves are easy enough to extract (either using the VB Error function, or by extracting from MSVBVM60.DLL as you say). The table is small anyway (3KB English) so doesn't cost much to embed it.

The plan is for us to have the strings in a json file that the compiler loads during startup, and there will be an option in Settings so that you can choose either a specific language, or 'system language (compile-time)' or 'system language (runtime)'.

@bclothier
Copy link
Collaborator

I asked because of the comment that it was English only and I thought they had an internationalization resource DLL that contains all translations of the messages.

@WaynePhillipsEA
Copy link
Collaborator Author

I asked because of the comment that it was English only and I thought they had an internationalization resource DLL that contains all translations of the messages.

Ah ok. If I remember correctly, they ship different DLLs for each target language, though I could be mistaken on that.

@KarlSevenSeven
Copy link

I wouldn't localize the error descriptions.
On errors we have to make our own messages anyways.

@WaynePhillipsEA
Copy link
Collaborator Author

In v0.13.66:

  • all VBA.Information module functions now throw errors matching VBx (ENGLISH ONLY FOR NOW)
  • all VBA.DateTime module functions now throw errors matching VBx (ENGLISH ONLY FOR NOW)

@WaynePhillipsEA
Copy link
Collaborator Author

In v0.13.67:

  • all VBA.Math module functions now throw errors matching VBx (ENGLISH ONLY FOR NOW)

@Greedquest
Copy link

Not sure if this is the same issue as we're mostly talking about Err.Description being set inside VBx functions, but Err.Raise 5 does not give the right description by default:

5: Access is denied. (tB)
instead of
Invalid procedure call or argument (VBA)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working confirmed the issue has been verified
Projects
None yet
Development

No branches or pull requests

10 participants