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

XslCompiledTransform doesn't work when using TrimMode=link #45393

Closed
eerhardt opened this issue Dec 1, 2020 · 1 comment · Fixed by #45522
Closed

XslCompiledTransform doesn't work when using TrimMode=link #45393

eerhardt opened this issue Dec 1, 2020 · 1 comment · Fixed by #45522
Labels
area-System.Xml linkable-framework Issues associated with delivering a linker friendly framework untriaged New issue has not been triaged by the area owner
Milestone

Comments

@eerhardt
Copy link
Member

eerhardt commented Dec 1, 2020

See the original report of this issue: #44995 (comment)

Run the following code in a Blazor WASM published app. Or in a console app that is PublishTrimmed=true && TrimMode=link

        public static void UseXsl()
        {
            using (StringReader text = new StringReader(
    @"<?xml version=""1.0"" encoding=""UTF-8""?>
<catalog>
    <cd>
        <title>Empire Burlesque</title>
        <artist>Bob Dylan</artist>
        <country>USA</country>
        <company>Columbia</company>
        <price>10.90</price>
        <year>1985</year>
    </cd>
</catalog>"))
            {


                XPathDocument myXPathDoc = new XPathDocument(text);
                XslCompiledTransform myXslTrans = new XslCompiledTransform();
                string xmlStr = @"<?xml version=""1.0""?>
<xsl:stylesheet version=""1.0"" xmlns:xsl=""http://www.w3.org/1999/XSL/Transform"">
<xsl:template match=""/"">
<html>
<body>
<h2> My CD Collection</h2>
   <table border = ""1"">
      <tr bgcolor = ""#9acd32"">
         <th> Title </th>
         <th> Artist </th>
       </tr>

      <xsl:for-each select = ""catalog/cd"">
          <tr>
            <td><xsl:value-of select = ""title"" /></td>
            <td><xsl:value-of select = ""artist"" /></td>
          </tr>
        </xsl:for-each>
       </table>
     </body>
     </html>
   </xsl:template>
   </xsl:stylesheet>";
                using (StringReader str = new StringReader(xmlStr))
                using (var reader = System.Xml.XmlReader.Create(str))
                {
                    myXslTrans.Load(reader);
                    StringWriter myWriter = new StringWriter();
                    myXslTrans.Transform(myXPathDoc, null, myWriter);
                    Console.WriteLine(myWriter.GetStringBuilder().ToString());

                }
            }

        }

Expected results

The code should work the same way it does in a non-trimmed app.

Actual results

(unknown) Unhandled Exception:
window.console.error
(unknown) System.ArgumentNullException: ArgumentNull_Generic Arg_ParamName_Name, con
window.console.error
(unknown)    at System.Reflection.Emit.CustomAttributeBuilder.Initialize(ConstructorInfo con, Object[] constructorArgs, PropertyInfo[] namedProperties, Object[] propertyValues, FieldInfo[] namedFields, Object[] fieldValues)
window.console.error
(unknown)    at System.Reflection.Emit.CustomAttributeBuilder..ctor(ConstructorInfo con, Object[] constructorArgs)
window.console.error
(unknown)    at System.Xml.Xsl.IlGen.XmlILModule.CreateLREModule()
window.console.error
(unknown)    at System.Xml.Xsl.IlGen.XmlILModule..cctor()
window.console.error
(unknown) crit: Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100]
      Unhandled exception rendering component: TypeInitialization_Type, System.Xml.Xsl.IlGen.XmlILModule
System.TypeInitializationException: TypeInitialization_Type, System.Xml.Xsl.IlGen.XmlILModule
 ---> System.ArgumentNullException: ArgumentNull_Generic Arg_ParamName_Name, con
   at System.Reflection.Emit.CustomAttributeBuilder.Initialize(ConstructorInfo con, Object[] constructorArgs, PropertyInfo[] namedProperties, Object[] propertyValues, FieldInfo[] namedFields, Object[] fieldValues)
   at System.Reflection.Emit.CustomAttributeBuilder..ctor(ConstructorInfo con, Object[] constructorArgs)
   at System.Xml.Xsl.IlGen.XmlILModule.CreateLREModule()
   at System.Xml.Xsl.IlGen.XmlILModule..cctor()
   Exception_EndOfInnerExceptionStack
   at System.Xml.Xsl.XmlILGenerator.Generate(QilExpression query, TypeBuilder typeBldr)
   at System.Xml.Xsl.XslCompiledTransform.CompileQilToMsil(XsltSettings settings)
   at System.Xml.Xsl.XslCompiledTransform.LoadInternal(Object stylesheet, XsltSettings settings, XmlResolver stylesheetResolver)
   at System.Xml.Xsl.XslCompiledTransform.Load(XmlReader stylesheet)
   at Panasoft.Web.MyData.Client.Pages.Monitor.TraceView.OnParametersSetAsync()
   at Microsoft.AspNetCore.Components.ComponentBase.CallStateHasChangedOnAsyncCompletion(Task task)
   at Microsoft.AspNetCore.Components.ComponentBase.RunInitAndSetParametersAsync()
   at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task taskToHandle)

