Skip to content

Commit b9aad87

Browse files
authored
Fix #3119. Don't expose ListValue<T> lists to users (#3129)
* Fix #3119. Don't expose ListValue<T> lists to users Use Collections.Generic.List<T> instead of ListValue<T>. Return a ListValue copy of these lists to user code. Changes: FileContent:binary Lexicon:keys Lexicon:values Part:children Stage:resources Stage:resourceslex String:split Structure:suffixnames Timewarp:ratelist Timewarp:railsratelist Timewarp:physicsratelist Vessel:parts Vessel:dockingports Vessel:decouplers (separators) Vessel:resources allnodes bound variable allwaypoints function Stage:resources, Stage:resourceslex, Vessel:parts, Vessel:dockingports, Vessel:decouplers now return copies instead of references to internal lists. All lists returned by these suffixes don't get modified over time so the only way to tell that they are copies now is to use the equality operator. Stage:resources and Stage:resourceslex returning a reference was a bug. * Optimize by not creating list copies where possible. Revert Vessel parts, dockingports, decouplers suffixes to return readonly references to internal lists
1 parent 2609a7a commit b9aad87

File tree

15 files changed

+62
-82
lines changed

15 files changed

+62
-82
lines changed

src/kOS.Safe/Encapsulation/Lexicon.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -115,10 +115,10 @@ private void FillWithEnumerableValues(IEnumerable<Structure> values)
115115
private void InitalizeSuffixes()
116116
{
117117
AddSuffix("CLEAR", new NoArgsVoidSuffix(Clear, "Removes all items from Lexicon"));
118-
AddSuffix("KEYS", new Suffix<ListValue<Structure>>(GetKeys, "Returns the lexicon keys"));
118+
AddSuffix("KEYS", new Suffix<ListValue>(GetKeys, "Returns the lexicon keys"));
119119
AddSuffix("HASKEY", new OneArgsSuffix<BooleanValue, Structure>(HasKey, "Returns true if a key is in the Lexicon"));
120120
AddSuffix("HASVALUE", new OneArgsSuffix<BooleanValue, Structure>(HasValue, "Returns true if value is in the Lexicon"));
121-
AddSuffix("VALUES", new Suffix<ListValue<Structure>>(GetValues, "Returns the lexicon values"));
121+
AddSuffix("VALUES", new Suffix<ListValue>(GetValues, "Returns the lexicon values"));
122122
AddSuffix("COPY", new NoArgsSuffix<Lexicon>(() => new Lexicon(this), "Returns a copy of Lexicon"));
123123
AddSuffix("LENGTH", new NoArgsSuffix<ScalarValue>(() => internalDictionary.Count, "Returns the number of elements in the collection"));
124124
AddSuffix("REMOVE", new OneArgsSuffix<BooleanValue, Structure>(one => Remove(one), "Removes the value at the given key"));
@@ -158,12 +158,12 @@ private BooleanValue HasKey(Structure key)
158158
return internalDictionary.ContainsKey(key);
159159
}
160160

161-
public ListValue<Structure> GetValues()
161+
public ListValue GetValues()
162162
{
163163
return ListValue.CreateList(Values);
164164
}
165165

166-
public ListValue<Structure> GetKeys()
166+
public ListValue GetKeys()
167167
{
168168
return ListValue.CreateList(Keys);
169169
}
@@ -380,9 +380,9 @@ public override BooleanValue HasSuffix(StringValue suffixName)
380380
/// to the list.
381381
/// </summary>
382382
/// <returns></returns>
383-
public override ListValue<StringValue> GetSuffixNames()
383+
public override ListValue GetSuffixNames()
384384
{
385-
ListValue<StringValue> theList = base.GetSuffixNames();
385+
ListValue theList = base.GetSuffixNames();
386386

387387
foreach (Structure key in internalDictionary.Keys)
388388
{
@@ -392,7 +392,7 @@ public override ListValue<StringValue> GetSuffixNames()
392392
theList.Add(keyStr);
393393
}
394394
}
395-
return new ListValue<StringValue>(theList.OrderBy(item => item.ToString()));
395+
return new ListValue(theList.OrderBy(item => item.ToString()));
396396
}
397397
public override Dump Dump()
398398
{

src/kOS.Safe/Encapsulation/StringValue.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -239,10 +239,10 @@ System.Collections.IEnumerator IEnumerable.GetEnumerator()
239239
}
240240

