using Esprima.Ast;
using Jint.Constraints;
using Jint.Native;
using Jint.Native.Function;
using Jint.Runtime.Descriptors;
using Jint.Runtime.Interop;
namespace Jint.Tests.PublicInterface;
///
/// Tests related to functionality that RavenDB needs exposed.
///
public class RavenApiUsageTests
{
[Fact]
public void CanBuildCustomScriptFunctionInstance()
{
var engine = new Engine();
var properties = new List
{
new Property(PropertyKind.Init, new Identifier("field"), false,
new StaticMemberExpression(new Identifier("self"), new Identifier("field"), optional: false), false, false)
};
var functionExp = new FunctionExpression(
new Identifier("functionId"),
NodeList.Create(new List { new Identifier("self") }),
new BlockStatement(NodeList.Create(new List { new ReturnStatement(new ObjectExpression(NodeList.Create(properties))) })),
generator: false,
strict: false,
async: false);
var functionObject = new ScriptFunctionInstance(
engine,
functionExp,
engine.CreateNewDeclarativeEnvironment(),
strict: false
);
Assert.NotNull(functionObject);
}
[Fact]
public void CanChangeMaxStatementValue()
{
var engine = new Engine(options => options.MaxStatements(123));
var constraint = engine.FindConstraint();
Assert.NotNull(constraint);
var oldMaxStatements = constraint.MaxStatements;
constraint.MaxStatements = 321;
Assert.Equal(123, oldMaxStatements);
Assert.Equal(321, constraint.MaxStatements);
}
[Fact]
public void CanConstructArrayInstanceFromDescriptorArray()
{
var descriptors = new[]
{
new PropertyDescriptor(42, writable: false, enumerable: false, configurable: false),
};
var engine = new Engine();
var array = new JsArray(engine, descriptors);
Assert.Equal(1L, array.Length);
Assert.Equal(42, array[0]);
}
[Fact]
public void CanGetPropertyDescriptor()
{
var engine = new Engine();
var obj = new DirectoryInfo("the-path");
var propertyDescriptor = ObjectWrapper.GetPropertyDescriptor(engine, obj, obj.GetType().GetProperty(nameof(DirectoryInfo.Name)));
Assert.Equal("the-path", propertyDescriptor.Value);
}
[Fact]
public void CanInjectConstructedObjects()
{
var engine = new Engine();
var obj = new JsObject(engine);
obj.FastSetDataProperty("name", "test");
var array1 = new JsArray(engine, new JsValue[]
{
JsNumber.Create(1),
JsNumber.Create(2),
JsNumber.Create(3)
});
engine.SetValue("array1", array1);
TestArrayAccess(engine, array1, "array1");
var array3 = new JsArray(engine, new []
{
new PropertyDescriptor(JsNumber.Create(1), true, true, true),
new PropertyDescriptor(JsNumber.Create(2), true, true, true),
new PropertyDescriptor(JsNumber.Create(3), true, true, true),
});
engine.SetValue("array3", array3);
TestArrayAccess(engine, array3, "array3");
engine.SetValue("obj", obj);
Assert.Equal("test", engine.Evaluate("obj.name"));
engine.SetValue("emptyArray", new JsArray(engine));
Assert.Equal(0, engine.Evaluate("emptyArray.length"));
Assert.Equal(1, engine.Evaluate("emptyArray.push(1); return emptyArray.length"));
engine.SetValue("emptyArray", new JsArray(engine, Array.Empty()));
Assert.Equal(0, engine.Evaluate("emptyArray.length"));
Assert.Equal(1, engine.Evaluate("emptyArray.push(1); return emptyArray.length"));
engine.SetValue("emptyArray", new JsArray(engine, Array.Empty()));
Assert.Equal(0, engine.Evaluate("emptyArray.length"));
Assert.Equal(1, engine.Evaluate("emptyArray.push(1); return emptyArray.length"));
engine.SetValue("date", new JsDate(engine, new DateTime(2022, 10, 20)));
Assert.Equal(2022, engine.Evaluate("date.getFullYear()"));
}
private static void TestArrayAccess(Engine engine, JsArray array, string name)
{
Assert.Equal(1, engine.Evaluate($"{name}.findIndex(x => x === 2)"));
Assert.Equal(2, array.GetOwnProperty("1").Value);
array.Push(4);
array.Push(new JsValue[] { 5, 6 });
var i = 0;
foreach (var entry in array.GetEntries())
{
Assert.Equal(i.ToString(), entry.Key);
Assert.Equal(i + 1, entry.Value);
i++;
}
Assert.Equal(6, i);
array[0] = "";
array[1] = false;
array[2] = null;
Assert.Equal("", array[0]);
Assert.Equal(false, array[1]);
Assert.Equal(JsValue.Undefined, array[2]);
Assert.Equal(4, array[3]);
Assert.Equal(5, array[4]);
Assert.Equal(6, array[5]);
for (i = 0; i < 100; ++i)
{
array.Push(JsValue.Undefined);
}
Assert.Equal(106L, array.Length);
Assert.True(array.All(x => x is JsNumber or JsUndefined or JsNumber or JsString or JsBoolean));
}
}