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

Nothing #106

Closed
ghost opened this issue Mar 29, 2019 · 20 comments
Closed

Nothing #106

ghost opened this issue Mar 29, 2019 · 20 comments
Assignees
Labels

Comments

@ghost
Copy link

ghost commented Mar 29, 2019

Hello,

I am using the VB Script engine and am trying to pass Nothing (Null) to one of the functions in an exposed host object. However it appears as Nothing is undefined?

m_scriptEngine.script.nothing = {[undefined]}

How to resolve this?

Many Thanks
Nick

@ClearScriptLib
Copy link
Collaborator

Hi Nick,

That's correct. ClearScript marshals nothing and empty into Undefined values, whereas VBScript's null shows up as null on the managed side.

If passing null isn't an option for your script code, you could add an overload of your host function that has an Undefined parameter. More details on your scenario could help us suggest other options as well.

Good luck!

@ghost
Copy link
Author

ghost commented Mar 29, 2019

Hi,

Thanks for getting back to me. I've already worked round it, but wanted to check that I wasn't missing something. As you state, VBScript supports 'Nothing'.

Thanks again. :)
Nick

@ClearScriptLib
Copy link
Collaborator

No problem at all! Please reopen this issue if you have more questions on this topic.

@ghost
Copy link
Author

ghost commented Apr 12, 2019

Hi,

I have a Host method that returns nothing in some instances and a COM object in others. I would like to trap for the value returned to check if it is valid. With EnableNullResultWrapping set to false, the VB script throws an error 'Object Required'. With EnableNullResultWrapping set to true, the function succeeds but I am unable to check whether the value is null or not.
e.g.

Set obj = MyHostObject.GetCOMObject()

If IsNull(obj) then
msgbox "Is Null"
Else
msgbox "Is Not Null"
End If

IsNull never seems to return true, even thought obj is nothing.

BTW I have also added a Host object instance.

scriptEngine.AddHostObject("host", HostItemFlags.GlobalMembers, New HostFunctions())

Any help would be appreciated.

Thanks
Nick

@ClearScriptLib
Copy link
Collaborator

ClearScriptLib commented Apr 12, 2019

Hi Nick,

You can make one of two changes to get the desired behavior:

  1. Disable null result wrapping and use obj = instead of set obj = . If the method returns null, you can test for it using VBScript's IsNull function.
  2. Enable null result wrapping and continue using set obj = . If the method returns null, you can test for it using ClearScript's isNull function. Your test above fails because you're still using VBScript's IsNull. Try host.isNull instead.

Good luck!

@ghost
Copy link
Author

ghost commented Apr 12, 2019

Thanks for the reply.
So it is not necessary to use 'Set' in Clear script?
Is it possible to access the host object IsNull method without specifying the Host. prefix?

Thanks :-)

@ClearScriptLib
Copy link
Collaborator

ClearScriptLib commented Apr 13, 2019

So it is not necessary to use 'Set' in Clear script?

It's VBScript that executes script code, not ClearScript.

The Set statement requires an object expression, and while nothing satisfies that requirement, null and empty do not. Non-object expressions (strings, numbers, etc.) must use "normal" assignment (without Set).

Unfortunately things get murkier with .NET in the mix. As marshaled by ClearScript, most .NET objects can be used with both normal and Set assignment, but fundamental values (strings, numbers, etc.) cannot, and neither can null. Therefore, a .NET method that returns an object instance or null (a popular pattern) can be clumsy to consume from VBScript.

To help resolve this we've added things like MarshalNullAsDispatch and EnableNullResultWrapping, but they have their own issues.

Is it possible to access the host object IsNull method without specifying the Host. prefix?

Apparently not, as VBScript doesn't seem to allow hosts to override its built-in IsNull function.

Good luck!

@ghost
Copy link
Author

ghost commented Apr 13, 2019

Thanks for the detailed explanation :-)

@ClearScriptLib
Copy link
Collaborator

The next ClearScript release will allow .NET methods and properties to explicitly return the value nothing to script code. That should make it easier to create VBScript-friendly APIs.

@ghost
Copy link
Author

ghost commented Apr 15, 2019