241241
// As the regular Split, except returning a ListValue rather than an array.
242-
public ListValue<StringValue> SplitToList(string separator)
242+
public ListValue SplitToList(string separator)
243243
{
244244
string[] split = Regex.Split(internalString, Regex.Escape(separator), RegexOptions.IgnoreCase);
245-
ListValue<StringValue> returnList = new ListValue<StringValue>();
245+
ListValue returnList = new ListValue();
246246
foreach (string s in split)
247247
returnList.Add(new StringValue(s));
248248
return returnList;
@@ -273,7 +273,7 @@ private void StringInitializeSuffixes()
273273
AddSuffix("PADRIGHT", new OneArgsSuffix<StringValue, ScalarValue>( one => PadRight(one)));
274274
AddSuffix("REMOVE", new TwoArgsSuffix<StringValue, ScalarValue, ScalarValue>( (one, two) => Remove(one, two)));
275275
AddSuffix("REPLACE", new TwoArgsSuffix<StringValue, StringValue, StringValue>( (one, two) => Replace(one, two)));
276-
AddSuffix("SPLIT", new OneArgsSuffix<ListValue<StringValue>, StringValue>( one => SplitToList(one)));
276+
AddSuffix("SPLIT", new OneArgsSuffix<ListValue, StringValue>( one => SplitToList(one)));
277277
AddSuffix("STARTSWITH", new OneArgsSuffix<BooleanValue, StringValue>( one => StartsWith(one)));
278278
AddSuffix("TOLOWER", new NoArgsSuffix<StringValue>(() => ToLower()));
279279
AddSuffix("TOUPPER", new NoArgsSuffix<StringValue>(() => ToUpper()));

src/kOS.Safe/Encapsulation/Structure.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ private void InitializeInstanceSuffixes()
6363

6464
AddSuffix("TOSTRING", new NoArgsSuffix<StringValue>(() => ToString()));
6565
AddSuffix("HASSUFFIX", new OneArgsSuffix<BooleanValue, StringValue>(HasSuffix));
66-
AddSuffix("SUFFIXNAMES", new NoArgsSuffix<ListValue<StringValue>>(GetSuffixNames));
66+
AddSuffix("SUFFIXNAMES", new NoArgsSuffix<ListValue>(GetSuffixNames));
6767
AddSuffix("ISSERIALIZABLE", new NoArgsSuffix<BooleanValue>(() => this is SerializableStructure));
6868
AddSuffix("TYPENAME", new NoArgsSuffix<StringValue>(() => new StringValue(KOSName)));
6969
AddSuffix("ISTYPE", new OneArgsSuffix<BooleanValue,StringValue>(GetKOSIsType));
@@ -208,17 +208,17 @@ public virtual BooleanValue HasSuffix(StringValue suffixName)
208208
return false;
209209
}
210210

211-
public virtual ListValue<StringValue> GetSuffixNames()
211+
public virtual ListValue GetSuffixNames()
212212
{
213213
callInitializeSuffixes();
214-
List<StringValue> names = new List<StringValue>();
215-
216-
names.AddRange(instanceSuffixes.Keys.Select(item => (StringValue)item));
217-
names.AddRange(GetStaticSuffixesForType(GetType()).Keys.Select(item => (StringValue)item));
214+
List<StringValue> names = new List<StringValue>();
215+
216+
foreach (var suffix in instanceSuffixes.Keys) names.Add(suffix);
217+
foreach (var staticSuffix in GetStaticSuffixesForType(GetType()).Keys) names.Add(staticSuffix);
218218

219219
// Return the list alphabetized by suffix name. The key lookups above, since they're coming
220220
// from a hashed dictionary, won't be in any predictable ordering:
221-
return new ListValue<StringValue>(names.OrderBy(item => item.ToString()));
221+
return new ListValue(names.OrderBy(item => item.ToString()));
222222
}
223223