It looks like the following code needs to be annotated correctly for the ILLinker to preserve the constructors correctly:

internal static class XmlILConstructors
{
public static readonly ConstructorInfo DecFromParts = GetConstructor(typeof(decimal), typeof(int), typeof(int), typeof(int), typeof(bool), typeof(byte));
public static readonly ConstructorInfo DecFromInt32 = GetConstructor(typeof(decimal), typeof(int));
public static readonly ConstructorInfo DecFromInt64 = GetConstructor(typeof(decimal), typeof(long));
public static readonly ConstructorInfo Debuggable = GetConstructor(typeof(DebuggableAttribute), typeof(DebuggableAttribute.DebuggingModes));
public static readonly ConstructorInfo NonUserCode = GetConstructor(typeof(DebuggerNonUserCodeAttribute));
public static readonly ConstructorInfo QName = GetConstructor(typeof(XmlQualifiedName), typeof(string), typeof(string));
public static readonly ConstructorInfo StepThrough = GetConstructor(typeof(DebuggerStepThroughAttribute));
public static readonly ConstructorInfo Transparent = GetConstructor(typeof(SecurityTransparentAttribute));
private static ConstructorInfo GetConstructor(Type className)
{
ConstructorInfo constrInfo = className.GetConstructor(Type.EmptyTypes)!;
Debug.Assert(constrInfo != null, "Constructor " + className + " cannot be null.");
return constrInfo;
}
private static ConstructorInfo GetConstructor(Type className, params Type[] args)
{
ConstructorInfo constrInfo = className.GetConstructor(args)!;
Debug.Assert(constrInfo != null, "Constructor " + className + " cannot be null.");
return constrInfo;
}
}

Side-note: The ILLink warnings caught this as well:

<attribute fullname="System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessageAttribute">
<argument>ILLink</argument>
<argument>IL2070</argument>
<property name="Scope">member</property>
<property name="Target">M:System.Xml.Xsl.IlGen.XmlILConstructors.GetConstructor(System.Type,System.Type[])</property>
</attribute>
<attribute fullname="System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessageAttribute">
<argument>ILLink</argument>
<argument>IL2070</argument>
<property name="Scope">member</property>
<property name="Target">M:System.Xml.Xsl.IlGen.XmlILConstructors.GetConstructor(System.Type)</property>
</attribute>

@eerhardt eerhardt added area-System.Xml linkable-framework Issues associated with delivering a linker friendly framework labels Dec 1, 2020
@eerhardt eerhardt added this to the 6.0.0 milestone Dec 1, 2020
@ghost
Copy link

ghost commented Dec 1, 2020

Tagging subscribers to this area: @buyaa-n, @krwq, @jeffhandley
See info in area-owners.md if you want to be subscribed.