That's great news. Would it also be possible to support the Nothing keyword in VBScript? At the moment Null appears to be the closest match. When can we expect the next release?

Thanks
Nick

@ClearScriptLib
Copy link
Collaborator

Hi Nick,

VBScript is supported in its entirety today, including the nothing keyword. The issue is what happens when nothing crosses the host-script boundary.

If script code passes nothing to a host method, the host sees it as null. Unfortunately there's no way to change that; it's a limitation of the .NET Framework.

On the other hand, it is possible for the host to pass nothing to script code. Currently it does that by passing null in conjunction with special options such as null result wrapping and null-as-dispatch marshaling.

In ClearScript 5.5.6 you'll be able to use something like return Nothing.Value to pass nothing to script code unconditionally. The script code will then be able to use its native is nothing test.

ClearScript 5.5.6 should be out within several weeks.

Good luck!

@ghost
Copy link
Author

ghost commented Apr 15, 2019

Thanks, I have noticed that passing Null from script to a host method appears to work. Where as Nothing does not...

ClearScriptLib added a commit that referenced this issue May 2, 2019
…ptEngine and V8Runtime; improved support for newer V8 features such as promises and WebAssembly; added Nothing class for better VBScript support (GitHub Issue #106); added readme.txt to NuGet package (GitHub Issue #109); updated API documentation. Tested with V8 7.4.288.26.
@ClearScriptLib
Copy link
Collaborator

Version 5.5.6 includes the Nothing class.

@ghost
Copy link
Author

ghost commented May 2, 2019

Brilliant, that's great news. Thank you :-)

@EtienneLaneville
Copy link

When a VB.NET method returns Nothing, should Is Nothing work now?

Given the following code:

Public Class Being
    Public Sub New(name As String)
        Me.Name = name
    End Sub
    Public Property Name As String = "Being"
End Class

Public Class Creator

    Public Function CreateBeing(name As String) As Being
        If name <> "" Then
            Return New Being(name)
        Else
            Return Nothing
        End If
    End Function

End Class

If I Execute "MsgBox creator.CreateBeing("""") Is Nothing" (using VBScriptEngine), it throws an Object Required exception:

Using host As New Microsoft.ClearScript.Windows.VBScriptEngine

	host.HostWindow = New HostWindow()

	Dim creator As New Creator
	host.AddHostObject("creator", creator)
	host.Execute("MsgBox creator.CreateBeing(""Jimmy"") Is Nothing")
	host.Execute("MsgBox creator.CreateBeing("""") Is Nothing")

End Using

@ClearScriptLib
Copy link
Collaborator

ClearScriptLib commented Jun 15, 2022

Hi @EtienneLaneville,

VB.NET's Nothing is actually equivalent to C#'s default literal, which in this case evaluates to a null reference, which ClearScript converts to VBScript's null by default.

However, you can get the behavior you're looking for by passing WindowsScriptEngineFlags.MarshalNullAsDispatch to the VBScriptEngine constructor.

Good luck!

@EtienneLaneville
Copy link

This saves me a lot work, thanks for your help!

@EtienneLaneville
Copy link

If script code passes nothing to a host method, the host sees it as null. Unfortunately there's no way to change that; it's a limitation of the .NET Framework.

This is still the case with version 7.3.0 correct? I am getting the following exception, which is consistent with your statement:

Invalid property assignment

This is something that is possible with the MSScriptControl though.

@ClearScriptLib
Copy link
Collaborator

ClearScriptLib commented Jun 17, 2022

Hello @EtienneLaneville,

This is still the case with version 7.3.0 correct?

VBScript and .NET behave as before, but some clarification might be helpful. Here's how VBScript's special values are handled as they move from script code to the host application:

VBScript code passes ClearScript receives Host application receives
null DBNull.Value null
nothing or empty null ScriptEngine.UndefinedImportValue

You can change ScriptEngine.UndefinedImportValue to adjust the handling of nothing and empty.

This is something that is possible with the MSScriptControl though.

Please clarify. What doesn't work as you expect with ClearScript?

Thanks!

@EtienneLaneville
Copy link

That table was very helpful. I have set ScriptEngine.UndefinedImportValue to null and things work as expected. Once again, thanks for the great help!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants