Skip to content

Commit 985cde1

Browse files
Fixed host-side and cross-engine assignment of VBScript class object properties (Issue ClearFoundry#104).
1 parent 325a436 commit 985cde1

5 files changed

Lines changed: 131 additions & 9 deletions

File tree

ClearScript/Util/COMDispatch.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,8 @@ [In] [MarshalAs(UnmanagedType.BStr)] string name,
208208
[Out] out int dispid
209209
);
210210

211-
void InvokeEx(
211+
[PreserveSig]
212+
int InvokeEx(
212213
[In] int dispid,
213214
[In] int lcid,
214215
[In] DispatchFlags flags,

ClearScript/Util/COMDispatchHelpers.cs

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ public static object GetProperty(this IDispatchEx dispatchEx, string name, bool
8282
{
8383
EXCEPINFO excepInfo;
8484
var dispArgs = new DISPPARAMS { cArgs = args.Length, rgvarg = argVariantArrayBlock.Addr, cNamedArgs = 0, rgdispidNamedArgs = IntPtr.Zero };
85-
dispatchEx.InvokeEx(dispid, 0, DispatchFlags.PropertyGet, ref dispArgs, resultVariantBlock.Addr, out excepInfo);
85+
Marshal.ThrowExceptionForHR(dispatchEx.InvokeEx(dispid, 0, DispatchFlags.PropertyGet, ref dispArgs, resultVariantBlock.Addr, out excepInfo));
8686
return Marshal.GetObjectForNativeVariant(resultVariantBlock.Addr);
8787
}
8888
}
@@ -110,7 +110,20 @@ public static void SetProperty(this IDispatchEx dispatchEx, string name, bool ig
110110
EXCEPINFO excepInfo;
111111
Marshal.WriteInt32(namedArgDispidBlock.Addr, SpecialDispIDs.PropertyPut);
112112
var dispArgs = new DISPPARAMS { cArgs = args.Length, rgvarg = argVariantArrayBlock.Addr, cNamedArgs = 1, rgdispidNamedArgs = namedArgDispidBlock.Addr };
113-
dispatchEx.InvokeEx(dispid, 0, DispatchFlags.PropertyPut | DispatchFlags.PropertyPutRef, ref dispArgs, IntPtr.Zero, out excepInfo);
113+
114+
result = dispatchEx.InvokeEx(dispid, 0, DispatchFlags.PropertyPut | DispatchFlags.PropertyPutRef, ref dispArgs, IntPtr.Zero, out excepInfo);
115+
if (result == RawCOMHelpers.HResult.DISP_E_MEMBERNOTFOUND)
116+
{
117+
// VBScript objects can be finicky about property-put dispatch flags
118+
119+
result = dispatchEx.InvokeEx(dispid, 0, DispatchFlags.PropertyPut, ref dispArgs, IntPtr.Zero, out excepInfo);
120+
if (result == RawCOMHelpers.HResult.DISP_E_MEMBERNOTFOUND)
121+
{
122+
result = dispatchEx.InvokeEx(dispid, 0, DispatchFlags.PropertyPutRef, ref dispArgs, IntPtr.Zero, out excepInfo);
123+
}
124+
}
125+
126+
Marshal.ThrowExceptionForHR(result);
114127
}
115128
}
116129
}
@@ -144,7 +157,7 @@ public static object Invoke(this IDispatchEx dispatchEx, object[] args, bool asC
144157
{
145158
EXCEPINFO excepInfo;
146159
var dispArgs = new DISPPARAMS { cArgs = args.Length, rgvarg = argVariantArrayBlock.Addr, cNamedArgs = 0, rgdispidNamedArgs = IntPtr.Zero };
147-
dispatchEx.InvokeEx(SpecialDispIDs.Default, 0, asConstructor ? DispatchFlags.Construct : DispatchFlags.Method, ref dispArgs, resultVariantBlock.Addr, out excepInfo);
160+
Marshal.ThrowExceptionForHR(dispatchEx.InvokeEx(SpecialDispIDs.Default, 0, asConstructor ? DispatchFlags.Construct : DispatchFlags.Method, ref dispArgs, resultVariantBlock.Addr, out excepInfo));
148161
return Marshal.GetObjectForNativeVariant(resultVariantBlock.Addr);
149162
}
150163
}
@@ -161,7 +174,7 @@ public static object InvokeMethod(this IDispatchEx dispatchEx, string name, bool
161174
{
162175
EXCEPINFO excepInfo;
163176
var dispArgs = new DISPPARAMS { cArgs = args.Length, rgvarg = argVariantArrayBlock.Addr, cNamedArgs = 0, rgdispidNamedArgs = IntPtr.Zero };
164-
dispatchEx.InvokeEx(dispid, 0, DispatchFlags.Method, ref dispArgs, resultVariantBlock.Addr, out excepInfo);
177+
Marshal.ThrowExceptionForHR(dispatchEx.InvokeEx(dispid, 0, DispatchFlags.Method, ref dispArgs, resultVariantBlock.Addr, out excepInfo));
165178
return Marshal.GetObjectForNativeVariant(resultVariantBlock.Addr);
166179
}
167180
}

ClearScript/V8/V8DebugAgent.cs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -264,10 +264,14 @@ public void SendMessage(string content)
264264

265265
private void RegisterWaitForQueueEvent()
266266
{
267-
var oldQueueWaitHandle = Interlocked.Exchange(ref queueWaitHandle, ThreadPool.RegisterWaitForSingleObject(queueEvent, OnQueueEvent, null, Timeout.Infinite, true));
268-
if (oldQueueWaitHandle != null)
267+
RegisteredWaitHandle newQueueWaitHandle;
268+
if (MiscHelpers.Try(out newQueueWaitHandle, () => ThreadPool.RegisterWaitForSingleObject(queueEvent, OnQueueEvent, null, Timeout.Infinite, true)))
269269
{
270-
oldQueueWaitHandle.Unregister(null);
270+
var oldQueueWaitHandle = Interlocked.Exchange(ref queueWaitHandle, newQueueWaitHandle);
271+
if (oldQueueWaitHandle != null)
272+
{
273+
oldQueueWaitHandle.Unregister(null);
274+
}
271275
}
272276
}
273277

ClearScript/Windows/WindowsScriptItem.cs

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,37 @@ public override void SetProperty(string name, object[] args)
271271
var marshaledArgs = engine.MarshalToScript(args);
272272
try
273273
{
274-
target.InvokeMember(name, BindingFlags.SetProperty, null, target, marshaledArgs, null, CultureInfo.InvariantCulture, null);
274+
try
275+
{
276+
target.InvokeMember(name, BindingFlags.SetProperty, null, target, marshaledArgs, null, CultureInfo.InvariantCulture, null);
277+
}
278+
catch (COMException primaryException)
279+
{
280+
// VBScript objects can be finicky about property-put dispatch flags
281+
282+
if (primaryException.ErrorCode == RawCOMHelpers.HResult.DISP_E_MEMBERNOTFOUND)
283+
{
284+
try
285+
{
286+
target.InvokeMember(name, BindingFlags.SetProperty | BindingFlags.PutDispProperty, null, target, marshaledArgs, null, CultureInfo.InvariantCulture, null);
287+
}
288+
catch (COMException secondaryException)
289+
{
290+
if (secondaryException.ErrorCode == RawCOMHelpers.HResult.DISP_E_MEMBERNOTFOUND)
291+
{
292+
target.InvokeMember(name, BindingFlags.SetProperty | BindingFlags.PutRefDispProperty, null, target, marshaledArgs, null, CultureInfo.InvariantCulture, null);
293+
}
294+
else
295+
{
296+
throw;
297+
}
298+
}
299+
}
300+
else
301+
{
302+
throw;
303+
}
304+
}
275305
}
276306
catch (MissingMemberException)
277307
{

ClearScriptTest/BugFixTest.cs

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1827,6 +1827,80 @@ public void BugFix_V8NativePropertyHiding_Method()
18271827
Assert.AreEqual(foo.toString(), engine.Evaluate("foo.toString()"));
18281828
}
18291829

1830+
[TestMethod, TestCategory("BugFix")]
1831+
public void BugFix_VBScript_PropertyPut()
1832+
{
1833+
using (var vbEngine = new VBScriptEngine())
1834+
{
1835+
vbEngine.Execute(@"
1836+
class Test
1837+
private myFoo
1838+
public property get foo
1839+
foo = myFoo
1840+
end property
1841+
public property let foo(value)
1842+
myFoo = value
1843+
end property
1844+
end class
1845+
set myTest = new Test
1846+
myTest.foo = 123
1847+
");
1848+
1849+
Assert.AreEqual(123, Convert.ToInt32(vbEngine.Script.myTest.foo));
1850+
1851+
vbEngine.Script.myTest.foo = 456;
1852+
Assert.AreEqual(456, Convert.ToInt32(vbEngine.Script.myTest.foo));
1853+
1854+
vbEngine.Script.myTest.foo = "blah";
1855+
Assert.AreEqual("blah", vbEngine.Script.myTest.foo);
1856+
1857+
vbEngine.Script.myTest.foo = new DateTime(2007, 5, 22);
1858+
Assert.AreEqual(new DateTime(2007, 5, 22), vbEngine.Script.myTest.foo);
1859+
}
1860+
}
1861+
1862+
[TestMethod, TestCategory("BugFix")]
1863+
public void BugFix_VBScript_PropertyPut_CrossEngine()
1864+
{
1865+
using (var vbEngine = new VBScriptEngine())
1866+
{
1867+
vbEngine.Execute(@"
1868+
class Test
1869+
private myFoo
1870+
public property get foo
1871+
foo = myFoo
1872+
end property
1873+
public property let foo(value)
1874+
myFoo = value
1875+
end property
1876+
end class
1877+
set myTest = new Test
1878+
myTest.foo = 123
1879+
");
1880+
1881+
engine.Script.test = vbEngine.Script.myTest;
1882+
Assert.AreEqual(123, Convert.ToInt32(engine.Evaluate("test.foo")));
1883+
1884+
engine.Execute("test.foo = 456");
1885+
Assert.AreEqual(456, Convert.ToInt32(engine.Evaluate("test.foo")));
1886+
1887+
engine.Execute("test.foo = \"blah\"");
1888+
Assert.AreEqual("blah", engine.Evaluate("test.foo"));
1889+
1890+
engine.AddHostObject("bar", new DateTime(2007, 5, 22));
1891+
engine.Execute("test.foo = bar");
1892+
Assert.AreEqual(new DateTime(2007, 5, 22), engine.Evaluate("test.foo"));
1893+
}
1894+
}
1895+
1896+
[TestMethod, TestCategory("BugFix")]
1897+
public void BugFix_VBScript_PropertyPut_CrossEngine_VBScript()
1898+
{
1899+
engine.Dispose();
1900+
engine = new VBScriptEngine();
1901+
BugFix_VBScript_PropertyPut_CrossEngine();
1902+
}
1903+
18301904
// ReSharper restore InconsistentNaming
18311905

18321906
#endregion

0 commit comments

Comments
 (0)