224224
public virtual BooleanValue GetKOSIsType(StringValue queryTypeName)

src/kOS.Safe/Persistence/FileContent.cs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -61,15 +61,10 @@ private void InitializeSuffixes()
6161
AddSuffix("EMPTY", new Suffix<BooleanValue>(() => Size == 0));
6262
AddSuffix("TYPE", new Suffix<StringValue>(() => Category.ToString()));
6363
AddSuffix("STRING", new Suffix<StringValue>(() => String));
64-
AddSuffix("BINARY", new Suffix<ListValue<ScalarIntValue>>(() => ContentAsIntList()));
64+
AddSuffix("BINARY", new Suffix<ListValue>(() => new ListValue(Bytes.Select(x => new ScalarIntValue(x)))));
6565
AddSuffix("ITERATOR", new Suffix<Enumerator>(() => new Enumerator(GetEnumerator())));
6666
}
6767

68-
private ListValue<ScalarIntValue> ContentAsIntList()
69-
{
70-
return new ListValue<ScalarIntValue>(Bytes.Select(x => new ScalarIntValue(x)));
71-
}
72-
7368
public override Dump Dump()
7469
{
7570
return new Dump { { DumpContent, PersistenceUtilities.EncodeBase64(Bytes) } };

src/kOS/Binding/FlightStats.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using System.Collections.Generic;
12
using kOS.Module;
23
using kOS.Control;
34
using kOS.Safe.Binding;
@@ -59,12 +60,12 @@ public override void AddTo(SharedObjects shared)
5960
shared.BindingMgr.AddGetter("ALLNODES", () => GetAllNodes(shared));
6061
}
6162

62-
public ListValue<Node> GetAllNodes(SharedObjects shared)
63+
public ListValue GetAllNodes(SharedObjects shared)
6364
{
6465
var vessel = shared.Vessel;
6566
if (vessel.patchedConicSolver == null || vessel.patchedConicSolver.maneuverNodes.Count == 0)
66-
return new ListValue<Node>();
67-
var ret = new ListValue<Node>(vessel.patchedConicSolver.maneuverNodes.Select(e => Node.FromExisting(vessel, e, shared)));
67+
return new ListValue();
68+
var ret = new ListValue(vessel.patchedConicSolver.maneuverNodes.Select(e => Node.FromExisting(vessel, e, shared)));
6869
return ret;
6970
}
7071
}

src/kOS/Function/Suffixed.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -732,7 +732,7 @@ public override void Execute(SharedObjects shared)
732732
AssertArgBottomAndConsume(shared); // no args
733733

734734
// ReSharper disable SuggestUseVarKeywordEvident
735-
ListValue<WaypointValue> returnList = new ListValue<WaypointValue>();
735+
ListValue returnList = new ListValue();
736736
// ReSharper enable SuggestUseVarKeywordEvident
737737

738738
WaypointManager wpm = WaypointManager.Instance();

src/kOS/Suffixed/AggregateResourceValue.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,10 +99,10 @@ public static ListValue PartsToList(IEnumerable<global::Part> parts, SharedObjec
9999
return list;
100100
}
101101

102-
public static ListValue<AggregateResourceValue> FromVessel(Vessel vessel, SharedObjects shared)
102+
public static ListValue FromVessel(Vessel vessel, SharedObjects shared)
103103
{
104104
var resources = ProspectResources(vessel.parts, shared);
105-
return ListValue<AggregateResourceValue>.CreateList(resources.Values);
105+
return new ListValue(resources.Values);
106106
}
107107
}
108108
}

