Example #1
0
        private void fillMembers()
        {
            lock (this)
            {
                if (_members != null)
                {
                    return;
                }

                var                tempMembers       = new StringMap <IList <MemberInfo> >();
                string             prewName          = null;
                IList <MemberInfo> temp              = null;
                bool               instanceAttribute = false;
#if (PORTABLE || NETCORE)
                var members = _hostedType.GetTypeInfo().DeclaredMembers
                              .Union(_hostedType.GetRuntimeMethods())
                              .Union(_hostedType.GetRuntimeProperties())
                              .Union(_hostedType.GetRuntimeFields())
                              .Union(_hostedType.GetRuntimeEvents()).ToArray();
#else
                var members = _hostedType.GetMembers();
#endif
                for (int i = 0; i < members.Length; i++)
                {
                    var member = members[i];
                    if (member.IsDefined(typeof(HiddenAttribute), false))
                    {
                        continue;
                    }

                    instanceAttribute = member.IsDefined(typeof(InstanceMemberAttribute), false);

                    if (!IsInstancePrototype && instanceAttribute)
                    {
                        continue;
                    }

                    var property = member as PropertyInfo;
                    if (property != null)
                    {
                        if ((property.GetSetMethod(true) ?? property.GetGetMethod(true)).IsStatic != !(IsInstancePrototype ^ instanceAttribute))
                        {
                            continue;
                        }
                        if ((property.GetSetMethod(true) == null || !property.GetSetMethod(true).IsPublic) &&
                            (property.GetGetMethod(true) == null || !property.GetGetMethod(true).IsPublic))
                        {
                            continue;
                        }

                        var parentProperty = property;
                        while (parentProperty != null &&
                               parentProperty.DeclaringType != typeof(object) &&
                               ((property.GetGetMethod() ?? property.GetSetMethod()).Attributes & MethodAttributes.NewSlot) == 0)
                        {
                            property = parentProperty;
#if (PORTABLE || NETCORE)
                            parentProperty = property.DeclaringType.GetTypeInfo().BaseType?.GetRuntimeProperty(property.Name);
#else
                            parentProperty = property.DeclaringType.GetTypeInfo().BaseType?.GetProperty(property.Name, BindingFlags.Public | BindingFlags.Instance);
#endif
                        }

                        member = property;
                    }

                    if (member is EventInfo &&
                        (!(member as EventInfo).GetAddMethod(true).IsPublic || (member as EventInfo).GetAddMethod(true).IsStatic != !IsInstancePrototype))
                    {
                        continue;
                    }

                    if (member is FieldInfo && (!(member as FieldInfo).IsPublic || (member as FieldInfo).IsStatic != !IsInstancePrototype))
                    {
                        continue;
                    }
#if (PORTABLE || NETCORE)
                    if ((members[i] is TypeInfo) && !(members[i] as TypeInfo).IsPublic)
                    {
                        continue;
                    }
#else
                    if (member is Type && !(member as Type).IsPublic && !(member as Type).IsNestedPublic)
                    {
                        continue;
                    }
#endif
                    var method = member as MethodBase;
                    if (method != null)
                    {
                        if (method.IsStatic != !(IsInstancePrototype ^ instanceAttribute))
                        {
                            continue;
                        }
                        if (!method.IsPublic)
                        {
                            continue;
                        }
                        if (method.DeclaringType == typeof(object) && member.Name == "GetType")
                        {
                            continue;
                        }
                        if (method is ConstructorInfo)
                        {
                            continue;
                        }

                        var parameterTypes = method.GetParameters().Select(x => x.ParameterType).ToArray();
                        if (parameterTypes.Any(x => x.IsByRef))
                        {
                            continue;
                        }

                        if (method.IsVirtual && (method.Attributes & MethodAttributes.NewSlot) == 0)
                        {
                            var parentMethod = method;
                            while (parentMethod != null && parentMethod.DeclaringType != typeof(object) && (method.Attributes & MethodAttributes.NewSlot) == 0)
                            {
                                method = parentMethod;
#if (PORTABLE || NETCORE)
                                parentMethod = method.DeclaringType.GetTypeInfo().BaseType?.GetMethod(method.Name, parameterTypes);
#else
                                parentMethod = method.DeclaringType.BaseType?.GetMethod(method.Name, BindingFlags.Public | BindingFlags.Instance, null, parameterTypes, null);
#endif
                            }
                        }

                        member = method;
                    }

                    var membername = member.Name;
                    if (member.IsDefined(typeof(JavaScriptNameAttribute), false))
                    {
                        var nameOverrideAttribute = member.GetCustomAttributes(typeof(JavaScriptNameAttribute), false).ToArray();
                        membername = (nameOverrideAttribute[0] as JavaScriptNameAttribute).Name;
                    }
                    else
                    {
                        membername = membername[0] == '.' ? membername : membername.Contains(".") ? membername.Substring(membername.LastIndexOf('.') + 1) : membername;

#if (PORTABLE || NETCORE)
                        if (members[i] is TypeInfo && membername.Contains("`"))
#else
                        if (member is Type && membername.Contains('`'))
#endif
                        {
                            membername = membername.Substring(0, membername.IndexOf('`'));
                        }
                    }

                    if (prewName != membername)
                    {
                        if (temp != null && temp.Count > 1)
                        {
                            var type = temp[0].DeclaringType;
                            for (var j = 1; j < temp.Count; j++)
                            {
                                if (type != temp[j].DeclaringType && type.IsAssignableFrom(temp[j].DeclaringType))
                                {
                                    type = temp[j].DeclaringType;
                                }
                            }
                            int offset = 0;
                            for (var j = 1; j < temp.Count; j++)
                            {
                                if (!type.IsAssignableFrom(temp[j].DeclaringType))
                                {
                                    temp.RemoveAt(j--);
                                    tempMembers.Remove(prewName + "$" + (++offset + j));
                                }
                            }
                            if (temp.Count == 1)
                            {
                                tempMembers.Remove(prewName + "$0");
                            }
                        }
                        if (!tempMembers.TryGetValue(membername, out temp))
                        {
                            tempMembers[membername] = temp = new List <MemberInfo>();
                        }
                        prewName = membername;
                    }

                    if (membername.StartsWith("@@"))
                    {
                        if (_symbols == null)
                        {
                            _symbols = new Dictionary <Symbol, JSValue>();
                        }
                        _symbols.Add(Symbol.@for(membername.Substring(2)), proxyMember(false, new[] { member }));
                    }
                    else
                    {
                        if (temp.Count == 1)
                        {
                            tempMembers.Add(membername + "$0", new[] { temp[0] });
                        }

                        temp.Add(member);

                        if (temp.Count != 1)
                        {
                            tempMembers.Add(membername + "$" + (temp.Count - 1), new[] { member });
                        }
                    }
                }

                _members = tempMembers;

                if (IsInstancePrototype)
                {
                    if (typeof(IIterable).IsAssignableFrom(_hostedType))
                    {
                        IList <MemberInfo> iterator = null;
                        if (_members.TryGetValue("iterator", out iterator))
                        {
                            if (_symbols == null)
                            {
                                _symbols = new Dictionary <Symbol, JSValue>();
                            }
                            _symbols.Add(Symbol.iterator, proxyMember(false, iterator));
                            _members.Remove("iterator");
                        }
                    }
#if NET40
                    var toStringTag = _hostedType.GetCustomAttribute <ToStringTagAttribute>();
#else
                    var toStringTag = _hostedType.GetTypeInfo().GetCustomAttribute <ToStringTagAttribute>();
#endif
                    if (toStringTag != null)
                    {
                        if (_symbols == null)
                        {
                            _symbols = new Dictionary <Symbol, JSValue>();
                        }
                        _symbols.Add(Symbol.toStringTag, toStringTag.Tag);
                    }
                }

                if (_indexersSupported)
                {
                    IList <MemberInfo> getter = null;
                    IList <MemberInfo> setter = null;
                    _members.TryGetValue("get_Item", out getter);
                    _members.TryGetValue("set_Item", out setter);

                    if (getter != null || setter != null)
                    {
                        _indexerProperty = new PropertyPair();

                        if (getter != null)
                        {
                            _indexerProperty.getter = (Function)proxyMember(false, getter);
                            _fields["get_Item"]     = _indexerProperty.getter;
                        }

                        if (setter != null)
                        {
                            _indexerProperty.setter = (Function)proxyMember(false, setter);
                            _fields["set_Item"]     = _indexerProperty.setter;
                        }
                    }
                    else
                    {
                        _indexersSupported = false;
                    }
                }
            }
        }