internal static JsValue ConvertToJsValue(Literal literal)
        {
            if (literal.TokenType == TokenType.BooleanLiteral)
            {
                return(literal.NumericValue > 0.0 ? JsBoolean.True : JsBoolean.False);
            }

            if (literal.TokenType == TokenType.NullLiteral)
            {
                return(JsValue.Null);
            }

            if (literal.TokenType == TokenType.NumericLiteral)
            {
                var intValue = (int)literal.NumericValue;
                return(literal.NumericValue == intValue &&
                       (intValue != 0 || BitConverter.DoubleToInt64Bits(literal.NumericValue) != JsNumber.NegativeZeroBits)
                    ? JsNumber.Create(intValue)
                    : JsNumber.Create(literal.NumericValue));
            }

            if (literal.TokenType == TokenType.StringLiteral)
            {
                return(JsString.Create((string)literal.Value));
            }

            return(null);
        }
Example #2
0
    public void ShouldAddModuleFromJsValue()
    {
        _engine.AddModule("my-module", builder => builder.ExportValue("value", JsString.Create("hello world")));
        var ns = _engine.ImportModule("my-module");

        Assert.Equal("hello world", ns.Get("value").AsString());
    }
Example #3
0
        public override List <JsValue> GetOwnPropertyKeys(Types types)
        {
            var properties = new List <JsValue>(_dense?.Length ?? 0 + 1);

            if (_dense != null)
            {
                var length = System.Math.Min(_dense.Length, GetLength());
                for (var i = 0; i < length; i++)
                {
                    if (_dense[i] != null)
                    {
                        properties.Add(JsString.Create(i));
                    }
                }
            }
            else
            {
                foreach (var entry in _sparse)
                {
                    properties.Add(JsString.Create(entry.Key));
                }
            }

            if (_length != null)
            {
                properties.Add(CommonProperties.Length);
            }

            properties.AddRange(base.GetOwnPropertyKeys(types));

            return(properties);
        }
Example #4
0
        /// <summary>
        /// https://tc39.es/ecma262/#sec-string-constructor-string-value
        /// </summary>
        ObjectInstance IConstructor.Construct(JsValue[] arguments, JsValue newTarget)
        {
            JsString s;

            if (arguments.Length == 0)
            {
                s = JsString.Empty;
            }
            else
            {
                var value = arguments.At(0);
                if (newTarget.IsUndefined() && value.IsSymbol())
                {
                    return(StringCreate(JsString.Create(((JsSymbol)value).ToString()), PrototypeObject));
                }
                s = TypeConverter.ToJsString(arguments[0]);
            }

            if (newTarget.IsUndefined())
            {
                return(StringCreate(s, PrototypeObject));
            }

            return(StringCreate(s, GetPrototypeFromConstructor(newTarget, static intrinsics => intrinsics.String.PrototypeObject)));
        }
        private JsValue Of(JsValue thisObj, JsValue[] arguments)
        {
            var            len = arguments.Length;
            ObjectInstance a;

            if (thisObj.IsConstructor)
            {
                a = ((IConstructor)thisObj).Construct(new JsValue[] { len }, thisObj);

                for (uint k = 0; k < arguments.Length; k++)
                {
                    var kValue = arguments[k];
                    var key    = JsString.Create(k);
                    a.CreateDataPropertyOrThrow(key, kValue);
                }

                a.Set(CommonProperties.Length, len, true);
            }
            else
            {
                // faster for real arrays
                ArrayInstance ai;
                a = ai = _engine.Array.Construct(len);

                for (uint k = 0; k < arguments.Length; k++)
                {
                    var kValue = arguments[k];
                    ai.SetIndexValue(k, kValue, updateLength: false);
                }

                ai.SetLength((uint)arguments.Length);
            }

            return(a);
        }
Example #6
0
 internal static JsString ToJsString(JsValue o)
 {
     if (o is JsString s)
     {
         return(s);
     }
     return(JsString.Create(ToStringNonString(o)));
 }
Example #7
0
        private JsValue AbstractWalkOperation(ObjectInstance thisObject, JsValue prop)
        {
            JsValue value = thisObject.Get(prop, thisObject);

            if (value.IsObject())
            {
                var valueAsObject = value.AsObject();
                if (valueAsObject.Class == ObjectClass.Array)
                {
                    var valAsArray = value.AsArray();
                    var i          = 0;
                    var arrLen     = valAsArray.GetLength();
                    while (i < arrLen)
                    {
                        var newValue = AbstractWalkOperation(valAsArray, JsString.Create(i));
                        if (newValue.IsUndefined())
                        {
                            valAsArray.Delete(JsString.Create(i));
                        }
                        else
                        {
                            valAsArray.DefineOwnProperty
                            (
                                JsString.Create(i),
                                new PropertyDescriptor
                                (
                                    value: newValue,
                                    PropertyFlag.ConfigurableEnumerableWritable
                                ));
                        }
                        i = i + 1;
                    }
                }
                else
                {
                    var keys = valueAsObject.GetOwnProperties();
                    foreach (var p in keys)
                    {
                        var newElement = AbstractWalkOperation(valueAsObject, p.Key);
                        if (newElement.IsUndefined())
                        {
                            valueAsObject.Delete(p.Key);
                        }
                        else
                        {
                            valueAsObject.DefineOwnProperty(
                                p.Key,
                                new PropertyDescriptor
                                (
                                    value: newElement,
                                    PropertyFlag.ConfigurableEnumerableWritable
                                ));
                        }
                    }
                }
            }
            return(_reviver.Invoke(thisObject, new[] { prop, value }));
        }
Example #8
0
    public void ShouldAllowInvokeUserDefinedClass()
    {
        _engine.AddModule("user", "export class UserDefined { constructor(v) { this._v = v; } hello(c) { return `hello ${this._v}${c}`; } }");
        var ctor     = _engine.ImportModule("user").Get("UserDefined");
        var instance = _engine.Construct(ctor, JsString.Create("world"));
        var result   = instance.GetMethod("hello").Call(instance, JsString.Create("!"));

        Assert.Equal("hello world!", result);
    }
            public override bool TryGetValue(ulong index, out JsValue value)
            {
                var propertyName = JsString.Create(index);
                var property     = _target.GetProperty(propertyName);
                var kPresent     = property != PropertyDescriptor.Undefined;

                value = kPresent ? _target.UnwrapJsValue(property) : JsValue.Undefined;
                return(kPresent);
            }
        private JsValue From(JsValue thisObj, JsValue[] arguments)
        {
            var source      = arguments.At(0);
            var mapFunction = arguments.At(1);
            var callable    = !mapFunction.IsUndefined() ? GetCallable(mapFunction) : null;
            var thisArg     = arguments.At(2);

            if (source.IsNullOrUndefined())
            {
                ExceptionHelper.ThrowTypeError(_engine, "Cannot convert undefined or null to object");
            }

            if (source is JsString jsString)
            {
                var a = _engine.Array.ConstructFast((uint)jsString.Length);
                for (int i = 0; i < jsString._value.Length; i++)
                {
                    a.SetIndexValue((uint)i, JsString.Create(jsString._value[i]), updateLength: false);
                }
                return(a);
            }

            if (thisObj.IsNull() || !(source is ObjectInstance objectInstance))
            {
                return(_engine.Array.ConstructFast(0));
            }

            if (objectInstance is IObjectWrapper wrapper && wrapper.Target is IEnumerable enumerable)
            {
                return(ConstructArrayFromIEnumerable(enumerable));
            }

            if (objectInstance.IsArrayLike)
            {
                return(ConstructArrayFromArrayLike(thisObj, objectInstance, callable, thisArg));
            }

            ObjectInstance instance;

            if (thisObj is IConstructor constructor)
            {
                instance = constructor.Construct(System.Array.Empty <JsValue>(), thisObj);
            }
            else
            {
                instance = _engine.Array.ConstructFast(0);
            }

            if (objectInstance.TryGetIterator(_engine, out var iterator))
            {
                var protocol = new ArrayProtocol(_engine, thisArg, instance, iterator, callable);
                protocol.Execute();
            }

            return(instance);
        }
