示例#1
0
 private static EcmaPropertyKey GetNameFromMember(IntrinsicMemberAttribute propAttr, MemberInfo member)
 {
     if (propAttr.Symbol != 0)
     {
         return(new EcmaPropertyKey(propAttr.Symbol));
     }
     return(new EcmaPropertyKey(propAttr.Name ?? Regex.Replace(member.Name, "^[A-Z](?=[a-z])", v => v.Value.ToLower())));
 }
示例#2
0
        private void DefineIntrinsicObjectFromType(Type type, IntrinsicObjectAttribute typeAttr)
        {
            int objectIndex = ToValidIndex((Enum)typeAttr.ObjectType);
            Dictionary <EcmaPropertyKey, EcmaPropertyDescriptor> ht = properties[objectIndex];
            SharedObjectHandle handle = new SharedObjectHandle(this.Container.ID, objectIndex);

            if (IsValidReference(typeAttr.Prototype, out SharedObjectHandle protoHandle))
            {
                RuntimeObject thisObj = EnsureObject(objectIndex);
                thisObj.SetPrototypeOf(this.Realm.GetRuntimeObject(protoHandle));
            }
            if (typeAttr.Global)
            {
                globals[typeAttr.Name ?? type.Name] = CreateSharedObjectDescriptor(handle, EcmaPropertyAttributes.Configurable | EcmaPropertyAttributes.Writable);
            }
            foreach (MemberInfo member in type.GetMembers())
            {
                // special handling if the type defines an instrinsic contructor
                // replace the default object created from EnsureWellKnownObject to InstrincFunction
                if (member.HasAttribute(out IntrinsicConstructorAttribute ctorAttr))
                {
                    string ctorName = ctorAttr.Name ?? member.Name;
                    runtimeObjects[objectIndex] = CreateIntrinsicFunction(ctorName, (MethodInfo)member, ctorAttr.SuperClass as Enum, WellKnownObject.Global, ctorName);
                    if (IsValidReference(ctorAttr.Prototype, out SharedObjectHandle p1))
                    {
                        Dictionary <EcmaPropertyKey, EcmaPropertyDescriptor> hp = properties[ToValidIndex((Enum)ctorAttr.Prototype)];
                        ht[WellKnownProperty.Prototype]   = CreateSharedObjectDescriptor(p1, EcmaPropertyAttributes.None);
                        hp[WellKnownProperty.Constructor] = CreateSharedObjectDescriptor(handle, EcmaPropertyAttributes.Configurable | EcmaPropertyAttributes.Writable);
                    }
                    if (ctorAttr.Global)
                    {
                        globals[ctorName] = CreateSharedObjectDescriptor(handle, EcmaPropertyAttributes.DefaultMethodProperty);
                    }
                    continue;
                }

                object[] propAttrs = member.GetCustomAttributes(typeof(IntrinsicMemberAttribute), false);
                if (propAttrs.Length > 0)
                {
                    EcmaValue sharedValue = default;
                    if (member.HasAttribute(out AliasOfAttribute aliasOf) && aliasOf.ObjectType is Enum aliasOfType)
                    {
                        EcmaPropertyKey aliasOfKey = aliasOf.Name != null ? (EcmaPropertyKey)aliasOf.Name : aliasOf.Symbol;
                        if (!properties[ToValidIndex(aliasOfType)].TryGetValue(aliasOfKey, out EcmaPropertyDescriptor descriptor))
                        {
                            // for sake of simplicity the aliased target should be defined on intrinsic object with smaller WellKnownObject enum value
                            // to avoid the need of topological sort
                            throw new InvalidOperationException();
                        }
                        sharedValue = descriptor.Value;
                    }
                    if (sharedValue == default)
                    {
                        switch (member.MemberType)
                        {
                        case MemberTypes.Method:
                            IntrinsicMemberAttribute propAttr = (IntrinsicMemberAttribute)propAttrs[0];
                            EcmaPropertyKey          name     = GetNameFromMember(propAttr, member);
                            string runtimeName = (propAttr.Getter ? "get " : propAttr.Setter ? "set " : "") + (name.IsSymbol ? "[" + name.Symbol.Description + "]" : name.Name);
                            sharedValue = this.Container.Add(CreateIntrinsicFunction(runtimeName, (MethodInfo)member, null, typeAttr.ObjectType as Enum, name)).ToValue();
                            if (propAttr.Overridable)
                            {
                                overridables.Add(new SharedObjectKey(typeAttr.ObjectType, name), sharedValue.ToInt32() & 0xFFFF);
                            }
                            break;

                        case MemberTypes.Field:
                            object fieldValue = ((FieldInfo)member).GetValue(null);
                            sharedValue = IsValidReference(fieldValue, out SharedObjectHandle p1) ? p1.ToValue() : new EcmaValue(fieldValue);
                            break;

                        case MemberTypes.Property:
                            object propertyValue = ((PropertyInfo)member).GetValue(null, null);
                            sharedValue = IsValidReference(propertyValue, out SharedObjectHandle p2) ? p2.ToValue() : new EcmaValue(propertyValue);
                            break;
                        }
                    }
                    foreach (IntrinsicMemberAttribute propAttr in propAttrs)
                    {
                        EcmaPropertyKey name = GetNameFromMember(propAttr, member);
                        if (propAttr.Getter)
                        {
                            DefineIntrinsicAccessorProperty(ht, name, sharedValue, propAttr.Attributes, true);
                        }
                        else if (propAttr.Setter)
                        {
                            DefineIntrinsicAccessorProperty(ht, name, sharedValue, propAttr.Attributes, false);
                        }
                        else if (member.MemberType != MemberTypes.Method)
                        {
                            DefineIntrinsicDataProperty(ht, name, sharedValue, propAttr.Attributes);
                        }
                        else
                        {
                            DefineIntrinsicMethodProperty(ht, name, sharedValue, propAttr.Attributes);
                            if (propAttr.Global)
                            {
                                DefineIntrinsicMethodProperty(globals, name, sharedValue, propAttr.Attributes);
                            }
                        }
                    }
                }
            }
        }