diff --git a/src/libraries/System.Private.Xml/src/ILLink/ILLink.Suppressions.xml b/src/libraries/System.Private.Xml/src/ILLink/ILLink.Suppressions.xml
index 5cc8e589f0faa..991377561048d 100644
--- a/src/libraries/System.Private.Xml/src/ILLink/ILLink.Suppressions.xml
+++ b/src/libraries/System.Private.Xml/src/ILLink/ILLink.Suppressions.xml
@@ -139,18 +139,6 @@
member
M:System.Xml.Serialization.XmlReflectionImporter.GetMethodFromSchemaProvider(System.Xml.Serialization.XmlSchemaProviderAttribute,System.Type)
-
- ILLink
- IL2070
- member
- M:System.Xml.Xsl.Runtime.EarlyBoundInfo.#ctor(System.String,System.Type)
-
-
- ILLink
- IL2070
- member
- M:System.Xml.Xsl.XslCompiledTransform.Load(System.Type)
-
ILLink
IL2072
@@ -175,12 +163,6 @@
member
M:System.Xml.Serialization.XmlSerializationILGen.GenerateTypedSerializer(System.String,System.String,System.Xml.Serialization.XmlMapping,System.Xml.Serialization.CodeIdentifiers,System.String,System.String,System.String)
-
- ILLink
- IL2072
- member
- M:System.Xml.Xsl.XsltOld.Processor.#ctor(System.Xml.XPath.XPathNavigator,System.Xml.Xsl.XsltArgumentList,System.Xml.XmlResolver,System.Xml.Xsl.XsltOld.Stylesheet,System.Collections.Generic.List{System.Xml.Xsl.XsltOld.TheQuery},System.Xml.Xsl.XsltOld.RootAction,System.Xml.Xsl.XsltOld.Debugger.IXsltDebugger)
-
ILLink
IL2075
@@ -319,18 +301,6 @@
member
M:System.Xml.Serialization.XmlSerializationWriterILGen.WriteElement(System.Xml.Serialization.SourceInfo,System.Xml.Serialization.ElementAccessor,System.String,System.Boolean)
-
- ILLink
- IL2075
- member
- M:System.Xml.Xsl.IlGen.XmlILModule.BakeMethods
-
-
- ILLink
- IL2075
- member
- M:System.Xml.Xsl.XsltOld.XsltCompileContext.GetExtentionMethod(System.String,System.String,System.Xml.XPath.XPathResultType[],System.Object@)
-
ILLink
IL2077
@@ -345,15 +315,21 @@
ILLink
- IL2080
+ IL2067
member
- M:System.Xml.Xsl.Runtime.XmlExtensionFunction.Bind
+ M:System.Xml.Xsl.Runtime.XmlExtensionFunction.#ctor(System.String,System.String,System.Int32,System.Type,System.Reflection.BindingFlags)
ILLink
- IL2080
+ IL2067
member
- M:System.Xml.Xsl.Runtime.XmlExtensionFunction.CanBind
+ M:System.Xml.Xsl.Runtime.XmlExtensionFunctionTable.Bind(System.String,System.String,System.Int32,System.Type,System.Reflection.BindingFlags)
+
+
+ ILLink
+ IL2075
+ member
+ M:System.Xml.Xsl.XsltOld.XsltCompileContext.GetExtentionMethod(System.String,System.String,System.Xml.XPath.XPathResultType[],System.Object@)
diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Xsl/IlGen/StaticDataManager.cs b/src/libraries/System.Private.Xml/src/System/Xml/Xsl/IlGen/StaticDataManager.cs
index c9e25cdad922b..8a163206ea3a4 100644
--- a/src/libraries/System.Private.Xml/src/System/Xml/Xsl/IlGen/StaticDataManager.cs
+++ b/src/libraries/System.Private.Xml/src/System/Xml/Xsl/IlGen/StaticDataManager.cs
@@ -4,6 +4,7 @@
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using System.Xml.Xsl.Qil;
using System.Xml.Xsl.Runtime;
@@ -172,7 +173,7 @@ public string[]? GlobalNames
/// Add early bound information to a list that is used by this query. Return the index of
/// the early bound information in the list.
///
- public int DeclareEarlyBound(string namespaceUri, Type ebType)
+ public int DeclareEarlyBound(string namespaceUri, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type ebType)
{
if (_earlyInfo == null)
_earlyInfo = new UniqueList();
diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Xsl/IlGen/XmlIlVisitor.cs b/src/libraries/System.Private.Xml/src/System/Xml/Xsl/IlGen/XmlIlVisitor.cs
index 10443b3ef29ea..49e6f3df25e30 100644
--- a/src/libraries/System.Private.Xml/src/System/Xml/Xsl/IlGen/XmlIlVisitor.cs
+++ b/src/libraries/System.Private.Xml/src/System/Xml/Xsl/IlGen/XmlIlVisitor.cs
@@ -35,6 +35,9 @@ internal class XmlILVisitor : QilVisitor
private IteratorDescriptor? _iterNested;
private int _indexId;
+ [RequiresUnreferencedCode("Method VisitXsltInvokeEarlyBound will require code that cannot be statically analyzed.")]
+ public XmlILVisitor()
+ { }
//-----------------------------------------------
// Entry
@@ -3597,6 +3600,9 @@ protected override QilNode VisitXsltInvokeLateBound(QilInvokeLateBound ndInvoke)
///
/// Generate code for QilNodeType.XsltInvokeEarlyBound.
///
+ [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2072:RequiresUnreferencedCode",
+ Justification = "Supressing warning about not having the RequiresUnreferencedCode attribute since we added " +
+ "the attribute to this subclass' constructor. This allows us to not have to annotate the whole QilNode hirerarchy.")]
protected override QilNode VisitXsltInvokeEarlyBound(QilInvokeEarlyBound ndInvoke)
{
QilName ndName = ndInvoke.Name;
diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Xsl/Runtime/EarlyBoundInfo.cs b/src/libraries/System.Private.Xml/src/System/Xml/Xsl/Runtime/EarlyBoundInfo.cs
index 9b44a9fe557d9..b63284285b45c 100644
--- a/src/libraries/System.Private.Xml/src/System/Xml/Xsl/Runtime/EarlyBoundInfo.cs
+++ b/src/libraries/System.Private.Xml/src/System/Xml/Xsl/Runtime/EarlyBoundInfo.cs
@@ -3,6 +3,7 @@
#nullable disable
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
using System.Reflection;
namespace System.Xml.Xsl.Runtime
@@ -14,13 +15,16 @@ internal sealed class EarlyBoundInfo
{
private readonly string _namespaceUri; // Namespace Uri mapped to these early bound functions
private readonly ConstructorInfo _constrInfo; // Constructor for the early bound function object
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)]
+ private readonly Type _ebType;
- public EarlyBoundInfo(string namespaceUri, Type ebType)
+ public EarlyBoundInfo(string namespaceUri, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type ebType)
{
Debug.Assert(namespaceUri != null && ebType != null);
// Get the default constructor
_namespaceUri = namespaceUri;
+ _ebType = ebType;
_constrInfo = ebType.GetConstructor(Type.EmptyTypes);
Debug.Assert(_constrInfo != null, "The early bound object type " + ebType.FullName + " must have a public default constructor");
}
@@ -33,7 +37,11 @@ public EarlyBoundInfo(string namespaceUri, Type ebType)
///
/// Return the Clr Type of the early bound object.
///
- public Type EarlyBoundType { get { return _constrInfo.DeclaringType; } }
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)]
+ public Type EarlyBoundType
+ {
+ get { return _ebType; }
+ }
///
/// Create an instance of the early bound object.
diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Xsl/Runtime/XmlExtensionFunction.cs b/src/libraries/System.Private.Xml/src/System/Xml/Xsl/Runtime/XmlExtensionFunction.cs
index 1707aa9d56099..6340197f07011 100644
--- a/src/libraries/System.Private.Xml/src/System/Xml/Xsl/Runtime/XmlExtensionFunction.cs
+++ b/src/libraries/System.Private.Xml/src/System/Xml/Xsl/Runtime/XmlExtensionFunction.cs
@@ -9,6 +9,7 @@
using System.Reflection;
using System.Globalization;
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
namespace System.Xml.Xsl.Runtime
{
@@ -57,6 +58,7 @@ internal class XmlExtensionFunction
private string _namespaceUri; // Extension object identifier
private string _name; // Name of this method
private int _numArgs; // Argument count
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods)]
private Type _objectType; // Type of the object which will be searched for matching methods
private BindingFlags _flags; // Modifiers that were used to search for a matching signature
private int _hashCode; // Pre-computed hashcode
@@ -95,7 +97,7 @@ public XmlExtensionFunction(string name, string namespaceUri, int numArgs, Type
///
/// Initialize, but do not bind.
///
- public void Init(string name, string namespaceUri, int numArgs, Type objectType, BindingFlags flags)
+ public void Init(string name, string namespaceUri, int numArgs, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.NonPublicMethods | DynamicallyAccessedMemberTypes.PublicMethods)] Type objectType, BindingFlags flags)
{
_name = name;
_namespaceUri = namespaceUri;
diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Xsl/Runtime/XmlQueryStaticData.cs b/src/libraries/System.Private.Xml/src/System/Xml/Xsl/Runtime/XmlQueryStaticData.cs
index 6f0fd48703b77..53387597f2db4 100644
--- a/src/libraries/System.Private.Xml/src/System/Xml/Xsl/Runtime/XmlQueryStaticData.cs
+++ b/src/libraries/System.Private.Xml/src/System/Xml/Xsl/Runtime/XmlQueryStaticData.cs
@@ -4,6 +4,7 @@
#nullable disable
using System.Collections.Generic;
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Xml.Xsl.IlGen;
using System.Xml.Xsl.Qil;
@@ -35,6 +36,7 @@ internal class XmlQueryStaticData
///
/// Constructor.
///
+ [RequiresUnreferencedCode("This method will create a copy that uses earlybound types which cannot be statically analyzed.")]
public XmlQueryStaticData(XmlWriterSettings defaultWriterSettings, IList whitespaceRules, StaticDataManager staticData)
{
Debug.Assert(defaultWriterSettings != null && staticData != null);
@@ -70,6 +72,7 @@ public XmlQueryStaticData(XmlWriterSettings defaultWriterSettings, IList
/// Deserialize XmlQueryStaticData object from a byte array.
///
+ [RequiresUnreferencedCode("This method will create EarlyBoundInfo from passed in ebTypes array which cannot be statically analyzed.")]
public XmlQueryStaticData(byte[] data, Type[] ebTypes)
{
MemoryStream dataStream = new MemoryStream(data, /*writable:*/false);
diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Xsl/XmlIlGenerator.cs b/src/libraries/System.Private.Xml/src/System/Xml/Xsl/XmlIlGenerator.cs
index 610a883ecfb0e..0e4272fb3d899 100644
--- a/src/libraries/System.Private.Xml/src/System/Xml/Xsl/XmlIlGenerator.cs
+++ b/src/libraries/System.Private.Xml/src/System/Xml/Xsl/XmlIlGenerator.cs
@@ -70,6 +70,10 @@ public XmlILGenerator()
// SxS Note: The way the trace file names are created (hardcoded) is NOT SxS safe. However the files are
// created only for internal tracing purposes. In addition XmlILTrace class is not compiled into retail
// builds. As a result it is fine to suppress the FxCop SxS warning.
+ [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode",
+ Justification = "This method will generate the IL methods using RefEmit at runtime, which will then try to call them " +
+ "using methods that are annotated as RequiresUnreferencedCode. In this case, these uses can be suppressed as the " +
+ "trimmer won't be able to trim any IL that gets generated at runtime.")]
public XmlILCommand? Generate(QilExpression query, TypeBuilder? typeBldr)
{
_qil = query;
diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Xsl/Xslt/QilGenerator.cs b/src/libraries/System.Private.Xml/src/System/Xml/Xsl/Xslt/QilGenerator.cs
index d7d3d3740534d..8f3526024e0ae 100644
--- a/src/libraries/System.Private.Xml/src/System/Xml/Xsl/Xslt/QilGenerator.cs
+++ b/src/libraries/System.Private.Xml/src/System/Xml/Xsl/Xslt/QilGenerator.cs
@@ -196,13 +196,14 @@ private QilExpression Compile(Compiler compiler)
}
// Create list of all early bound objects
- Dictionary scriptClasses = compiler.Scripts.ScriptClasses;
+ Scripts.TrimSafeDictionary scriptClasses = compiler.Scripts.ScriptClasses;
List ebTypes = new List(scriptClasses.Count);
- foreach (KeyValuePair pair in scriptClasses)
+ foreach (string key in scriptClasses.Keys)
{
- if (pair.Value != null)
+ Type? value = scriptClasses[key];
+ if (value != null)
{
- ebTypes.Add(new EarlyBoundInfo(pair.Key, pair.Value));
+ ebTypes.Add(new EarlyBoundInfo(key, value));
}
}
diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Xsl/Xslt/Scripts.cs b/src/libraries/System.Private.Xml/src/System/Xml/Xsl/Xslt/Scripts.cs
index cbc8e315b3a92..d486470c823df 100644
--- a/src/libraries/System.Private.Xml/src/System/Xml/Xsl/Xslt/Scripts.cs
+++ b/src/libraries/System.Private.Xml/src/System/Xml/Xsl/Xslt/Scripts.cs
@@ -4,7 +4,9 @@
// http://devdiv/Documents/Whidbey/CLR/CurrentSpecs/BCL/CodeDom%20Activation.doc
//------------------------------------------------------------------------------
+using System.Collections;
using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
using System.Xml.Xsl.Runtime;
namespace System.Xml.Xsl.Xslt
@@ -12,7 +14,7 @@ namespace System.Xml.Xsl.Xslt
internal class Scripts
{
private readonly Compiler _compiler;
- private readonly Dictionary _nsToType = new Dictionary();
+ private readonly TrimSafeDictionary _nsToType = new TrimSafeDictionary();
private readonly XmlExtensionFunctionTable _extFuncs = new XmlExtensionFunctionTable();
public Scripts(Compiler compiler)
@@ -20,7 +22,7 @@ public Scripts(Compiler compiler)
_compiler = compiler;
}
- public Dictionary ScriptClasses
+ public TrimSafeDictionary ScriptClasses
{
get { return _nsToType; }
}
@@ -41,5 +43,29 @@ public Scripts(Compiler compiler)
}
return null;
}
+
+ internal class TrimSafeDictionary
+ {
+ private readonly Dictionary _backingDictionary = new Dictionary();
+
+ public Type? this[string key]
+ {
+ [UnconditionalSuppressMessage("TrimAnalysis", "IL2073:MissingDynamicallyAccessedMembers",
+ Justification = "The getter of the dictionary is not annotated to preserve the constructor, but the sources that are adding the items to " +
+ "the dictionary are annotated so we can supress the message as we know the constructor will be preserved.")]
+ [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)]
+ get => _backingDictionary[key];
+ [param: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)]
+ set => _backingDictionary[key] = value;
+ }
+
+ public ICollection Keys => _backingDictionary.Keys;
+
+ public int Count => _backingDictionary.Count;
+
+ public bool ContainsKey(string key) => _backingDictionary.ContainsKey(key);
+
+ public bool TryGetValue(string key, [MaybeNullWhen(false)] out Type? value) => _backingDictionary.TryGetValue(key, out value);
+ }
}
}
diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Xsl/XsltOld/Processor.cs b/src/libraries/System.Private.Xml/src/System/Xml/Xsl/XsltOld/Processor.cs
index 8ef9fb4acef42..e9274d40a16a7 100644
--- a/src/libraries/System.Private.Xml/src/System/Xml/Xsl/XsltOld/Processor.cs
+++ b/src/libraries/System.Private.Xml/src/System/Xml/Xsl/XsltOld/Processor.cs
@@ -371,15 +371,10 @@ public Processor(
_scriptExtensions = new Hashtable(_stylesheet.ScriptObjectTypes.Count);
{
- foreach (DictionaryEntry entry in _stylesheet.ScriptObjectTypes)
+ // Scripts are not supported on stylesheets
+ if (_stylesheet.ScriptObjectTypes.Count > 0)
{
- string namespaceUri = (string)entry.Key;
- if (GetExtensionObject(namespaceUri) != null)
- {
- throw XsltException.Create(SR.Xslt_ScriptDub, namespaceUri);
- }
- _scriptExtensions.Add(namespaceUri, Activator.CreateInstance((Type)entry.Value!,
- BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, null, null));
+ throw new PlatformNotSupportedException(SR.CompilingScriptsNotSupported);
}
}
diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Xslt/XslCompiledTransform.cs b/src/libraries/System.Private.Xml/src/System/Xml/Xslt/XslCompiledTransform.cs
index 6ed5b7ace1a74..f9abc50023f24 100644
--- a/src/libraries/System.Private.Xml/src/System/Xml/Xslt/XslCompiledTransform.cs
+++ b/src/libraries/System.Private.Xml/src/System/Xml/Xslt/XslCompiledTransform.cs
@@ -194,7 +194,7 @@ private void CompileQilToMsil(XsltSettings settings)
//------------------------------------------------
// Load compiled stylesheet from a Type
//------------------------------------------------
-
+ [RequiresUnreferencedCode("This method will get fields and types from the assembly of the passed in compiledStylesheet and call their constructors which cannot be statically analyzed")]
public void Load(Type compiledStylesheet)
{
Reset();
@@ -238,6 +238,7 @@ public void Load(Type compiledStylesheet)
throw new ArgumentException(SR.Format(SR.Xslt_NotCompiledStylesheet, compiledStylesheet.FullName), nameof(compiledStylesheet));
}
+ [RequiresUnreferencedCode("This method will call into constructors of the earlyBoundTypes array which cannot be statically analyzed.")]
public void Load(MethodInfo executeMethod, byte[] queryData, Type[]? earlyBoundTypes)
{
Reset();
diff --git a/src/libraries/System.Private.Xml/tests/Xslt/XslTransformApi/CXslTransform.cs b/src/libraries/System.Private.Xml/tests/Xslt/XslTransformApi/CXslTransform.cs
index 2a71cb87072ef..141c830925b1b 100644
--- a/src/libraries/System.Private.Xml/tests/Xslt/XslTransformApi/CXslTransform.cs
+++ b/src/libraries/System.Private.Xml/tests/Xslt/XslTransformApi/CXslTransform.cs
@@ -871,6 +871,34 @@ public void LoadGeneric12(InputType inputType, ReaderType readerType)
_output.WriteLine("Did not throw compile exception for stylesheet");
Assert.True(false);
}
+
+ [Fact]
+ public void XslTransformThrowsPNSEWhenUsingScripts()
+ {
+ using StringReader xslFile = new StringReader(
+ @"
+
+
+
+
+
+
+
+
+");
+
+ using XmlReader reader = XmlReader.Create(xslFile);
+ XslTransform xslt = new XslTransform();
+ XsltCompileException compilationException = Assert.Throws(() => xslt.Load(reader));
+ Assert.True(compilationException.InnerException != null && compilationException.InnerException is PlatformNotSupportedException);
+ }
}
/**************************************************************************/
diff --git a/src/libraries/System.Xml.ReaderWriter/ref/System.Xml.ReaderWriter.cs b/src/libraries/System.Xml.ReaderWriter/ref/System.Xml.ReaderWriter.cs
index 01cedbb200edd..b5d4ab5dc9311 100644
--- a/src/libraries/System.Xml.ReaderWriter/ref/System.Xml.ReaderWriter.cs
+++ b/src/libraries/System.Xml.ReaderWriter/ref/System.Xml.ReaderWriter.cs
@@ -2787,9 +2787,11 @@ public sealed partial class XslCompiledTransform
public XslCompiledTransform() { }
public XslCompiledTransform(bool enableDebug) { }
public System.Xml.XmlWriterSettings? OutputSettings { get { throw null; } }
+ [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("This method will call into constructors of the earlyBoundTypes array which cannot be statically analyzed.")]
public void Load(System.Reflection.MethodInfo executeMethod, byte[] queryData, System.Type[]? earlyBoundTypes) { }
public void Load(string stylesheetUri) { }
public void Load(string stylesheetUri, System.Xml.Xsl.XsltSettings? settings, System.Xml.XmlResolver? stylesheetResolver) { }
+ [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("This method will get fields and types from the assembly of the passed in compiledStylesheet and call their constructors which cannot be statically analyzed")]
public void Load(System.Type compiledStylesheet) { }
public void Load(System.Xml.XmlReader stylesheet) { }
public void Load(System.Xml.XmlReader stylesheet, System.Xml.Xsl.XsltSettings? settings, System.Xml.XmlResolver? stylesheetResolver) { }