Example #11
0
        private PropertyDescriptor GetProperty(uint index)
        {
            var prop = GetOwnProperty(index);

            if (prop != PropertyDescriptor.Undefined)
            {
                return(prop);
            }
            return(Prototype?.GetProperty(JsString.Create(index)) ?? PropertyDescriptor.Undefined);
        }
Example #12
0
        protected override void Initialize()
        {
            _canReturnToPool = false;
            var args = _args;

            DefinePropertyOrThrow(CommonProperties.Length, new PropertyDescriptor(_args.Length, PropertyFlag.NonEnumerable));

            if (_func is null)
            {
                // unmapped
                ParameterMap = null;

                for (uint i = 0; i < (uint)args.Length; i++)
                {
                    var val = args[i];
                    CreateDataProperty(JsString.Create(i), val);
                }

                DefinePropertyOrThrow(CommonProperties.Callee, new GetSetPropertyDescriptor.ThrowerPropertyDescriptor(_engine, PropertyFlag.CustomJsValue));
            }
            else
            {
                ObjectInstance map = null;
                if (args.Length > 0)
                {
                    var mappedNamed = _mappedNamed.Value;
                    mappedNamed.Clear();

                    map = Engine.Realm.Intrinsics.Object.Construct(Arguments.Empty);

                    for (uint i = 0; i < (uint)args.Length; i++)
                    {
                        SetOwnProperty(JsString.Create(i), new PropertyDescriptor(args[i], PropertyFlag.ConfigurableEnumerableWritable));
                        if (i < _names.Length)
                        {
                            var name = _names[i];
                            if (mappedNamed.Add(name))
                            {
                                map.SetOwnProperty(JsString.Create(i), new ClrAccessDescriptor(_env, Engine, name));
                            }
                        }
                    }
                }

                ParameterMap = map;

                // step 13
                DefinePropertyOrThrow(CommonProperties.Callee, new PropertyDescriptor(_func, PropertyFlag.NonEnumerable));
            }

            var iteratorFunction = new ClrFunctionInstance(Engine, "iterator", _engine.Realm.Intrinsics.Array.PrototypeObject.Values, 0, PropertyFlag.Configurable);

            DefinePropertyOrThrow(GlobalSymbolRegistry.Iterator, new PropertyDescriptor(iteratorFunction, PropertyFlag.Writable | PropertyFlag.Configurable));
        }
        private static JsValue FromCharCode(JsValue thisObj, JsValue[] arguments)
        {
            var chars = new char[arguments.Length];

            for (var i = 0; i < chars.Length; i++)
            {
                chars[i] = (char)TypeConverter.ToUint16(arguments[i]);
            }

            return(JsString.Create(new string(chars)));
        }
Example #14
0
        internal JsValue Get(uint index)
        {
            var prop = GetOwnProperty(index);

            if (prop == PropertyDescriptor.Undefined)
            {
                prop = Prototype?.GetProperty(JsString.Create(index)) ?? PropertyDescriptor.Undefined;
            }

            return(UnwrapJsValue(prop));
        }
Example #15
0
        public bool TryGetValue(uint index, out JsValue value)
        {
            value = Undefined;

            if (!TryGetDescriptor(index, out var desc))
            {
                desc = GetProperty(JsString.Create(index));
            }

            return(desc.TryGetValue(this, out value));
        }