Issue Details

See the original report of this issue: #44995 (comment)

Run the following code in a Blazor WASM published app. Or in a console app that is PublishTrimmed=true && TrimMode=link

        public static void UseXsl()
        {
            using (StringReader text = new StringReader(
    @"<?xml version=""1.0"" encoding=""UTF-8""?>
<catalog>
    <cd>
        <title>Empire Burlesque</title>
        <artist>Bob Dylan</artist>
        <country>USA</country>
        <company>Columbia</company>
        <price>10.90</price>
        <year>1985</year>
    </cd>
</catalog>"))
            {


                XPathDocument myXPathDoc = new XPathDocument(text);
                XslCompiledTransform myXslTrans = new XslCompiledTransform();
                string xmlStr = @"<?xml version=""1.0""?>
<xsl:stylesheet version=""1.0"" xmlns:xsl=""http://www.w3.org/1999/XSL/Transform"">
<xsl:template match=""/"">
<html>
<body>
<h2> My CD Collection</h2>
   <table border = ""1"">
      <tr bgcolor = ""#9acd32"">
         <th> Title </th>
         <th> Artist </th>
       </tr>

      <xsl:for-each select = ""catalog/cd"">
          <tr>
            <td><xsl:value-of select = ""title"" /></td>
            <td><xsl:value-of select = ""artist"" /></td>
          </tr>
        </xsl:for-each>
       </table>
     </body>
     </html>
   </xsl:template>
   </xsl:stylesheet>";
                using (StringReader str = new StringReader(xmlStr))
                using (var reader = System.Xml.XmlReader.Create(str))
                {
                    myXslTrans.Load(reader);
                    StringWriter myWriter = new StringWriter();
                    myXslTrans.Transform(myXPathDoc, null, myWriter);
                    Console.WriteLine(myWriter.GetStringBuilder().ToString());

                }
            }

        }

Expected results

The code should work the same way it does in a non-trimmed app.

Actual results

(unknown) Unhandled Exception:
window.console.error
(unknown) System.ArgumentNullException: ArgumentNull_Generic Arg_ParamName_Name, con
window.console.error
(unknown)    at System.Reflection.Emit.CustomAttributeBuilder.Initialize(ConstructorInfo con, Object[] constructorArgs, PropertyInfo[] namedProperties, Object[] propertyValues, FieldInfo[] namedFields, Object[] fieldValues)
window.console.error
(unknown)    at System.Reflection.Emit.CustomAttributeBuilder..ctor(ConstructorInfo con, Object[] constructorArgs)
window.console.error
(unknown)    at System.Xml.Xsl.IlGen.XmlILModule.CreateLREModule()
window.console.error
(unknown)    at System.Xml.Xsl.IlGen.XmlILModule..cctor()
window.console.error
(unknown) crit: Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100]
      Unhandled exception rendering component: TypeInitialization_Type, System.Xml.Xsl.IlGen.XmlILModule
System.TypeInitializationException: TypeInitialization_Type, System.Xml.Xsl.IlGen.XmlILModule
 ---> System.ArgumentNullException: ArgumentNull_Generic Arg_ParamName_Name, con
   at System.Reflection.Emit.CustomAttributeBuilder.Initialize(ConstructorInfo con, Object[] constructorArgs, PropertyInfo[] namedProperties, Object[] propertyValues, FieldInfo[] namedFields, Object[] fieldValues)
   at System.Reflection.Emit.CustomAttributeBuilder..ctor(ConstructorInfo con, Object[] constructorArgs)
   at System.Xml.Xsl.IlGen.XmlILModule.CreateLREModule()
   at System.Xml.Xsl.IlGen.XmlILModule..cctor()
   Exception_EndOfInnerExceptionStack
   at System.Xml.Xsl.XmlILGenerator.Generate(QilExpression query, TypeBuilder typeBldr)
   at System.Xml.Xsl.XslCompiledTransform.CompileQilToMsil(XsltSettings settings)
   at System.Xml.Xsl.XslCompiledTransform.LoadInternal(Object stylesheet, XsltSettings settings, XmlResolver stylesheetResolver)
   at System.Xml.Xsl.XslCompiledTransform.Load(XmlReader stylesheet)
   at Panasoft.Web.MyData.Client.Pages.Monitor.TraceView.OnParametersSetAsync()
   at Microsoft.AspNetCore.Components.ComponentBase.CallStateHasChangedOnAsyncCompletion(Task task)
   at Microsoft.AspNetCore.Components.ComponentBase.RunInitAndSetParametersAsync()
   at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task taskToHandle)

