Do not trim private methods used by the designer #102244

Description

@Tanya-Solyanik

Description

Copied from dotnet/winforms#11314

Private methods whose names follow the pattern ShouldSerialize<PropertyName> or Reset<ProppertyName> should not be trimmed by the linker because they are used by the TypeDescriptor via reflection. Additional conditions: Winforms designer is interested in types derived from IComponent. Property should not be hidden from serializers via SerializerVisibility attribute. Property should be public.

TypeDescriptor accesses these methods here

Suggested fix from @ericstj

The fix is to add a file here runtime/src/libraries/System.Data.Common/src/ILLink at bad00cf23ec49a2607776ffd6e1810c4dbf540b3 · dotnet/runtime (github.com)

That looks similar to runtime/src/libraries/System.ComponentModel.TypeConverter/src/ILLink/ILLink.Descriptors.LibraryBuild.xml at bad00cf23ec49a2607776ffd6e1810c4dbf540b3 · dotnet/runtime (github.com)

Search pattern for ShouldSerialize

Search pattern for Reset

Searches yeld some false positives if the class is not designable, not an IComponent, or class does not have the public, serializable property, or method is actually called directly. For each property we need to examine metadata in the trimmed assembly to see if the methods were removed.

Reproduction Steps

This works on 4.8.1 but doesn't on net6