src/kOS/Suffixed/Part/DockingPortValue.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ public PartValue GetPartner()
6262
}
6363

6464
var otherVessel = VesselTarget.CreateOrGetExisting(otherNode.vessel, Shared);
65-
foreach (var part in otherVessel.Parts)
65+
foreach (PartValue part in otherVessel.Parts)
6666
{
6767
if (part.Part == otherNode.part)
6868
{

src/kOS/Suffixed/Part/PartValue.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ public class PartValue : Structure, IKOSTargetable
2222
public global::Part Part { get; private set; }
2323
public PartValue Parent { get; private set; }
2424
public DecouplerValue Decoupler { get; private set; }
25-
public ListValue<PartValue> Children { get; private set; }
25+
public ListValue Children { get; private set; }
2626
public Structure ParentValue { get { return (Structure)Parent ?? StringValue.None; } }
2727
public Structure DecouplerValue { get { return (Structure)Decoupler ?? StringValue.None; } }
2828
public int DecoupledIn { get { return (Decoupler != null) ? Decoupler.Part.inverseStage : -1; } }
@@ -37,7 +37,7 @@ internal PartValue(SharedObjects shared, global::Part part, PartValue parent, De
3737
Parent = parent;
3838
Decoupler = decoupler;
3939
RegisterInitializer(PartInitializeSuffixes);
40-
Children = new ListValue<PartValue>();
40+
Children = new ListValue();
4141
}
4242

4343
private void PartInitializeSuffixes()
@@ -66,7 +66,7 @@ private void PartInitializeSuffixes()
6666
AddSuffix(new[] { "DECOUPLER", "SEPARATOR" }, new Suffix<Structure>(() => DecouplerValue, "The part that will decouple/separate this part when activated"));
6767
AddSuffix(new[] { "DECOUPLEDIN", "SEPARATEDIN" }, new Suffix<ScalarValue>(() => DecoupledIn));
6868
AddSuffix("HASPARENT", new Suffix<BooleanValue>(() => Part.parent != null, "Tells you if this part has a parent, is used to avoid null exception from PARENT"));
69-
AddSuffix("CHILDREN", new Suffix<ListValue<PartValue>>(() => PartValueFactory.ConstructGeneric(Part.children, Shared), "A LIST() of the children parts of this part"));
69+
AddSuffix("CHILDREN", new Suffix<ListValue>(() => PartValueFactory.ConstructGeneric(Part.children, Shared), "A LIST() of the children parts of this part"));
7070
AddSuffix("DRYMASS", new Suffix<ScalarValue>(() => Part.GetDryMass(), "The Part's mass when empty"));
7171
AddSuffix("MASS", new Suffix<ScalarValue>(() => Part.CalculateCurrentMass(), "The Part's current mass"));
7272
AddSuffix("WETMASS", new Suffix<ScalarValue>(() => Part.GetWetMass(), "The Part's mass when full"));

src/kOS/Suffixed/Part/PartValueFactory.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ public static ListValue Construct(IEnumerable<global::Part> parts, SharedObjects
1212
return ListValue.CreateList(parts.Select(part => Construct(part, shared)).Where(p => p != null));
1313
}
1414

15-
public static ListValue<PartValue> ConstructGeneric(IEnumerable<global::Part> parts, SharedObjects shared) {
16-
return ListValue<PartValue>.CreateList(parts.Select(part => Construct(part, shared)).Where(p => p != null));
15+
public static ListValue ConstructGeneric(IEnumerable<global::Part> parts, SharedObjects shared) {
16+
return new ListValue(parts.Select(part => Construct(part, shared)).Where(p => p != null));
1717
}
1818

1919
public static PartValue Construct(global::Part part, SharedObjects shared) {

0 commit comments

Comments
 (0)