Example #16
0
        protected internal override JsValue Call(JsValue thisObject, JsValue[] arguments)
        {
            if (arguments.Length == 0)
            {
                return(JsString.Empty);
            }

            var arg = arguments[0];
            var str = arg is JsSymbol s
                ? s.ToString()
                : TypeConverter.ToString(arg);

            return(JsString.Create(str));
        }
Example #17
0
        public override List <JsValue> GetOwnPropertyKeys(Types types)
        {
            var keys = new List <JsValue>(PrimitiveValue.Length + 1);

            for (uint i = 0; i < PrimitiveValue.Length; ++i)
            {
                keys.Add(JsString.Create(i));
            }

            keys.AddRange(base.GetOwnPropertyKeys(types));
            keys.Sort((v1, v2) => TypeConverter.ToNumber(v1).CompareTo(TypeConverter.ToNumber(v2)));

            keys.Add(JsString.LengthString);

            return(keys);
        }
Example #18
0
        private JsString BuildString(EvaluationContext context)
        {
            using var sb = StringBuilderPool.Rent();
            for (var i = 0; i < _templateLiteralExpression.Quasis.Count; i++)
            {
                var quasi = _templateLiteralExpression.Quasis[i];
                sb.Builder.Append(quasi.Value.Cooked);
                if (i < _expressions.Length)
                {
                    var completion = _expressions[i].GetValue(context);
                    sb.Builder.Append(completion.Value);
                }
            }

            return(JsString.Create(sb.ToString()));
        }
Example #19
0
        private JsString BuildString()
        {
            using (var sb = StringBuilderPool.Rent())
            {
                for (var i = 0; i < _templateLiteralExpression.Quasis.Count; i++)
                {
                    var quasi = _templateLiteralExpression.Quasis[i];
                    sb.Builder.Append(quasi.Value.Cooked);
                    if (i < _expressions.Length)
                    {
                        sb.Builder.Append(_expressions[i].GetValue());
                    }
                }

                return(JsString.Create(sb.ToString()));
            }
        }
Example #20
0
            protected override object EvaluateInternal()
            {
                var left  = _left.GetValue();
                var right = _right.GetValue();

                if (AreIntegerOperands(left, right))
                {
                    return(JsNumber.Create(left.AsInteger() + right.AsInteger()));
                }

                var lprim = TypeConverter.ToPrimitive(left);
                var rprim = TypeConverter.ToPrimitive(right);

                return(lprim.IsString() || rprim.IsString()
                    ? (JsValue)JsString.Create(TypeConverter.ToString(lprim) + TypeConverter.ToString(rprim))
                    : JsNumber.Create(TypeConverter.ToNumber(lprim) + TypeConverter.ToNumber(rprim)));
            }
Example #21
0
        private static JsValue InternalizeJSONProperty(JsValue holder, JsValue name, ICallable reviver)
        {
            JsValue temp = holder.Get(name, holder);

            if (temp is ObjectInstance val)
            {
                if (val.IsArray())
                {
                    var i   = 0UL;
                    var len = TypeConverter.ToLength(val.Get(CommonProperties.Length));
                    while (i < len)
                    {
                        var prop       = JsString.Create(i);
                        var newElement = InternalizeJSONProperty(val, prop, reviver);
                        if (newElement.IsUndefined())
                        {
                            val.Delete(prop);
                        }
                        else
                        {
                            val.CreateDataProperty(prop, newElement);
                        }
                        i = i + 1;
                    }
                }
                else
                {
                    var keys = val.EnumerableOwnPropertyNames(EnumerableOwnPropertyNamesKind.Key);
                    foreach (var p in keys)
                    {
                        var newElement = InternalizeJSONProperty(val, p, reviver);
                        if (newElement.IsUndefined())
                        {
                            val.Delete(p);
                        }
                        else
                        {
                            val.CreateDataProperty(p, newElement);
                        }
                    }
                }
            }

            return(reviver.Call(holder, new[] { name, temp }));
        }
Example #22
0
        /// <summary>
        /// https://tc39.es/ecma262/#sec-string.fromcharcode
        /// </summary>
        private static JsValue FromCharCode(JsValue thisObj, JsValue[] arguments)
        {
            var length = arguments.Length;

            if (length == 0)
            {
                return(JsString.Empty);
            }

            var elements = new char[length];

            for (var i = 0; i < elements.Length; i++)
            {
                var nextCu = TypeConverter.ToUint16(arguments[i]);
                elements[i] = (char)nextCu;
            }

            return(JsString.Create(new string(elements)));
        }
        private JsValue Slice(JsValue thisObj, JsValue[] arguments)
        {
            TypeConverter.CheckObjectCoercible(Engine, thisObj);

            var start = TypeConverter.ToNumber(arguments.At(0));

            if (double.IsNegativeInfinity(start))
            {
                start = 0;
            }
            if (double.IsPositiveInfinity(start))
            {
                return(JsString.Empty);
            }

            var s   = TypeConverter.ToString(thisObj);
            var end = TypeConverter.ToNumber(arguments.At(1));

            if (double.IsPositiveInfinity(end))
            {
                end = s.Length;
            }

            var len      = s.Length;
            var intStart = (int)start;
            var intEnd   = arguments.At(1).IsUndefined() ? len : (int)TypeConverter.ToInteger(end);
            var from     = intStart < 0 ? System.Math.Max(len + intStart, 0) : System.Math.Min(intStart, len);
            var to       = intEnd < 0 ? System.Math.Max(len + intEnd, 0) : System.Math.Min(intEnd, len);
            var span     = System.Math.Max(to - from, 0);

            if (span == 0)
            {
                return(JsString.Empty);
            }

            if (span == 1)
            {
                return(JsString.Create(s[from]));
            }

            return(new JsString(s.Substring(from, span)));
        }
        private JsValue Substring(JsValue thisObj, JsValue[] arguments)
        {
            TypeConverter.CheckObjectCoercible(Engine, thisObj);

            var s     = TypeConverter.ToString(thisObj);
            var start = TypeConverter.ToNumber(arguments.At(0));
            var end   = TypeConverter.ToNumber(arguments.At(1));

            if (double.IsNaN(start) || start < 0)
            {
                start = 0;
            }

            if (double.IsNaN(end) || end < 0)
            {
                end = 0;
            }

            var len      = s.Length;
            var intStart = ToIntegerSupportInfinity(start);

            var intEnd     = arguments.At(1).IsUndefined() ? len : ToIntegerSupportInfinity(end);
            var finalStart = System.Math.Min(len, System.Math.Max(intStart, 0));
            var finalEnd   = System.Math.Min(len, System.Math.Max(intEnd, 0));
            // Swap value if finalStart < finalEnd
            var from   = System.Math.Min(finalStart, finalEnd);
            var to     = System.Math.Max(finalStart, finalEnd);
            var length = to - from;

            if (length == 0)
            {
                return(JsString.Empty);
            }

            if (length == 1)
            {
                return(JsString.Create(s[from]));
            }

            return(new JsString(s.Substring(from, length)));
        }
