public DomEventInstance(DomNodeInstance node, EventInfo eventInfo)
        {
            Getter = new ClrFunctionInstance(node.Engine, (thisObject, arguments) => _function ?? JsValue.Null);
            Setter = new ClrFunctionInstance(node.Engine, (thisObject, arguments) =>
            {
                if (_handler != null)
                {
                    eventInfo.RemoveEventHandler(node.Value, _handler);
                    _handler = null;
                    _function = null;
                }

                if (arguments[0].Is<FunctionInstance>())
                {
                    _function = arguments[0].As<FunctionInstance>();
                    _handler = (s, ev) => 
                    {
                        var sender = s.ToJsValue(node.Context);
                        var args = ev.ToJsValue(node.Context);
                        _function.Call(sender, new [] { args });
                    };
                    eventInfo.AddEventHandler(node.Value, _handler);
                }

                return arguments[0];
            });
        }
Exemplo n.º 2
0
        public override PropertyDescriptor GetOwnProperty(JsValue property)
        {
            if (TryGetProperty(property, out var x))
            {
                return(x);
            }

            // if we have array-like or dictionary or expando, we can provide iterator
            if (property.IsSymbol() && property == GlobalSymbolRegistry.Iterator && _typeDescriptor.Iterable)
            {
                var iteratorFunction = new ClrFunctionInstance(
                    Engine,
                    "iterator",
                    Iterator,
                    1,
                    PropertyFlag.Configurable);

                var iteratorProperty = new PropertyDescriptor(iteratorFunction, PropertyFlag.Configurable | PropertyFlag.Writable);
                SetProperty(GlobalSymbolRegistry.Iterator, iteratorProperty);
                return(iteratorProperty);
            }

            var member = property.ToString();

            // if type is dictionary, we cannot enumerate anything other than keys
            // and we cannot store accessors as dictionary can change dynamically

            var isDictionary = _typeDescriptor.IsStringKeyedGenericDictionary;

            if (isDictionary)
            {
                if (_typeDescriptor.TryGetValue(Target, member, out var value))
                {
                    return(new PropertyDescriptor(FromObject(_engine, value), PropertyFlag.OnlyEnumerable));
                }
            }

            var result = Engine.Options.Interop.MemberAccessor(Engine, Target, member);

            if (result is not null)
            {
                return(new PropertyDescriptor(result, PropertyFlag.OnlyEnumerable));
            }

            var accessor   = _engine.Options.Interop.TypeResolver.GetAccessor(_engine, Target.GetType(), member);
            var descriptor = accessor.CreatePropertyDescriptor(_engine, Target, enumerable: !isDictionary);

            if (!isDictionary)
            {
                SetProperty(member, descriptor);
            }
            return(descriptor);
        }
Exemplo n.º 3
0
 public ObjectWrapper(Engine engine, object obj)
     : base(engine)
 {
     Target          = obj;
     _typeDescriptor = TypeDescriptor.Get(obj.GetType());
     if (_typeDescriptor.LengthProperty is not null)
     {
         // create a forwarder to produce length from Count or Length if one of them is present
         var functionInstance = new ClrFunctionInstance(engine, "length", GetLength);
         var descriptor       = new GetSetPropertyDescriptor(functionInstance, Undefined, PropertyFlag.Configurable);
         SetProperty(KnownKeys.Length, descriptor);
     }
 }
Exemplo n.º 4
0
        public ObjectWrapper(Engine engine, object obj)
            : base(engine)
        {
            Target = obj;
            var type = obj.GetType();

            if (ObjectIsArrayLikeClrCollection(type))
            {
                // create a forwarder to produce length from Count or Length if one of them is present
                var lengthProperty = type.GetProperty("Count") ?? type.GetProperty("Length");
                if (lengthProperty is null)
                {
                    return;
                }
                IsArrayLike = true;

                var functionInstance = new ClrFunctionInstance(engine, "length", (thisObj, arguments) => JsNumber.Create((int)lengthProperty.GetValue(obj)));
                var descriptor       = new GetSetPropertyDescriptor(functionInstance, Undefined, PropertyFlag.Configurable);
                SetProperty(KnownKeys.Length, descriptor);
            }
        }