It looks like the following code needs to be annotated correctly for the ILLinker to preserve the constructors correctly:

internal static class XmlILConstructors
{
public static readonly ConstructorInfo DecFromParts = GetConstructor(typeof(decimal), typeof(int), typeof(int), typeof(int), typeof(bool), typeof(byte));
public static readonly ConstructorInfo DecFromInt32 = GetConstructor(typeof(decimal), typeof(int));
public static readonly ConstructorInfo DecFromInt64 = GetConstructor(typeof(decimal), typeof(long));
public static readonly ConstructorInfo Debuggable = GetConstructor(typeof(DebuggableAttribute), typeof(DebuggableAttribute.DebuggingModes));
public static readonly ConstructorInfo NonUserCode = GetConstructor(typeof(DebuggerNonUserCodeAttribute));
public static readonly ConstructorInfo QName = GetConstructor(typeof(XmlQualifiedName), typeof(string), typeof(string));
public static readonly ConstructorInfo StepThrough = GetConstructor(typeof(DebuggerStepThroughAttribute));
public static readonly ConstructorInfo Transparent = GetConstructor(typeof(SecurityTransparentAttribute));
private static ConstructorInfo GetConstructor(Type className)
{
ConstructorInfo constrInfo = className.GetConstructor(Type.EmptyTypes)!;
Debug.Assert(constrInfo != null, "Constructor " + className + " cannot be null.");
return constrInfo;
}
private static ConstructorInfo GetConstructor(Type className, params Type[] args)
{
ConstructorInfo constrInfo = className.GetConstructor(args)!;
Debug.Assert(constrInfo != null, "Constructor " + className + " cannot be null.");
return constrInfo;
}
}

Side-note: The ILLink warnings caught this as well:

<attribute fullname="System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessageAttribute">
<argument>ILLink</argument>
<argument>IL2070</argument>
<property name="Scope">member</property>
<property name="Target">M:System.Xml.Xsl.IlGen.XmlILConstructors.GetConstructor(System.Type,System.Type[])</property>
</attribute>
<attribute fullname="System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessageAttribute">
<argument>ILLink</argument>
<argument>IL2070</argument>
<property name="Scope">member</property>
<property name="Target">M:System.Xml.Xsl.IlGen.XmlILConstructors.GetConstructor(System.Type)</property>
</attribute>

Author: eerhardt
Assignees: -
Labels:

area-System.Xml, linkable-framework

Milestone: 6.0.0

@Dotnet-GitSync-Bot Dotnet-GitSync-Bot added the untriaged New issue has not been triaged by the area owner label Dec 1, 2020
eerhardt added a commit to eerhardt/runtime that referenced this issue Dec 3, 2020
Resolve ILLinker warnings in Xml.Xsl in order to make a basic Xslt scenario work.

Fix dotnet#45393
eerhardt added a commit that referenced this issue Dec 8, 2020
Resolve ILLinker warnings in Xml.Xsl in order to make a basic Xslt scenario work.

Fix #45393
@ghost ghost locked as resolved and limited conversation to collaborators Jan 8, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-System.Xml linkable-framework Issues associated with delivering a linker friendly framework untriaged New issue has not been triaged by the area owner
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants