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

Inheriting from CustomType and retaining type on object cloning #193

Closed
rmja opened this issue Oct 8, 2019 · 2 comments
Closed

Inheriting from CustomType and retaining type on object cloning #193

rmja opened this issue Oct 8, 2019 · 2 comments

Comments

@rmja
Copy link
Contributor

rmja commented Oct 8, 2019

I am exposing a few types inheriting from CustomType, for example:

    public class SampleObject : CustomType
    {
        public Sample Sample => (Sample)Value;

        public SampleObject(Sample sample)
        {
            Value = sample;
        }

        protected override JSValue GetProperty(JSValue key, bool forWrite, PropertyScope propertyScope)
        {
            if (key.Value is string propertyName)
            {
                switch (propertyName)
                {
                    case "registerId": return Sample.Register.Id;
                    ...
                    case "unitId": return Sample.Unit.Id;
                }
            }
            return Undefined;
        }

Now consider the following example:

getSample().registerId

This correctly invokes the GetProperty method on SampleObject as this is the returned type from getSample(). However, if I assign the result from getSample() to an intermediate variable, then the value get cloned, and the new instance becomes of type JSValue because a new instance in created:

internal virtual JSValue CloneImpl(bool force, JSValueAttributesInternal resetMask)
{
if (!force && (_attributes & JSValueAttributesInternal.Cloned) != 0)
{
_attributes &= ~(JSValueAttributesInternal.Cloned | resetMask);
return this;
}
var res = new JSValue();
res.Assign(this);
res._attributes = this._attributes & ~resetMask;
return res;
}

So, when accessing properties on this cloned instance (for example after variable assignment), then accessing the property throws:

const sample = getSample();
sample.registerId; // this throws with "Method GetProperty(...) of custom types must be overridden"

CloneImpl() is internal and so it is not possible to override it so that the returned instance on cloning becomes of the same type as the original returned instance.

How does one inherit from CustomType and make sure that this type propagate on object cloning?

@nilproject
Copy link
Owner

Do not override property Value and content of this property. When you assign result of getSample() to variable, you get a raw instance of Sample without proxy, not SampleObject. Value must contains this. It is how works mechanism of variables.

Also, for cases, when property is unknown is more correct to return NotExistsInObject. This is matter for operators like in and delete.

Yet another "also": CustomType is not required for custom types. You can inherit JSValue directly. Look at this example. CustomType is kind of sugar.

@rmja
Copy link
Contributor Author

rmja commented Oct 9, 2019

Ahh, perfect! https://github.com/nilproject/NiL.JS/blob/version-2.5/Examples/5.%20Namespaces%20and%20external%20types/Extend%20JSValue.cs was a good example that I should have seen a long time ago. And a good point with NotExistsInObject. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants