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); }
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()); }
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); }
/// <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); }
internal static JsString ToJsString(JsValue o) { if (o is JsString s) { return(s); } return(JsString.Create(ToStringNonString(o))); }
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 })); }
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); }
private PropertyDescriptor GetProperty(uint index) { var prop = GetOwnProperty(index); if (prop != PropertyDescriptor.Undefined) { return(prop); } return(Prototype?.GetProperty(JsString.Create(index)) ?? PropertyDescriptor.Undefined); }
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))); }
internal JsValue Get(uint index) { var prop = GetOwnProperty(index); if (prop == PropertyDescriptor.Undefined) { prop = Prototype?.GetProperty(JsString.Create(index)) ?? PropertyDescriptor.Undefined; } return(UnwrapJsValue(prop)); }
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)); }
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)); }
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); }
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())); }
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())); } }
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))); }
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 })); }
/// <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))); }
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); } } }
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)); }
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); }
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)); }
public StringInstance Construct(string value) { return(Construct(JsString.Create(value))); }
public BindingName(string value) { Key = (Key)value; StringValue = JsString.Create(value); }