usingSystem;usingSystem.ComponentModel;usingSystem.Data;namespaceConsoleApp1{internalclassProgram{staticvoidMain(string[]args){DataColumndataColumn1=newDataColumn{ColumnName="dataColumn1",DataType=typeof(DateTime)};varproperties=TypeDescriptor.GetProperties(dataColumn1);varproperty=properties[nameof(DataColumn.DefaultValue)];if(property!=null){boolshouldSerialize=property.ShouldSerializeValue(dataColumn1);Console.WriteLine($"ShouldSerialize default? expected {false} actual {shouldSerialize}");dataColumn1.DefaultValue=DateTime.MinValue;shouldSerialize=property.ShouldSerializeValue(dataColumn1);Console.WriteLine($"ShouldSerialize changed? expected {true} actual {shouldSerialize}");// Reset method is not availableproperty.ResetValue(dataColumn1);Console.WriteLine($"Reset? expected {DateTime.MinValue} actual {dataColumn1.DefaultValue}");}property=properties[nameof(DataColumn.Caption)];if(property!=null){boolshouldSerialize=property.ShouldSerializeValue(dataColumn1);Console.WriteLine($"ShouldSerialize default? expected {false} actual {shouldSerialize}");dataColumn1.Caption="Caption";shouldSerialize=property.ShouldSerializeValue(dataColumn1);Console.WriteLine($"ShouldSerialize changed? expected {true} actual {shouldSerialize}");// Reset method is availableproperty.ResetValue(dataColumn1);Console.WriteLine($"Reset? expected {nameof(dataColumn1)} actual {dataColumn1.Caption}");}property=properties[nameof(DataColumn.Namespace)];if(property!=null){boolshouldSerialize=property.ShouldSerializeValue(dataColumn1);Console.WriteLine($"ShouldSerialize default? expected {false} actual {shouldSerialize}");dataColumn1.Namespace="Namespace";shouldSerialize=property.ShouldSerializeValue(dataColumn1);Console.WriteLine($"ShouldSerialize changed? expected {true} actual {shouldSerialize}");// Reset method is availableproperty.ResetValue(dataColumn1);Console.WriteLine($"Reset? expected '' actual `{dataColumn1.Namespace}`");}_=Console.ReadLine();}}}

Expected behavior

ShouldSerialize, Reset methods are present in the assembly

Actual behavior

ShouldSerialize, Reset methods are trimmed

Regression?

The end scenario regressed between the InProc and OOP designers.

Known Workarounds

none

Configuration

WIndows

Other information

Trimmed ShouldSerialize causes serialization using BinaryFormatter. The fix should be serviced.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

    , 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
     blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
    }
    } catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
    })();
    (function(){
    try {
    var __m = "github.com";
    var __re = new RegExp('^' + "github\\.com" + '
    
    Skip to content

    Do not trim private methods used by the designer #102244

    Description

    @Tanya-Solyanik

    Description

    Copied from dotnet/winforms#11314

    Private methods whose names follow the pattern ShouldSerialize<PropertyName> or Reset<ProppertyName> should not be trimmed by the linker because they are used by the TypeDescriptor via reflection. Additional conditions: Winforms designer is interested in types derived from IComponent. Property should not be hidden from serializers via SerializerVisibility attribute. Property should be public.

    TypeDescriptor accesses these methods here

    Suggested fix from @ericstj

    The fix is to add a file here runtime/src/libraries/System.Data.Common/src/ILLink at bad00cf23ec49a2607776ffd6e1810c4dbf540b3 · dotnet/runtime (github.com)

    That looks similar to runtime/src/libraries/System.ComponentModel.TypeConverter/src/ILLink/ILLink.Descriptors.LibraryBuild.xml at bad00cf23ec49a2607776ffd6e1810c4dbf540b3 · dotnet/runtime (github.com)

    Search pattern for ShouldSerialize

    Search pattern for Reset

    Searches yeld some false positives if the class is not designable, not an IComponent, or class does not have the public, serializable property, or method is actually called directly. For each property we need to examine metadata in the trimmed assembly to see if the methods were removed.

    Reproduction Steps

    This works on 4.8.1 but doesn't on net6

    usingSystem;usingSystem.ComponentModel;usingSystem.Data;namespaceConsoleApp1{internalclassProgram{staticvoidMain(string[]args){DataColumndataColumn1=newDataColumn{ColumnName="dataColumn1",DataType=typeof(DateTime)};varproperties=TypeDescriptor.GetProperties(dataColumn1);varproperty=properties[nameof(DataColumn.DefaultValue)];if(property!=null){boolshouldSerialize=property.ShouldSerializeValue(dataColumn1);Console.WriteLine($"ShouldSerialize default? expected {false} actual {shouldSerialize}");dataColumn1.DefaultValue=DateTime.MinValue;shouldSerialize=property.ShouldSerializeValue(dataColumn1);Console.WriteLine($"ShouldSerialize changed? expected {true} actual {shouldSerialize}");// Reset method is not availableproperty.ResetValue(dataColumn1);Console.WriteLine($"Reset? expected {DateTime.MinValue} actual {dataColumn1.DefaultValue}");}property=properties[nameof(DataColumn.Caption)];if(property!=null){boolshouldSerialize=property.ShouldSerializeValue(dataColumn1);Console.WriteLine($"ShouldSerialize default? expected {false} actual {shouldSerialize}");dataColumn1.Caption="Caption";shouldSerialize=property.ShouldSerializeValue(dataColumn1);Console.WriteLine($"ShouldSerialize changed? expected {true} actual {shouldSerialize}");// Reset method is availableproperty.ResetValue(dataColumn1);Console.WriteLine($"Reset? expected {nameof(dataColumn1)} actual {dataColumn1.Caption}");}property=properties[nameof(DataColumn.Namespace)];if(property!=null){boolshouldSerialize=property.ShouldSerializeValue(dataColumn1);Console.WriteLine($"ShouldSerialize default? expected {false} actual {shouldSerialize}");dataColumn1.Namespace="Namespace";shouldSerialize=property.ShouldSerializeValue(dataColumn1);Console.WriteLine($"ShouldSerialize changed? expected {true} actual {shouldSerialize}");// Reset method is availableproperty.ResetValue(dataColumn1);Console.WriteLine($"Reset? expected '' actual `{dataColumn1.Namespace}`");}_=Console.ReadLine();}}}

    Expected behavior

    ShouldSerialize, Reset methods are present in the assembly

    Actual behavior

    ShouldSerialize, Reset methods are trimmed

    Regression?

    The end scenario regressed between the InProc and OOP designers.

    Known Workarounds

    none

    Configuration

    WIndows

    Other information

    Trimmed ShouldSerialize causes serialization using BinaryFormatter. The fix should be serviced.

    Metadata

    Metadata

    Assignees

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions

      , 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
      Skip to content

      Do not trim private methods used by the designer #102244

      Description

      @Tanya-Solyanik

      Description

      Copied from dotnet/winforms#11314

      Private methods whose names follow the pattern ShouldSerialize<PropertyName> or Reset<ProppertyName> should not be trimmed by the linker because they are used by the TypeDescriptor via reflection. Additional conditions: Winforms designer is interested in types derived from IComponent. Property should not be hidden from serializers via SerializerVisibility attribute. Property should be public.

      TypeDescriptor accesses these methods here

      Suggested fix from @ericstj

      The fix is to add a file here runtime/src/libraries/System.Data.Common/src/ILLink at bad00cf23ec49a2607776ffd6e1810c4dbf540b3 · dotnet/runtime (github.com)

      That looks similar to runtime/src/libraries/System.ComponentModel.TypeConverter/src/ILLink/ILLink.Descriptors.LibraryBuild.xml at bad00cf23ec49a2607776ffd6e1810c4dbf540b3 · dotnet/runtime (github.com)

      Search pattern for ShouldSerialize

      Search pattern for Reset

      Searches yeld some false positives if the class is not designable, not an IComponent, or class does not have the public, serializable property, or method is actually called directly. For each property we need to examine metadata in the trimmed assembly to see if the methods were removed.

      Reproduction Steps

      This works on 4.8.1 but doesn't on net6

      usingSystem;usingSystem.ComponentModel;usingSystem.Data;namespaceConsoleApp1{internalclassProgram{staticvoidMain(string[]args){DataColumndataColumn1=newDataColumn{ColumnName="dataColumn1",DataType=typeof(DateTime)};varproperties=TypeDescriptor.GetProperties(dataColumn1);varproperty=properties[nameof(DataColumn.DefaultValue)];if(property!=null){boolshouldSerialize=property.ShouldSerializeValue(dataColumn1);Console.WriteLine($"ShouldSerialize default? expected {false} actual {shouldSerialize}");dataColumn1.DefaultValue=DateTime.MinValue;shouldSerialize=property.ShouldSerializeValue(dataColumn1);Console.WriteLine($"ShouldSerialize changed? expected {true} actual {shouldSerialize}");// Reset method is not availableproperty.ResetValue(dataColumn1);Console.WriteLine($"Reset? expected {DateTime.MinValue} actual {dataColumn1.DefaultValue}");}property=properties[nameof(DataColumn.Caption)];if(property!=null){boolshouldSerialize=property.ShouldSerializeValue(dataColumn1);Console.WriteLine($"ShouldSerialize default? expected {false} actual {shouldSerialize}");dataColumn1.Caption="Caption";shouldSerialize=property.ShouldSerializeValue(dataColumn1);Console.WriteLine($"ShouldSerialize changed? expected {true} actual {shouldSerialize}");// Reset method is availableproperty.ResetValue(dataColumn1);Console.WriteLine($"Reset? expected {nameof(dataColumn1)} actual {dataColumn1.Caption}");}property=properties[nameof(DataColumn.Namespace)];if(property!=null){boolshouldSerialize=property.ShouldSerializeValue(dataColumn1);Console.WriteLine($"ShouldSerialize default? expected {false} actual {shouldSerialize}");dataColumn1.Namespace="Namespace";shouldSerialize=property.ShouldSerializeValue(dataColumn1);Console.WriteLine($"ShouldSerialize changed? expected {true} actual {shouldSerialize}");// Reset method is availableproperty.ResetValue(dataColumn1);Console.WriteLine($"Reset? expected '' actual `{dataColumn1.Namespace}`");}_=Console.ReadLine();}}}

      Expected behavior

      ShouldSerialize, Reset methods are present in the assembly

      Actual behavior

      ShouldSerialize, Reset methods are trimmed

      Regression?

      The end scenario regressed between the InProc and OOP designers.

      Known Workarounds

      none

      Configuration

      WIndows

      Other information

      Trimmed ShouldSerialize causes serialization using BinaryFormatter. The fix should be serviced.

      Metadata

      Metadata

      Assignees

      Type

      No type

      Projects

      No projects

        Milestone

        Relationships

        None yet

        Development

        No branches or pull requests

        Issue actions

        , 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
        Skip to content

        Do not trim private methods used by the designer #102244

        Description

        @Tanya-Solyanik

        Description

        Copied from dotnet/winforms#11314

        Private methods whose names follow the pattern ShouldSerialize<PropertyName> or Reset<ProppertyName> should not be trimmed by the linker because they are used by the TypeDescriptor via reflection. Additional conditions: Winforms designer is interested in types derived from IComponent. Property should not be hidden from serializers via SerializerVisibility attribute. Property should be public.

        TypeDescriptor accesses these methods here

        Suggested fix from @ericstj

        The fix is to add a file here runtime/src/libraries/System.Data.Common/src/ILLink at bad00cf23ec49a2607776ffd6e1810c4dbf540b3 · dotnet/runtime (github.com)

        That looks similar to runtime/src/libraries/System.ComponentModel.TypeConverter/src/ILLink/ILLink.Descriptors.LibraryBuild.xml at bad00cf23ec49a2607776ffd6e1810c4dbf540b3 · dotnet/runtime (github.com)

        Search pattern for ShouldSerialize

        Search pattern for Reset

        Searches yeld some false positives if the class is not designable, not an IComponent, or class does not have the public, serializable property, or method is actually called directly. For each property we need to examine metadata in the trimmed assembly to see if the methods were removed.

        Reproduction Steps

        This works on 4.8.1 but doesn't on net6

        usingSystem;usingSystem.ComponentModel;usingSystem.Data;namespaceConsoleApp1{internalclassProgram{staticvoidMain(string[]args){DataColumndataColumn1=newDataColumn{ColumnName="dataColumn1",DataType=typeof(DateTime)};varproperties=TypeDescriptor.GetProperties(dataColumn1);varproperty=properties[nameof(DataColumn.DefaultValue)];if(property!=null){boolshouldSerialize=property.ShouldSerializeValue(dataColumn1);Console.WriteLine($"ShouldSerialize default? expected {false} actual {shouldSerialize}");dataColumn1.DefaultValue=DateTime.MinValue;shouldSerialize=property.ShouldSerializeValue(dataColumn1);Console.WriteLine($"ShouldSerialize changed? expected {true} actual {shouldSerialize}");// Reset method is not availableproperty.ResetValue(dataColumn1);Console.WriteLine($"Reset? expected {DateTime.MinValue} actual {dataColumn1.DefaultValue}");}property=properties[nameof(DataColumn.Caption)];if(property!=null){boolshouldSerialize=property.ShouldSerializeValue(dataColumn1);Console.WriteLine($"ShouldSerialize default? expected {false} actual {shouldSerialize}");dataColumn1.Caption="Caption";shouldSerialize=property.ShouldSerializeValue(dataColumn1);Console.WriteLine($"ShouldSerialize changed? expected {true} actual {shouldSerialize}");// Reset method is availableproperty.ResetValue(dataColumn1);Console.WriteLine($"Reset? expected {nameof(dataColumn1)} actual {dataColumn1.Caption}");}property=properties[nameof(DataColumn.Namespace)];if(property!=null){boolshouldSerialize=property.ShouldSerializeValue(dataColumn1);Console.WriteLine($"ShouldSerialize default? expected {false} actual {shouldSerialize}");dataColumn1.Namespace="Namespace";shouldSerialize=property.ShouldSerializeValue(dataColumn1);Console.WriteLine($"ShouldSerialize changed? expected {true} actual {shouldSerialize}");// Reset method is availableproperty.ResetValue(dataColumn1);Console.WriteLine($"Reset? expected '' actual `{dataColumn1.Namespace}`");}_=Console.ReadLine();}}}

        Expected behavior

        ShouldSerialize, Reset methods are present in the assembly

        Actual behavior

        ShouldSerialize, Reset methods are trimmed

        Regression?

        The end scenario regressed between the InProc and OOP designers.

        Known Workarounds

        none

        Configuration

        WIndows

        Other information

        Trimmed ShouldSerialize causes serialization using BinaryFormatter. The fix should be serviced.

        Metadata

        Metadata

        Assignees

        Type

        No type

        Projects

        No projects

          Milestone

          Relationships

          None yet

          Development

          No branches or pull requests

          Issue actions

          , 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
          Skip to content

          Do not trim private methods used by the designer #102244

          Description

          @Tanya-Solyanik

          Description

          Copied from dotnet/winforms#11314

          Private methods whose names follow the pattern ShouldSerialize<PropertyName> or Reset<ProppertyName> should not be trimmed by the linker because they are used by the TypeDescriptor via reflection. Additional conditions: Winforms designer is interested in types derived from IComponent. Property should not be hidden from serializers via SerializerVisibility attribute. Property should be public.

          TypeDescriptor accesses these methods here

          Suggested fix from @ericstj

          The fix is to add a file here runtime/src/libraries/System.Data.Common/src/ILLink at bad00cf23ec49a2607776ffd6e1810c4dbf540b3 · dotnet/runtime (github.com)

          That looks similar to runtime/src/libraries/System.ComponentModel.TypeConverter/src/ILLink/ILLink.Descriptors.LibraryBuild.xml at bad00cf23ec49a2607776ffd6e1810c4dbf540b3 · dotnet/runtime (github.com)

          Search pattern for ShouldSerialize

          Search pattern for Reset

          Searches yeld some false positives if the class is not designable, not an IComponent, or class does not have the public, serializable property, or method is actually called directly. For each property we need to examine metadata in the trimmed assembly to see if the methods were removed.

          Reproduction Steps

          This works on 4.8.1 but doesn't on net6

          usingSystem;usingSystem.ComponentModel;usingSystem.Data;namespaceConsoleApp1{internalclassProgram{staticvoidMain(string[]args){DataColumndataColumn1=newDataColumn{ColumnName="dataColumn1",DataType=typeof(DateTime)};varproperties=TypeDescriptor.GetProperties(dataColumn1);varproperty=properties[nameof(DataColumn.DefaultValue)];if(property!=null){boolshouldSerialize=property.ShouldSerializeValue(dataColumn1);Console.WriteLine($"ShouldSerialize default? expected {false} actual {shouldSerialize}");dataColumn1.DefaultValue=DateTime.MinValue;shouldSerialize=property.ShouldSerializeValue(dataColumn1);Console.WriteLine($"ShouldSerialize changed? expected {true} actual {shouldSerialize}");// Reset method is not availableproperty.ResetValue(dataColumn1);Console.WriteLine($"Reset? expected {DateTime.MinValue} actual {dataColumn1.DefaultValue}");}property=properties[nameof(DataColumn.Caption)];if(property!=null){boolshouldSerialize=property.ShouldSerializeValue(dataColumn1);Console.WriteLine($"ShouldSerialize default? expected {false} actual {shouldSerialize}");dataColumn1.Caption="Caption";shouldSerialize=property.ShouldSerializeValue(dataColumn1);Console.WriteLine($"ShouldSerialize changed? expected {true} actual {shouldSerialize}");// Reset method is availableproperty.ResetValue(dataColumn1);Console.WriteLine($"Reset? expected {nameof(dataColumn1)} actual {dataColumn1.Caption}");}property=properties[nameof(DataColumn.Namespace)];if(property!=null){boolshouldSerialize=property.ShouldSerializeValue(dataColumn1);Console.WriteLine($"ShouldSerialize default? expected {false} actual {shouldSerialize}");dataColumn1.Namespace="Namespace";shouldSerialize=property.ShouldSerializeValue(dataColumn1);Console.WriteLine($"ShouldSerialize changed? expected {true} actual {shouldSerialize}");// Reset method is availableproperty.ResetValue(dataColumn1);Console.WriteLine($"Reset? expected '' actual `{dataColumn1.Namespace}`");}_=Console.ReadLine();}}}

          Expected behavior

          ShouldSerialize, Reset methods are present in the assembly

          Actual behavior

          ShouldSerialize, Reset methods are trimmed

          Regression?

          The end scenario regressed between the InProc and OOP designers.

          Known Workarounds

          none

          Configuration

          WIndows

          Other information

          Trimmed ShouldSerialize causes serialization using BinaryFormatter. The fix should be serviced.

          Metadata

          Metadata

          Assignees

          Type

          No type

          Projects

          No projects

            Milestone

            Relationships

            None yet

            Development

            No branches or pull requests

            Issue actions

            , 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
            Skip to content

            Do not trim private methods used by the designer #102244

            Description

            @Tanya-Solyanik

            Description

            Copied from dotnet/winforms#11314

            Private methods whose names follow the pattern ShouldSerialize<PropertyName> or Reset<ProppertyName> should not be trimmed by the linker because they are used by the TypeDescriptor via reflection. Additional conditions: Winforms designer is interested in types derived from IComponent. Property should not be hidden from serializers via SerializerVisibility attribute. Property should be public.

            TypeDescriptor accesses these methods here

            Suggested fix from @ericstj

            The fix is to add a file here runtime/src/libraries/System.Data.Common/src/ILLink at bad00cf23ec49a2607776ffd6e1810c4dbf540b3 · dotnet/runtime (github.com)

            That looks similar to runtime/src/libraries/System.ComponentModel.TypeConverter/src/ILLink/ILLink.Descriptors.LibraryBuild.xml at bad00cf23ec49a2607776ffd6e1810c4dbf540b3 · dotnet/runtime (github.com)

            Search pattern for ShouldSerialize

            Search pattern for Reset

            Searches yeld some false positives if the class is not designable, not an IComponent, or class does not have the public, serializable property, or method is actually called directly. For each property we need to examine metadata in the trimmed assembly to see if the methods were removed.

            Reproduction Steps

            This works on 4.8.1 but doesn't on net6

            usingSystem;usingSystem.ComponentModel;usingSystem.Data;namespaceConsoleApp1{internalclassProgram{staticvoidMain(string[]args){DataColumndataColumn1=newDataColumn{ColumnName="dataColumn1",DataType=typeof(DateTime)};varproperties=TypeDescriptor.GetProperties(dataColumn1);varproperty=properties[nameof(DataColumn.DefaultValue)];if(property!=null){boolshouldSerialize=property.ShouldSerializeValue(dataColumn1);Console.WriteLine($"ShouldSerialize default? expected {false} actual {shouldSerialize}");dataColumn1.DefaultValue=DateTime.MinValue;shouldSerialize=property.ShouldSerializeValue(dataColumn1);Console.WriteLine($"ShouldSerialize changed? expected {true} actual {shouldSerialize}");// Reset method is not availableproperty.ResetValue(dataColumn1);Console.WriteLine($"Reset? expected {DateTime.MinValue} actual {dataColumn1.DefaultValue}");}property=properties[nameof(DataColumn.Caption)];if(property!=null){boolshouldSerialize=property.ShouldSerializeValue(dataColumn1);Console.WriteLine($"ShouldSerialize default? expected {false} actual {shouldSerialize}");dataColumn1.Caption="Caption";shouldSerialize=property.ShouldSerializeValue(dataColumn1);Console.WriteLine($"ShouldSerialize changed? expected {true} actual {shouldSerialize}");// Reset method is availableproperty.ResetValue(dataColumn1);Console.WriteLine($"Reset? expected {nameof(dataColumn1)} actual {dataColumn1.Caption}");}property=properties[nameof(DataColumn.Namespace)];if(property!=null){boolshouldSerialize=property.ShouldSerializeValue(dataColumn1);Console.WriteLine($"ShouldSerialize default? expected {false} actual {shouldSerialize}");dataColumn1.Namespace="Namespace";shouldSerialize=property.ShouldSerializeValue(dataColumn1);Console.WriteLine($"ShouldSerialize changed? expected {true} actual {shouldSerialize}");// Reset method is availableproperty.ResetValue(dataColumn1);Console.WriteLine($"Reset? expected '' actual `{dataColumn1.Namespace}`");}_=Console.ReadLine();}}}

            Expected behavior

            ShouldSerialize, Reset methods are present in the assembly

            Actual behavior

            ShouldSerialize, Reset methods are trimmed

            Regression?

            The end scenario regressed between the InProc and OOP designers.

            Known Workarounds

            none

            Configuration

            WIndows

            Other information

            Trimmed ShouldSerialize causes serialization using BinaryFormatter. The fix should be serviced.

            Metadata

            Metadata

            Assignees

            Type

            No type

            Projects

            No projects

              Milestone

              Relationships

              None yet

              Development

              No branches or pull requests

              Issue actions

              , 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
              Skip to content

              Do not trim private methods used by the designer #102244

              Description

              @Tanya-Solyanik

              Description

              Copied from dotnet/winforms#11314

              Private methods whose names follow the pattern ShouldSerialize<PropertyName> or Reset<ProppertyName> should not be trimmed by the linker because they are used by the TypeDescriptor via reflection. Additional conditions: Winforms designer is interested in types derived from IComponent. Property should not be hidden from serializers via SerializerVisibility attribute. Property should be public.

              TypeDescriptor accesses these methods here

              Suggested fix from @ericstj

              The fix is to add a file here runtime/src/libraries/System.Data.Common/src/ILLink at bad00cf23ec49a2607776ffd6e1810c4dbf540b3 · dotnet/runtime (github.com)

              That looks similar to runtime/src/libraries/System.ComponentModel.TypeConverter/src/ILLink/ILLink.Descriptors.LibraryBuild.xml at bad00cf23ec49a2607776ffd6e1810c4dbf540b3 · dotnet/runtime (github.com)

              Search pattern for ShouldSerialize

              Search pattern for Reset

              Searches yeld some false positives if the class is not designable, not an IComponent, or class does not have the public, serializable property, or method is actually called directly. For each property we need to examine metadata in the trimmed assembly to see if the methods were removed.

              Reproduction Steps

              This works on 4.8.1 but doesn't on net6

              usingSystem;usingSystem.ComponentModel;usingSystem.Data;namespaceConsoleApp1{internalclassProgram{staticvoidMain(string[]args){DataColumndataColumn1=newDataColumn{ColumnName="dataColumn1",DataType=typeof(DateTime)};varproperties=TypeDescriptor.GetProperties(dataColumn1);varproperty=properties[nameof(DataColumn.DefaultValue)];if(property!=null){boolshouldSerialize=property.ShouldSerializeValue(dataColumn1);Console.WriteLine($"ShouldSerialize default? expected {false} actual {shouldSerialize}");dataColumn1.DefaultValue=DateTime.MinValue;shouldSerialize=property.ShouldSerializeValue(dataColumn1);Console.WriteLine($"ShouldSerialize changed? expected {true} actual {shouldSerialize}");// Reset method is not availableproperty.ResetValue(dataColumn1);Console.WriteLine($"Reset? expected {DateTime.MinValue} actual {dataColumn1.DefaultValue}");}property=properties[nameof(DataColumn.Caption)];if(property!=null){boolshouldSerialize=property.ShouldSerializeValue(dataColumn1);Console.WriteLine($"ShouldSerialize default? expected {false} actual {shouldSerialize}");dataColumn1.Caption="Caption";shouldSerialize=property.ShouldSerializeValue(dataColumn1);Console.WriteLine($"ShouldSerialize changed? expected {true} actual {shouldSerialize}");// Reset method is availableproperty.ResetValue(dataColumn1);Console.WriteLine($"Reset? expected {nameof(dataColumn1)} actual {dataColumn1.Caption}");}property=properties[nameof(DataColumn.Namespace)];if(property!=null){boolshouldSerialize=property.ShouldSerializeValue(dataColumn1);Console.WriteLine($"ShouldSerialize default? expected {false} actual {shouldSerialize}");dataColumn1.Namespace="Namespace";shouldSerialize=property.ShouldSerializeValue(dataColumn1);Console.WriteLine($"ShouldSerialize changed? expected {true} actual {shouldSerialize}");// Reset method is availableproperty.ResetValue(dataColumn1);Console.WriteLine($"Reset? expected '' actual `{dataColumn1.Namespace}`");}_=Console.ReadLine();}}}

              Expected behavior

              ShouldSerialize, Reset methods are present in the assembly

              Actual behavior

              ShouldSerialize, Reset methods are trimmed

              Regression?

              The end scenario regressed between the InProc and OOP designers.

              Known Workarounds

              none

              Configuration

              WIndows

              Other information

              Trimmed ShouldSerialize causes serialization using BinaryFormatter. The fix should be serviced.

              Metadata

              Metadata

              Assignees

              Type

              No type

              Projects

              No projects

                Milestone

                Relationships

                None yet

                Development

                No branches or pull requests

                Issue actions

                , 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
                Skip to content

                Do not trim private methods used by the designer #102244

                Description

                @Tanya-Solyanik

                Description

                Copied from dotnet/winforms#11314

                Private methods whose names follow the pattern ShouldSerialize<PropertyName> or Reset<ProppertyName> should not be trimmed by the linker because they are used by the TypeDescriptor via reflection. Additional conditions: Winforms designer is interested in types derived from IComponent. Property should not be hidden from serializers via SerializerVisibility attribute. Property should be public.

                TypeDescriptor accesses these methods here

                Suggested fix from @ericstj

                The fix is to add a file here runtime/src/libraries/System.Data.Common/src/ILLink at bad00cf23ec49a2607776ffd6e1810c4dbf540b3 · dotnet/runtime (github.com)

                That looks similar to runtime/src/libraries/System.ComponentModel.TypeConverter/src/ILLink/ILLink.Descriptors.LibraryBuild.xml at bad00cf23ec49a2607776ffd6e1810c4dbf540b3 · dotnet/runtime (github.com)

                Search pattern for ShouldSerialize

                Search pattern for Reset

                Searches yeld some false positives if the class is not designable, not an IComponent, or class does not have the public, serializable property, or method is actually called directly. For each property we need to examine metadata in the trimmed assembly to see if the methods were removed.

                Reproduction Steps

                This works on 4.8.1 but doesn't on net6

                usingSystem;usingSystem.ComponentModel;usingSystem.Data;namespaceConsoleApp1{internalclassProgram{staticvoidMain(string[]args){DataColumndataColumn1=newDataColumn{ColumnName="dataColumn1",DataType=typeof(DateTime)};varproperties=TypeDescriptor.GetProperties(dataColumn1);varproperty=properties[nameof(DataColumn.DefaultValue)];if(property!=null){boolshouldSerialize=property.ShouldSerializeValue(dataColumn1);Console.WriteLine($"ShouldSerialize default? expected {false} actual {shouldSerialize}");dataColumn1.DefaultValue=DateTime.MinValue;shouldSerialize=property.ShouldSerializeValue(dataColumn1);Console.WriteLine($"ShouldSerialize changed? expected {true} actual {shouldSerialize}");// Reset method is not availableproperty.ResetValue(dataColumn1);Console.WriteLine($"Reset? expected {DateTime.MinValue} actual {dataColumn1.DefaultValue}");}property=properties[nameof(DataColumn.Caption)];if(property!=null){boolshouldSerialize=property.ShouldSerializeValue(dataColumn1);Console.WriteLine($"ShouldSerialize default? expected {false} actual {shouldSerialize}");dataColumn1.Caption="Caption";shouldSerialize=property.ShouldSerializeValue(dataColumn1);Console.WriteLine($"ShouldSerialize changed? expected {true} actual {shouldSerialize}");// Reset method is availableproperty.ResetValue(dataColumn1);Console.WriteLine($"Reset? expected {nameof(dataColumn1)} actual {dataColumn1.Caption}");}property=properties[nameof(DataColumn.Namespace)];if(property!=null){boolshouldSerialize=property.ShouldSerializeValue(dataColumn1);Console.WriteLine($"ShouldSerialize default? expected {false} actual {shouldSerialize}");dataColumn1.Namespace="Namespace";shouldSerialize=property.ShouldSerializeValue(dataColumn1);Console.WriteLine($"ShouldSerialize changed? expected {true} actual {shouldSerialize}");// Reset method is availableproperty.ResetValue(dataColumn1);Console.WriteLine($"Reset? expected '' actual `{dataColumn1.Namespace}`");}_=Console.ReadLine();}}}

                Expected behavior

                ShouldSerialize, Reset methods are present in the assembly

                Actual behavior

                ShouldSerialize, Reset methods are trimmed

                Regression?

                The end scenario regressed between the InProc and OOP designers.

                Known Workarounds

                none

                Configuration

                WIndows

                Other information

                Trimmed ShouldSerialize causes serialization using BinaryFormatter. The fix should be serviced.

                Metadata

                Metadata

                Assignees

                Type

                No type

                Projects

                No projects

                  Milestone

                  Relationships

                  None yet

                  Development

                  No branches or pull requests

                  Issue actions