Skip to content

Commit fbd59e0

Browse files
Version 5.5.5: Enhanced ScriptObject to simplify script object access without "dynamic"; added IWindowsScriptObject (GitHub Issue microsoft#97); improved property accessor scriptability (GitHub Issue microsoft#88); updated API documentation. Tested with V8 7.2.502.25.
1 parent 33036db commit fbd59e0

File tree

588 files changed

+2095
-1283
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

588 files changed

+2095
-1283
lines changed

ClearScript.NoV8.sln.DotSettings

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpKeepExistingMigration/@EntryIndexedValue">True</s:Boolean>
4848
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpPlaceEmbeddedOnSameLineMigration/@EntryIndexedValue">True</s:Boolean>
4949
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpRenamePlacementToArrangementMigration/@EntryIndexedValue">True</s:Boolean>
50+
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpUseContinuousIndentInsideBracesMigration/@EntryIndexedValue">True</s:Boolean>
5051
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EAddAccessorOwnerDeclarationBracesMigration/@EntryIndexedValue">True</s:Boolean>
5152
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002ECSharpPlaceAttributeOnSameLineMigration/@EntryIndexedValue">True</s:Boolean>
5253
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateBlankLinesAroundFieldToBlankLinesAroundProperty/@EntryIndexedValue">True</s:Boolean>

ClearScript.sln.DotSettings

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpKeepExistingMigration/@EntryIndexedValue">True</s:Boolean>
4848
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpPlaceEmbeddedOnSameLineMigration/@EntryIndexedValue">True</s:Boolean>
4949
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpRenamePlacementToArrangementMigration/@EntryIndexedValue">True</s:Boolean>
50+
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpUseContinuousIndentInsideBracesMigration/@EntryIndexedValue">True</s:Boolean>
5051
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EAddAccessorOwnerDeclarationBracesMigration/@EntryIndexedValue">True</s:Boolean>
5152
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002ECSharpPlaceAttributeOnSameLineMigration/@EntryIndexedValue">True</s:Boolean>
5253
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateBlankLinesAroundFieldToBlankLinesAroundProperty/@EntryIndexedValue">True</s:Boolean>

ClearScript/ClearScript.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@
141141
<Compile Include="V8\V8RuntimeFlags.cs" />
142142
<Compile Include="V8\V8TestProxy.cs" />
143143
<Compile Include="Windows\IHostWindow.cs" />
144+
<Compile Include="Windows\IWindowsScriptObject.cs" />
144145
<Compile Include="Windows\WindowsScriptEngineFlags.cs" />
145146
<Compile Include="Util\IDynamic.cs" />
146147
<Compile Include="Util\SpecialMemberNames.cs" />

ClearScript/Exports/VersionSymbols.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,5 @@
55

66
#pragma once
77

8-
#define CLEARSCRIPT_VERSION_STRING "5.5.4.0"
9-
#define CLEARSCRIPT_VERSION_COMMA_SEPARATED 5,5,4,0
8+
#define CLEARSCRIPT_VERSION_STRING "5.5.5.0"
9+
#define CLEARSCRIPT_VERSION_COMMA_SEPARATED 5,5,5,0

ClearScript/HostItem.cs

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -968,7 +968,7 @@ private object InvokeDynamicMember(string name, BindingFlags invokeFlags, object
968968
{
969969
if (name == SpecialMemberNames.Default)
970970
{
971-
return TargetDynamic.Invoke(args, true);
971+
return TargetDynamic.Invoke(true, args);
972972
}
973973

974974
throw new InvalidOperationException("Invalid constructor invocation");
@@ -980,7 +980,7 @@ private object InvokeDynamicMember(string name, BindingFlags invokeFlags, object
980980
{
981981
try
982982
{
983-
return TargetDynamic.Invoke(args, false);
983+
return TargetDynamic.Invoke(false, args);
984984
}
985985
catch (Exception)
986986
{
@@ -1302,7 +1302,7 @@ private object InvokeHostMember(string name, BindingFlags invokeFlags, object[]
13021302
var enumerableHelpersHostItem = Wrap(engine, EnumerableHelpers.HostType, HostItemFlags.PrivateAccess);
13031303
try
13041304
{
1305-
return ((IDynamic)enumerableHelpersHostItem).InvokeMethod("GetEnumerator", new object[] { this });
1305+
return ((IDynamic)enumerableHelpersHostItem).InvokeMethod("GetEnumerator", this);
13061306
}
13071307
catch (MissingMemberException)
13081308
{
@@ -1542,7 +1542,7 @@ private object GetHostProperty(PropertyInfo property, BindingFlags invokeFlags,
15421542
}
15431543

15441544
var getMethod = property.GetMethod;
1545-
if ((getMethod == null) || !getMethod.IsAccessible(accessContext) || getMethod.IsBlockedFromScript(defaultAccess))
1545+
if ((getMethod == null) || !getMethod.IsAccessible(accessContext) || getMethod.IsBlockedFromScript(defaultAccess, false))
15461546
{
15471547
throw new UnauthorizedAccessException("Property get method is unavailable or inaccessible");
15481548
}
@@ -1655,7 +1655,7 @@ private object SetHostProperty(PropertyInfo property, BindingFlags invokeFlags,
16551655
}
16561656

16571657
var setMethod = property.SetMethod;
1658-
if ((setMethod == null) || !setMethod.IsAccessible(accessContext) || setMethod.IsBlockedFromScript(defaultAccess))
1658+
if ((setMethod == null) || !setMethod.IsAccessible(accessContext) || setMethod.IsBlockedFromScript(defaultAccess, false))
16591659
{
16601660
throw new UnauthorizedAccessException("Property set method is unavailable or inaccessible");
16611661
}
@@ -1697,7 +1697,7 @@ public override string ToString()
16971697

16981698
public override bool TryCreateInstance(CreateInstanceBinder binder, object[] args, out object result)
16991699
{
1700-
result = ThisDynamic.Invoke(args, true).ToDynamicResult(engine);
1700+
result = ThisDynamic.Invoke(true, args).ToDynamicResult(engine);
17011701
return true;
17021702
}
17031703

@@ -1709,7 +1709,7 @@ public override bool TryGetMember(GetMemberBinder binder, out object result)
17091709

17101710
public override bool TrySetMember(SetMemberBinder binder, object value)
17111711
{
1712-
ThisDynamic.SetProperty(binder.Name, new[] { value });
1712+
ThisDynamic.SetProperty(binder.Name, value);
17131713
return true;
17141714
}
17151715

@@ -1730,7 +1730,7 @@ public override bool TryGetIndex(GetIndexBinder binder, object[] indices, out ob
17301730

17311731
if (indices.Length > 1)
17321732
{
1733-
result = ThisDynamic.GetProperty(SpecialMemberNames.Default, indices);
1733+
result = ThisDynamic.GetProperty(SpecialMemberNames.Default, indices).ToDynamicResult(engine);
17341734
return true;
17351735
}
17361736

@@ -1748,7 +1748,7 @@ public override bool TrySetIndex(SetIndexBinder binder, object[] indices, object
17481748
return true;
17491749
}
17501750

1751-
ThisDynamic.SetProperty(indices[0].ToString(), new[] { value });
1751+
ThisDynamic.SetProperty(indices[0].ToString(), value);
17521752
return true;
17531753
}
17541754

@@ -1762,7 +1762,7 @@ public override bool TrySetIndex(SetIndexBinder binder, object[] indices, object
17621762

17631763
public override bool TryInvoke(InvokeBinder binder, object[] args, out object result)
17641764
{
1765-
result = ThisDynamic.Invoke(args, false).ToDynamicResult(engine);
1765+
result = ThisDynamic.Invoke(false, args).ToDynamicResult(engine);
17661766
return true;
17671767
}
17681768

@@ -1930,12 +1930,12 @@ Type IReflect.UnderlyingSystemType
19301930

19311931
#region IDynamic implementation
19321932

1933-
object IDynamic.GetProperty(string name, object[] args)
1933+
object IDynamic.GetProperty(string name, params object[] args)
19341934
{
19351935
return InvokeReflectMember(name, BindingFlags.GetProperty, args, CultureInfo.InvariantCulture, null);
19361936
}
19371937

1938-
object IDynamic.GetProperty(string name, object[] args, out bool isCacheable)
1938+
object IDynamic.GetProperty(string name, out bool isCacheable, params object[] args)
19391939
{
19401940
return InvokeReflectMember(name, BindingFlags.GetProperty, args, CultureInfo.InvariantCulture, null, out isCacheable);
19411941
}
@@ -2011,7 +2011,7 @@ object IDynamic.GetProperty(int index)
20112011

20122012
void IDynamic.SetProperty(int index, object value)
20132013
{
2014-
ThisDynamic.SetProperty(index.ToString(CultureInfo.InvariantCulture), new[] { value });
2014+
ThisDynamic.SetProperty(index.ToString(CultureInfo.InvariantCulture), value);
20152015
}
20162016

20172017
bool IDynamic.DeleteProperty(int index)
@@ -2064,12 +2064,12 @@ int[] IDynamic.GetPropertyIndices()
20642064
});
20652065
}
20662066

2067-
object IDynamic.Invoke(object[] args, bool asConstructor)
2067+
object IDynamic.Invoke(bool asConstructor, params object[] args)
20682068
{
20692069
return ThisReflect.InvokeMember(SpecialMemberNames.Default, asConstructor ? BindingFlags.CreateInstance : ((args.Length < 1) ? BindingFlags.InvokeMethod : BindingFlags.InvokeMethod | BindingFlags.GetProperty), null, ThisReflect, args, null, CultureInfo.InvariantCulture, null);
20702070
}
20712071

2072-
object IDynamic.InvokeMethod(string name, object[] args)
2072+
object IDynamic.InvokeMethod(string name, params object[] args)
20732073
{
20742074
return ThisReflect.InvokeMember(name, BindingFlags.InvokeMethod, null, ThisReflect, args, null, CultureInfo.InvariantCulture, null);
20752075
}

ClearScript/Properties/AssemblyInfo.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,13 @@
1717
[assembly: InternalsVisibleTo("ClearScriptTest")]
1818

1919
[assembly: ComVisible(false)]
20-
[assembly: AssemblyVersion("5.5.4.0")]
21-
[assembly: AssemblyFileVersion("5.5.4.0")]
20+
[assembly: AssemblyVersion("5.5.5.0")]
21+
[assembly: AssemblyFileVersion("5.5.5.0")]
2222

2323
namespace Microsoft.ClearScript.Properties
2424
{
2525
internal static class ClearScriptVersion
2626
{
27-
public const string Value = "5.5.4.0";
27+
public const string Value = "5.5.5.0";
2828
}
2929
}

ClearScript/PropertyBag.cs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -161,16 +161,20 @@ private void NotifyExposedToScriptCode(object value)
161161

162162
#endregion
163163

164-
#region IEnumerable<KeyValuePair<string, object>> implementation
164+
#region IEnumerable implementation
165165

166166
[SuppressMessage("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes", Justification = "This member requires explicit implementation to resolve ambiguity.")]
167-
IEnumerator<KeyValuePair<string, object>> IEnumerable<KeyValuePair<string, object>>.GetEnumerator()
167+
IEnumerator IEnumerable.GetEnumerator()
168168
{
169169
return dictionary.GetEnumerator();
170170
}
171171

172+
#endregion
173+
174+
#region IEnumerable<KeyValuePair<string, object>> implementation
175+
172176
[SuppressMessage("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes", Justification = "This member requires explicit implementation to resolve ambiguity.")]
173-
IEnumerator IEnumerable.GetEnumerator()
177+
IEnumerator<KeyValuePair<string, object>> IEnumerable<KeyValuePair<string, object>>.GetEnumerator()
174178
{
175179
return dictionary.GetEnumerator();
176180
}

ClearScript/ScriptItem.cs

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,32 @@ private DynamicMetaObject PostProcessBindResult(DynamicMetaObject result)
143143
return new DynamicMetaObject(Expression.TryCatchFinally(result.Expression, Expression.Call(clearLastScriptErrorMethod), Expression.Catch(typeof(Exception), catchBody)), result.Restrictions);
144144
}
145145

146+
#region ScriptObject overrides
147+
148+
public override IEnumerable<string> PropertyNames
149+
{
150+
get { return GetPropertyNames(); }
151+
}
152+
153+
public override IEnumerable<int> PropertyIndices
154+
{
155+
get { return GetPropertyIndices(); }
156+
}
157+
158+
public new object this[string name, params object[] args]
159+
{
160+
get { return GetProperty(name, args).ToDynamicResult(Engine); }
161+
set { SetProperty(name, args.Concat(new[] { value }).ToArray()); }
162+
}
163+
164+
public new object this[int index]
165+
{
166+
get { return GetProperty(index).ToDynamicResult(Engine); }
167+
set { SetProperty(index, value); }
168+
}
169+
170+
#endregion
171+
146172
#region DynamicObject overrides
147173

148174
public override DynamicMetaObject GetMetaObject(Expression param)
@@ -263,7 +289,7 @@ public object InvokeMember(string name, BindingFlags invokeFlags, Binder binder,
263289
{
264290
if (name == SpecialMemberNames.Default)
265291
{
266-
return Invoke(args, false);
292+
return Invoke(false, args);
267293
}
268294

269295
return InvokeMethod(name, args);
@@ -336,7 +362,7 @@ public void RemoveMember(MemberInfo member)
336362

337363
#region IDynamic implementation
338364

339-
public object GetProperty(string name, object[] args, out bool isCacheable)
365+
public object GetProperty(string name, out bool isCacheable, params object[] args)
340366
{
341367
isCacheable = false;
342368
return GetProperty(name, args);
@@ -346,16 +372,8 @@ public object GetProperty(string name, object[] args, out bool isCacheable)
346372

347373
#region IDynamic implementation (abstract)
348374

349-
public abstract object GetProperty(string name, object[] args);
350-
public abstract void SetProperty(string name, object[] args);
351-
public abstract bool DeleteProperty(string name);
352375
public abstract string[] GetPropertyNames();
353-
public abstract object GetProperty(int index);
354-
public abstract void SetProperty(int index, object value);
355-
public abstract bool DeleteProperty(int index);
356376
public abstract int[] GetPropertyIndices();
357-
public abstract object Invoke(object[] args, bool asConstructor);
358-
public abstract object InvokeMethod(string name, object[] args);
359377

360378
#endregion
361379

ClearScript/ScriptObject.cs

Lines changed: 99 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,12 @@
1-
using System.Dynamic;
1+
using System.Collections.Generic;
2+
using System.Dynamic;
3+
using System.Linq;
24

35
namespace Microsoft.ClearScript
46
{
57
/// <summary>
68
/// Represents a script object.
79
/// </summary>
8-
/// <remarks>
9-
/// Use this class in conjunction with C#'s
10-
/// <c><see href="https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/is">is</see></c>
11-
/// operator to identify script objects.
12-
/// </remarks>
1310
/// <seealso cref="ScriptEngine.Evaluate(string, bool, string)"/>
1411
public abstract class ScriptObject : DynamicObject
1512
{
@@ -21,5 +18,101 @@ internal ScriptObject()
2118
/// Gets the script engine that owns the object.
2219
/// </summary>
2320
public abstract ScriptEngine Engine { get; }
21+
22+
/// <summary>
23+
/// Gets the value of a named script object property.
24+
/// </summary>
25+
/// <param name="name">The name of the property to get.</param>
26+
/// <param name="args">Optional arguments for property retrieval.</param>
27+
/// <returns>The value of the specified property.</returns>
28+
public abstract object GetProperty(string name, params object[] args);
29+
30+
/// <summary>
31+
/// Sets the value of a named script object property.
32+
/// </summary>
33+
/// <param name="name">The name of the property to set.</param>
34+
/// <param name="args">An array containing optional arguments and the new property value.</param>
35+
/// <remarks>
36+
/// The <paramref name="args"></paramref> array must contain at least one element. The new
37+
/// property value must be the last element of the array.
38+
/// </remarks>
39+
public abstract void SetProperty(string name, params object[] args);
40+
41+
/// <summary>
42+
/// Removes a named script object property.
43+
/// </summary>
44+
/// <param name="name">The name of the property to remove.</param>
45+
/// <returns><c>True</c> if the property was removed successfully, <c>false</c> otherwise.</returns>
46+
public abstract bool DeleteProperty(string name);
47+
48+
/// <summary>
49+
/// Enumerates the script object's property names.
50+
/// </summary>
51+
public abstract IEnumerable<string> PropertyNames { get; }
52+
53+
/// <summary>
54+
/// Gets or sets the value of a named script object property.
55+
/// </summary>
56+
/// <param name="name">The name of the property to get or set.</param>
57+
/// <param name="args">Optional arguments for property access.</param>
58+
/// <returns>The value of the specified property.</returns>
59+
public object this[string name, params object[] args]
60+
{
61+
get { return GetProperty(name, args); }
62+
set { SetProperty(name, args.Concat(new[] { value }).ToArray()); }
63+
}
64+
65+
/// <summary>
66+
/// Gets the value of an indexed script object property.
67+
/// </summary>
68+
/// <param name="index">The index of the property to get.</param>
69+
/// <returns>The value of the specified property.</returns>
70+
public abstract object GetProperty(int index);
71+
72+
/// <summary>
73+
/// Sets the value of an indexed script object property.
74+
/// </summary>
75+
/// <param name="index">The index of the property to set.</param>
76+
/// <param name="value">The new property value.</param>
77+
public abstract void SetProperty(int index, object value);
78+
79+
/// <summary>
80+
/// Removes an indexed script object property.
81+
/// </summary>
82+
/// <param name="index">The index of the property to remove.</param>
83+
/// <returns><c>True</c> if the property was removed successfully, <c>false</c> otherwise.</returns>
84+
public abstract bool DeleteProperty(int index);
85+
86+
/// <summary>
87+
/// Enumerates the script object's property indices.
88+
/// </summary>
89+
public abstract IEnumerable<int> PropertyIndices { get; }
90+
91+
/// <summary>
92+
/// Gets or sets the value of an indexed script object property.
93+
/// </summary>
94+
/// <param name="index">The index of the property to get or set.</param>
95+
/// <returns>The value of the specified property.</returns>
96+
public object this[int index]
97+
{
98+
get { return GetProperty(index); }
99+
set { SetProperty(index, value); }
100+
}
101+
102+
/// <summary>
103+
/// Invokes the script object.
104+
/// </summary>
105+
/// <param name="asConstructor"><c>True</c> to invoke the object as a constructor, <c>false</c> otherwise.</param>
106+
/// <param name="args">Optional arguments for object invocation.</param>
107+
/// <returns>The invocation result value.</returns>
108+
public abstract object Invoke(bool asConstructor, params object[] args);
109+
110+
/// <summary>
111+
/// Invokes a script object method.
112+
/// </summary>
113+
/// <param name="name">The name of the method to invoke.</param>
114+
/// <param name="args">Optional arguments for method invocation.</param>
115+
/// <returns>The invocation result value.</returns>
116+
public abstract object InvokeMethod(string name, params object[] args);
24117
}
25118
}

0 commit comments

Comments
 (0)