123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221 |
- using Jint.Native;
- using Jint.Native.Symbol;
- using Jint.Runtime.Descriptors;
- using Jint.Runtime.Interop;
- using Jint.Tests.Runtime.Domain;
- using Microsoft.Extensions.DependencyInjection;
- namespace Jint.Tests.Runtime;
- public partial class InteropTests
- {
- [Fact]
- public void DelegateWithDefaultValueParametersCanBeInvoked()
- {
- var instance = new A();
- _engine.SetValue("Instance", instance);
- _engine.SetValue("Class", TypeReference.CreateTypeReference(_engine, typeof(A)));
- RunTest(@"
- assert(Instance.Call19() === 0);
- assert(Instance.Call19(1) === 1);
- assert(Instance.Call20(1) === 4);
- assert(Instance.Call20(1, 2) === 5);
- assert(Instance.Call20(1 , 2, 3) === 6);
- assert(Class.Call19Static() === 0);
- assert(Class.Call19Static(1) === 1);
- assert(Class.Call20Static(1) === 4);
- assert(Class.Call20Static(1, 2) === 5);
- assert(Class.Call20Static(1 , 2, 3) === 6);
- ");
- }
- [Fact]
- public void JavaScriptClassCanExtendClrType()
- {
- _engine.SetValue("TestClass", TypeReference.CreateTypeReference<TestClass>(_engine));
- _engine.Execute("class ExtendedType extends TestClass { constructor() { super(); this.a = 1; } get aProp() { return 'A'; } }");
- _engine.Execute("class MyExtendedType extends ExtendedType { constructor() { super(); this.b = 2; } get bProp() { return 'B'; } }");
- _engine.Evaluate("let obj = new MyExtendedType();");
- _engine.Evaluate("obj.setString('Hello World!');");
- Assert.Equal("Hello World!", _engine.Evaluate("obj.string"));
- Assert.Equal(1, _engine.Evaluate("obj.a"));
- Assert.Equal(2, _engine.Evaluate("obj.b"));
- Assert.Equal("A", _engine.Evaluate("obj.aProp"));
- Assert.Equal("B", _engine.Evaluate("obj.bProp"));
- // TODO we should have a special prototype based on wrapped type so we could differentiate between own and type properties
- // Assert.Equal("[\"a\"]", _engine.Evaluate("JSON.stringify(Object.getOwnPropertyNames(new ExtendedType()))"));
- // Assert.Equal("[\"a\",\"b\"]", _engine.Evaluate("JSON.stringify(Object.getOwnPropertyNames(new MyExtendedType()))"));
- }
- [Fact]
- public void ShouldAllowMethodsOnClrExtendedTypes()
- {
- _engine.SetValue("ClrBaseType", TypeReference.CreateTypeReference<TestClass>(_engine));
- _engine.Evaluate(@"
- class JsBaseType {}
- class ExtendsFromJs extends JsBaseType {
- constructor() {
- super();
- this.a = 1;
- }
- getA() {
- return this.a;
- }
- }
- class ExtendsFromClr extends ClrBaseType {
- constructor() {
- super();
- this.a = 1;
- }
- getA() {
- return this.a;
- }
- }
- ");
- var extendsFromJs = _engine.Construct("ExtendsFromJs");
- Assert.Equal(1, _engine.Evaluate("new ExtendsFromJs().getA();"));
- Assert.NotEqual(JsValue.Undefined, extendsFromJs.Get("getA"));
- var extendsFromClr = _engine.Construct("ExtendsFromClr");
- Assert.Equal(1, _engine.Evaluate("new ExtendsFromClr().getA();"));
- Assert.NotEqual(JsValue.Undefined, extendsFromClr.Get("getA"));
- }
- [Fact]
- public void ShouldBeInstanceOfTypeReferenceType()
- {
- _engine.SetValue("A", typeof(A));
- RunTest(@"
- var a = new A();
- assert(a instanceof A);
- ");
- }
- [Fact]
- public void IntegerEnumResolutionShouldWork()
- {
- var engine = new Engine(options => options.AllowClr(GetType().Assembly));
- engine.SetValue("a", new OverLoading());
- engine.SetValue("E", TypeReference.CreateTypeReference(engine, typeof(IntegerEnum)));
- Assert.Equal("integer-enum", engine.Evaluate("a.testFunc(E.a);").AsString());
- }
- [Fact]
- public void UnsignedIntegerEnumResolutionShouldWork()
- {
- var engine = new Engine(options => options.AllowClr(GetType().Assembly));
- engine.SetValue("E", TypeReference.CreateTypeReference(engine, typeof(UintEnum)));
- Assert.Equal(1, engine.Evaluate("E.b;").AsNumber());
- }
- [Fact]
- public void ExceptionFromConstructorShouldPropagate()
- {
- _engine.SetValue("Class", TypeReference.CreateTypeReference(_engine, typeof(MemberExceptionTest)));
- var ex = Assert.Throws<InvalidOperationException>(() => _engine.Evaluate("new Class(true);"));
- Assert.Equal("thrown as requested", ex.Message);
- }
- [Fact]
- public void ShouldScoreDoubleToDoubleParameterMatchHigherThanDoubleToFloat()
- {
- var engine = new Engine();
- var mathTypeReference = TypeReference.CreateTypeReference(engine, typeof(Math));
- engine.SetValue("Math2", mathTypeReference);
- var result = engine.Evaluate("Math2.Max(5.37, 5.56)").AsNumber();
- Assert.Equal(5.56d, result);
- }
- [Fact]
- public void TypeReferenceShouldGetIntermediaryPrototype()
- {
- var engine = new Engine();
- engine.SetValue("Person", TypeReference.CreateTypeReference<Person>(engine));
- var calls = new List<string>();
- engine.SetValue("log", new Action<string>(calls.Add));
- engine.Execute("Person.prototype.__defineGetter__('bar', function() { log('called'); return 5 });");
- engine.Execute("var instance = new Person();");
- engine.Execute("log(instance.bar)");
- engine.Execute("var z = {};");
- engine.Execute("z['bar'] = 20;");
- engine.Execute("log(z['bar']);");
- Assert.Equal("called#5#20", string.Join("#", calls));
- }
- [Fact]
- public void CanConfigureCustomInstanceCreator()
- {
- var collection = new ServiceCollection();
- collection.AddTransient<Injectable>();
- collection.AddTransient<Dependency>();
- var serviceProvider = collection.BuildServiceProvider();
- var engine = new Engine(options =>
- {
- options.Interop.CreateTypeReferenceObject = (e, type, arguments) =>
- {
- var instance = serviceProvider.GetRequiredService(type);
- return instance;
- };
- });
- engine.SetValue("Injectable", TypeReference.CreateTypeReference<Injectable>(engine));
- Assert.Equal("Hello world", engine.Evaluate("new Injectable(123, 'abc').getInjectedValue();"));
- }
- [Fact]
- public void CanRegisterToStringTag()
- {
- var reference = TypeReference.CreateTypeReference<Dependency>(_engine);
- reference.FastSetProperty(GlobalSymbolRegistry.ToStringTag, new PropertyDescriptor(nameof(Dependency), false, false, true));
- reference.FastSetDataProperty("abc", 123);
- _engine.SetValue("MyClass", reference);
- _engine.Execute("var c = new MyClass();");
- Assert.Equal("[object Dependency]", _engine.Evaluate("Object.prototype.toString.call(c);"));
- Assert.Equal(123, _engine.Evaluate("c.abc"));
- // engine uses registered type reference
- _engine.SetValue("c2", new Dependency());
- Assert.Equal("[object Dependency]", _engine.Evaluate("Object.prototype.toString.call(c2);"));
- Assert.Equal(123, _engine.Evaluate("c2.abc"));
- }
- private class Injectable
- {
- private readonly Dependency _dependency;
- public Injectable(Dependency dependency)
- {
- _dependency = dependency;
- }
- public string GetInjectedValue() => _dependency.Value;
- }
- private class Dependency
- {
- public string Value => "Hello world";
- }
- }
|