Example #25
0
        private IEnumerable <JsValue> EnumerateOwnPropertyKeys(Types types)
        {
            var basePropertyKeys = base.GetOwnPropertyKeys(types);
            // prefer object order, add possible other properties after
            var processed = basePropertyKeys.Count > 0 ? new HashSet <JsValue>() : null;

            var includeStrings = (types & Types.String) != 0;

            if (Target is IDictionary dictionary && includeStrings)
            {
                // we take values exposed as dictionary keys only
                foreach (var key in dictionary.Keys)
                {
                    if (_engine.ClrTypeConverter.TryConvert(key, typeof(string), CultureInfo.InvariantCulture, out var stringKey))
                    {
                        var jsString = JsString.Create((string)stringKey);
                        processed?.Add(jsString);
                        yield return(jsString);
                    }
                }
            }
Example #26
0
        public object Apply(JsValue thisObject, JsValue[] arguments)
        {
            if (arguments.Length != 2)
            {
                ExceptionHelper.ThrowArgumentException("Apply has to be called with two arguments.");
            }

            var func     = thisObject.TryCast <ICallable>();
            var thisArg  = arguments[0];
            var argArray = arguments[1];

            if (func is null)
            {
                return(ExceptionHelper.ThrowTypeError <object>(Engine));
            }

            if (argArray.IsNullOrUndefined())
            {
                return(func.Call(thisArg, Arguments.Empty));
            }

            var argArrayObj = argArray.TryCast <ObjectInstance>();

            if (ReferenceEquals(argArrayObj, null))
            {
                ExceptionHelper.ThrowTypeError(Engine);
            }

            var len     = argArrayObj.Get(CommonProperties.Length, argArrayObj);
            var n       = TypeConverter.ToUint32(len);
            var argList = new JsValue[n];

            for (var index = 0; index < n; index++)
            {
                var indexName = TypeConverter.ToString(index);
                var nextArg   = argArrayObj.Get(JsString.Create(indexName), argArrayObj);
                argList[index] = nextArg;
            }
            return(func.Call(thisArg, argList));
        }
Example #27
0
        private JsValue Of(JsValue thisObj, JsValue[] arguments)
        {
            var            len = arguments.Length;
            ObjectInstance a;

            if (thisObj.IsConstructor)
            {
                a = ((IConstructor)thisObj).Construct(new JsValue[] { len }, thisObj);
            }
            else
            {
                a = _realm.Intrinsics.Array.Construct(len);
            }

            if (a is ArrayInstance ai)
            {
                // faster for real arrays
                for (uint k = 0; k < arguments.Length; k++)
                {
                    var kValue = arguments[k];
                    ai.SetIndexValue(k, kValue, updateLength: k == arguments.Length - 1);
                }
            }
            else
            {
                // slower version
                for (uint k = 0; k < arguments.Length; k++)
                {
                    var kValue = arguments[k];
                    var key    = JsString.Create(k);
                    a.CreateDataPropertyOrThrow(key, kValue);
                }

                a.Set(CommonProperties.Length, len, true);
            }

            return(a);
        }
Example #28
0
            protected override ExpressionResult EvaluateInternal(EvaluationContext context)
            {
                var left  = _left.GetValue(context).Value;
                var right = _right.GetValue(context).Value;

                if (context.OperatorOverloadingAllowed &&
                    TryOperatorOverloading(context, left, right, "op_Addition", out var opResult))
                {
                    return(NormalCompletion(JsValue.FromObject(context.Engine, opResult)));
                }

                if (AreIntegerOperands(left, right))
                {
                    return(NormalCompletion(JsNumber.Create((long)left.AsInteger() + right.AsInteger())));
                }

                var     lprim = TypeConverter.ToPrimitive(left);
                var     rprim = TypeConverter.ToPrimitive(right);
                JsValue result;

                if (lprim.IsString() || rprim.IsString())
                {
                    result = JsString.Create(TypeConverter.ToString(lprim) + TypeConverter.ToString(rprim));
                }
                else if (AreNonBigIntOperands(left, right))
                {
                    result = JsNumber.Create(TypeConverter.ToNumber(lprim) + TypeConverter.ToNumber(rprim));
                }
                else
                {
                    AssertValidBigIntArithmeticOperands(context, lprim, rprim);
                    result = JsBigInt.Create(TypeConverter.ToBigInt(lprim) + TypeConverter.ToBigInt(rprim));
                }

                return(NormalCompletion(result));
            }
Example #29
0
 public StringInstance Construct(string value)
 {
     return(Construct(JsString.Create(value)));
 }
Example #30
0
 public BindingName(string value)
 {
     Key         = (Key)value;
     StringValue = JsString.Create(value);
 }