Exemplo n.º 5
0
        private JsValue Replace(JsValue thisObj, JsValue[] arguments)
        {
            TypeConverter.CheckObjectCoercible(Engine, thisObj);

            var thisString = TypeConverter.ToString(thisObj);
            var searchValue = arguments.At(0);
            var replaceValue = arguments.At(1);

            // If the second parameter is not a function we create one
            var replaceFunction = replaceValue.TryCast<FunctionInstance>();
            if (replaceFunction == null)
            {
                replaceFunction = new ClrFunctionInstance(Engine, (self, args) =>
                {
                    var replaceString = TypeConverter.ToString(replaceValue);
                    var matchValue = TypeConverter.ToString(args.At(0));
                    var matchIndex = (int)TypeConverter.ToInteger(args.At(args.Length - 2));

                    // Check if the replacement string contains any patterns.
                    bool replaceTextContainsPattern = replaceString.IndexOf('$') >= 0;

                    // If there is no pattern, replace the pattern as is.
                    if (replaceTextContainsPattern == false)
                        return replaceString;

                    // Patterns
                    // $$	Inserts a "$".
                    // $&	Inserts the matched substring.
                    // $`	Inserts the portion of the string that precedes the matched substring.
                    // $'	Inserts the portion of the string that follows the matched substring.
                    // $n or $nn	Where n or nn are decimal digits, inserts the nth parenthesized submatch string, provided the first argument was a RegExp object.
                    var replacementBuilder = new StringBuilder();
                    for (int i = 0; i < replaceString.Length; i++)
                    {
                        char c = replaceString[i];
                        if (c == '$' && i < replaceString.Length - 1)
                        {
                            c = replaceString[++i];
                            if (c == '$')
                                replacementBuilder.Append('$');
                            else if (c == '&')
                                replacementBuilder.Append(matchValue);
                            else if (c == '`')
                                replacementBuilder.Append(thisString.Substring(0, matchIndex));
                            else if (c == '\'')
                                replacementBuilder.Append(thisString.Substring(matchIndex + matchValue.Length));
                            else if (c >= '0' && c <= '9')
                            {
                                int matchNumber1 = c - '0';

                                // The match number can be one or two digits long.
                                int matchNumber2 = 0;
                                if (i < replaceString.Length - 1 && replaceString[i + 1] >= '0' && replaceString[i + 1] <= '9')
                                    matchNumber2 = matchNumber1 * 10 + (replaceString[i + 1] - '0');

                                // Try the two digit capture first.
                                if (matchNumber2 > 0 && matchNumber2 < args.Length - 2)
                                {
                                    // Two digit capture replacement.
                                    replacementBuilder.Append(TypeConverter.ToString(args[matchNumber2]));
                                    i++;
                                }
                                else if (matchNumber1 > 0 && matchNumber1 < args.Length - 2)
                                {
                                    // Single digit capture replacement.
                                    replacementBuilder.Append(TypeConverter.ToString(args[matchNumber1]));
                                }
                                else
                                {
                                    // Capture does not exist.
                                    replacementBuilder.Append('$');
                                    i--;
                                }
                            }
                            else
                            {
                                // Unknown replacement pattern.
                                replacementBuilder.Append('$');
                                replacementBuilder.Append(c);
                            }
                        }
                        else
                            replacementBuilder.Append(c);
                    }

                    return replacementBuilder.ToString();
                });
            }

            // searchValue is a regular expression

            if (searchValue.IsNull()) 
            {
                searchValue = new JsValue(Null.Text);
            }
            if (searchValue.IsUndefined())
            {
                searchValue = new JsValue(Undefined.Text);
            }
            
            var rx = TypeConverter.ToObject(Engine, searchValue) as RegExpInstance;
            if (rx != null)
            {
                // Replace the input string with replaceText, recording the last match found.
                string result = rx.Value.Replace(thisString, match =>
                {
                    var args = new List<JsValue>();
                    
                    for (var k = 0; k < match.Groups.Count; k++)
                    {
                        var group = match.Groups[k];
                        args.Add(group.Value);
                    }
                    
                    args.Add(match.Index);
                    args.Add(thisString);

                    var v = TypeConverter.ToString(replaceFunction.Call(Undefined.Instance, args.ToArray()));
                    return v;
                }, rx.Global == true ? -1 : 1);

                // Set the deprecated RegExp properties if at least one match was found.
                //if (lastMatch != null)
                //    this.Engine.RegExp.SetDeprecatedProperties(input, lastMatch);

                return result;
            }

            // searchValue is a string
            else
            {
                var substr = TypeConverter.ToString(searchValue);

                // Find the first occurrance of substr.
                int start = thisString.IndexOf(substr, StringComparison.Ordinal);
                if (start == -1)
                    return thisString;
                int end = start + substr.Length;

                var args = new List<JsValue>();
                args.Add(substr);
                args.Add(start);
                args.Add(thisString);

                var replaceString = TypeConverter.ToString(replaceFunction.Call(Undefined.Instance, args.ToArray()));

                // Replace only the first match.
                var result = new StringBuilder(thisString.Length + (substr.Length - substr.Length));
                result.Append(thisString, 0, start);
                result.Append(replaceString);
                result.Append(thisString, end, thisString.Length - end);
                return result.ToString();
            }
        }
Exemplo n.º 6
0
 public MethodInfoFunctionInstance(Engine engine, MethodDescriptor[] methods, ClrFunctionInstance fallbackClrFunctionInstance)
     : this(engine, methods)
 {
     _fallbackClrFunctionInstance = fallbackClrFunctionInstance;
 }