Announcement

Collapse
No announcement yet.

[CLOSED] [#3224] Parent object incorrectly initialized

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

    [CLOSED] [#3224] Parent object incorrectly initialized

    Hey Guys,

    This one is a little tricky in that I have a case where when I compile from C# to JS locally using Bridge.net version 16.4.1 from nuget (to be referred to as "Locally") I get different result when compared to using deck.net online also using Bridge.net version 16.4.1 (to be referred to as "Online").

    The attached sample when run online outputs "Test" to the console where as locally I get "null".

    In the generated JS on the line
    System.Console.WriteLine(result.IChild$StringField);
    the value of
    result.IChild$StringField
    is null yet if I inspect result I can see that
    result.StringField
    has the value "Test".

    Stepping through the resulting JS it appears that when parent is created Online it does have "Class.$ctor" and runs it where as Locally Class.$ctor is null (and therefore not run). This is on line 2528 in bridge.js. If have tried using the bridge.min.js version and I get the same result.

    As best as I can tell the bridge.min.js, ClassLibrary1.js and the meta js files are identical between Online and Locally. Due to the Online version only having the minified version I have not been able to debug any further.

    In the repro case below I have drastically simplified from the code I had when I found this issue. I am hoping this will help in sorting out what the issue is.

    I will continue to look to see if I can find the cause, unless someone else gets there first.

    Thanks for your time.

    Source C#

    https://deck.net/5bae69505350b04aec853a54051b7c95

    using System;
    using System.Collections.Generic;
    
    public interface IParent
    {
        List<IChild> Children { get; set; }
    }
    
    public class Parent : IParent
    {
        public List<IChild> Children { get; set; }
    }
    
    public interface IChild
    {
        string StringField { get; }
    }
    
    public class Child : IChild
    {
        public string StringField { get; set; }
    }
    
    public class Program
    {
        public static void Main()
        {
            var parent = new Parent();
            var child = new Child();
            child.StringField = "Test";
    
            parent.Children = new List<IChild>();
            parent.Children.Add(child);
    
            var result = parent.Children[0];
    
            Console.WriteLine(result.StringField);
        }
    }
    Locally Generated JS
    /**
     * @version 1.0.0.0
     * @copyright Copyright ©  2017
     * @compiler Bridge.NET 16.4.1
     */
    Bridge.assembly("ClassLibrary1", function ($asm, globals) {
        "use strict";
    
        Bridge.define("IChild", {
            $kind: "interface"
        });
    
        Bridge.define("IParent", {
            $kind: "interface"
        });
    
        Bridge.define("Program", {
            main: function Main () {
                var parent = new Parent();
                var child = new Child();
                child.StringField = "Test";
    
                parent.Children = new (System.Collections.Generic.List$1(IChild)).ctor();
                parent.Children.add(child);
    
                var result = parent.Children.getItem(0);
    
                System.Console.WriteLine(result.IChild$StringField);
            }
        });
    
        Bridge.define("Child", {
            inherits: [IChild],
            fields: {
                StringField: null
            },
            alias: ["StringField", "IChild$StringField"]
        });
    
        Bridge.define("Parent", {
            inherits: [IParent],
            fields: {
                Children: null
            },
            alias: ["Children", "IParent$Children"]
        });
    });
    
    //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAiZmlsZSI6ICJDbGFzc0xpYnJhcnkxLmpzIiwKICAic291cmNlUm9vdCI6ICIiLAogICJzb3VyY2VzIjogWyJDbGFzczEuY3MiXSwKICAibmFtZXMiOiBbIiJdLAogICJtYXBwaW5ncyI6ICI7Ozs7Ozs7Ozs7Ozs7Ozs7OztZQTJCRUEsYUFBYUEsSUFBSUE7WUFDakJBLFlBQVlBLElBQUlBO1lBQ2hCQTs7WUFFQUEsa0JBQWtCQSxLQUFJQTtZQUN0QkEsb0JBQW9CQTs7WUFFcEJBLGFBQWFBOztZQUViQSx5QkFBa0JBIiwKICAic291cmNlc0NvbnRlbnQiOiBbInVzaW5nIFN5c3RlbTtcclxudXNpbmcgU3lzdGVtLkNvbGxlY3Rpb25zLkdlbmVyaWM7XHJcblxyXG5wdWJsaWMgaW50ZXJmYWNlIElQYXJlbnRcclxue1xyXG5cdExpc3Q8SUNoaWxkPiBDaGlsZHJlbiB7IGdldDsgc2V0OyB9XHJcbn1cclxuXHJcbnB1YmxpYyBjbGFzcyBQYXJlbnQgOiBJUGFyZW50XHJcbntcclxuXHRwdWJsaWMgTGlzdDxJQ2hpbGQ+IENoaWxkcmVuIHsgZ2V0OyBzZXQ7IH1cclxufVxyXG5cclxucHVibGljIGludGVyZmFjZSBJQ2hpbGRcclxue1xyXG5cdHN0cmluZyBTdHJpbmdGaWVsZCB7IGdldDsgcHJpdmF0ZSBzZXQ7IH1cclxufVxyXG5cclxucHVibGljIGNsYXNzIENoaWxkIDogSUNoaWxkXHJcbntcclxuXHRwdWJsaWMgc3RyaW5nIFN0cmluZ0ZpZWxkIHsgZ2V0OyBzZXQ7IH1cclxufVxyXG5cclxucHVibGljIGNsYXNzIFByb2dyYW1cclxue1xyXG5cdHB1YmxpYyBzdGF0aWMgdm9pZCBNYWluKClcclxuXHR7XHJcblx0XHR2YXIgcGFyZW50ID0gbmV3IFBhcmVudCgpO1xyXG5cdFx0dmFyIGNoaWxkID0gbmV3IENoaWxkKCk7XHJcblx0XHRjaGlsZC5TdHJpbmdGaWVsZCA9IFwiVGVzdFwiO1xyXG5cclxuXHRcdHBhcmVudC5DaGlsZHJlbiA9IG5ldyBMaXN0PElDaGlsZD4oKTtcclxuXHRcdHBhcmVudC5DaGlsZHJlbi5BZGQoY2hpbGQpO1xyXG5cclxuXHRcdHZhciByZXN1bHQgPSBwYXJlbnQuQ2hpbGRyZW5bMF07XHJcblxyXG5cdFx0Q29uc29sZS5Xcml0ZUxpbmUocmVzdWx0LlN0cmluZ0ZpZWxkKTtcclxuXHR9XHJcbn0iXQp9Cg==
    Remote Generated JS
    /**
     * @compiler Bridge.NET 16.4.1
     */
    Bridge.assembly("Demo", function ($asm, globals) {
        "use strict";
    
        Bridge.define("IChild", {
            $kind: "interface"
        });
    
        Bridge.define("IParent", {
            $kind: "interface"
        });
    
        Bridge.define("Program", {
            main: function Main () {
                var parent = new Parent();
                var child = new Child();
                child.StringField = "Test";
    
                parent.Children = new (System.Collections.Generic.List$1(IChild)).ctor();
                parent.Children.add(child);
    
                var result = parent.Children.getItem(0);
    
                System.Console.WriteLine(result.IChild$StringField);
            }
        });
    
        Bridge.define("Child", {
            inherits: [IChild],
            props: {
                StringField: null
            },
            alias: ["StringField", "IChild$StringField"]
        });
    
        Bridge.define("Parent", {
            inherits: [IParent],
            props: {
                Children: null
            },
            alias: ["Children", "IParent$Children"]
        });
    });
    Last edited by geoffrey.mcgill; 2017-11-02 @ 03:18 AM.

    #2
    Hello benbillbob,

    Welcome to the Bridge.NET community forums!

    Thanks for the really excellent post documenting the issue and demonstrating how to reproduce.

    Check your bridge.json config file under the rules section and set the autoProperty value to Managed.

    More info on rules in the docs.

    That might fix the problem, or at least provide a temp work-around, but we will investigate further to figure out why Plain is not working in this case.

    I also added a shared Deck link to your original post.

    Comment


      #3
      Thanks for the quick reply.

      A Deck link would have been a good idea, thanks for adding. I probably should have done a bit more reading through other posts and got the hint.

      I just tested Locally with autoProperty set to Managed and it is now working for me. I will try again with my full project and see how it goes.

      In trying to sort this out I also came up with this exception which is actually replicating both Locally and Online. While this is not going to effect my current project (as I am not using this pattern) I thought it best to at least report it on the of chance it helps identify an issue.

      Comment


        #4
        I did some testing with your initial sample, and there is something strange going on. It might be a defect. We will need to investigate further.

        Your new sample doesn't compile in native C# either. See https://dotnetfiddle.net/Hvob9Z

        Comment


          #5
          Regarding the new sample it does compile if you are compiling with C# 6, new feature, "Getter-only auto-properties", also known as "Auto-Property Initializers for Read-Only Properties". To fix simply add "set;" to the property on line 17 (https://dotnetfiddle.net/kQ8YIA).

          Comment


            #6
            I'm getting the following exception with your new dotnetfiddle sample.

            Run-time exception (line -1): Index was out of range. Must be non-negative and less than the size of the collection.
            Parameter name: index
            
            Stack Trace:
            
            [System.ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection.
            Parameter name: index]
               at System.ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument argument, ExceptionResource resource)
               at System.Collections.Generic.List`1.get_Item(Int32 index)
               at Program.Main()

            Comment


              #7
              Whoops, that one is totally on me (parent.Children.Add(child) actually does nothing as the list it adds too is immediately lost). Sorry for wasting your time there.

              Regarding the original issue I can say that setting autoProperty to Managed works for me so I will proceed with that.

              Though I am guessing there is something going on with why Plain isn't working.

              Comment


                #8
                Your original sample appears to be working correctly with the Bridge 16.5.0 release.

                When you get a chance to upgrade to 16.5.0, please confirm.

                It appears the fix occurred in Issue #3224.
                Last edited by geoffrey.mcgill; 2017-11-12 @ 07:16 AM.

                Comment

                Working...
                X