Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix inheriting from TypeReference backed interop type #1168

Merged
merged 1 commit into from
May 15, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Jint.Tests.Test262/Jint.Tests.Test262.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
<AssemblyOriginatorKeyFile>..\Jint\Jint.snk</AssemblyOriginatorKeyFile>
<SignAssembly>true</SignAssembly>
<IsPackable>false</IsPackable>
<NoWarn>$(NoWarn);CS8002</NoWarn>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Jint\Jint.csproj" />
Expand Down
7 changes: 3 additions & 4 deletions Jint.Tests/Runtime/GenericMethodTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ public void TestFancyGenericFail()
// we _may_ be able to address this by simply instantiating generic types using System.Object for the generic arguments
// This test currently generates the following error:
// No public methods with the specified arguments were found.
[Fact(Skip = "not supported yet")]
public void TestGenericClassDeriveFromGenericInterface()
{
var engine = new Engine(cfg => cfg.AllowClr(typeof(OpenGenericTest<>).Assembly));
Expand Down Expand Up @@ -206,17 +207,15 @@ public static bool SelectInvoked
private set;
}

TState _stateSubject;

public ReduxStore()
{
SelectInvoked = false;
}

public IObservable<TResult> Select<TResult>(ISelectorWithoutProps<TState, TResult> selector, string? optionsStr = null)
public IObservable<TResult> Select<TResult>(ISelectorWithoutProps<TState, TResult> selector, string optionsStr = null)
{
SelectInvoked = true;
return selector.Apply(_stateSubject);
return selector.Apply(null);
}
}

Expand Down
62 changes: 53 additions & 9 deletions Jint.Tests/Runtime/InteropTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -789,20 +789,64 @@ public void CanUseDelegateAsFunction()
[Fact]
public void JavaScriptClassCanExtendClrType()
{
var engine = new Engine();
engine.SetValue("TestClass", TypeReference.CreateTypeReference<TestClass>(engine));
_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.Execute("class ExtendedType extends TestClass { constructor() { super(); this.a = 1; } }");
engine.Execute("class MyExtendedType extends ExtendedType { constructor() { super(); this.b = 2; } }");
engine.Evaluate("let obj = new MyExtendedType();");
_engine.Evaluate("obj.setString('Hello World!');");

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("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"));
}

private struct TestStruct
{
public int Value;
Expand Down
1 change: 0 additions & 1 deletion Jint.Tests/Runtime/ModuleTests.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#if(NET6_0_OR_GREATER)
using System;
using System.IO;
using System.Reflection;
#endif
Expand Down
4 changes: 3 additions & 1 deletion Jint/Native/BigInt/BigIntConstructor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,9 @@ ObjectInstance IConstructor.Construct(JsValue[] arguments, JsValue newTarget)
var o = OrdinaryCreateFromConstructor(
newTarget,
static intrinsics => intrinsics.BigInt.PrototypeObject,
static (engine, realm, state) => new BigIntInstance(engine, (JsBigInt) state), value);
static (engine, realm, state) => new BigIntInstance(engine, state),
value);

return o;
}

Expand Down
2 changes: 1 addition & 1 deletion Jint/Native/BigInt/BigIntPrototype.cs
Original file line number Diff line number Diff line change
Expand Up @@ -150,4 +150,4 @@ private JsBigInt ThisBigIntValue(JsValue value)
return JsBigInt.One;
}
}
}
}
2 changes: 1 addition & 1 deletion Jint/Native/DataView/DataViewConstructor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ ObjectInstance IConstructor.Construct(JsValue[] arguments, JsValue newTarget)
var o = OrdinaryCreateFromConstructor(
newTarget,
static intrinsics => intrinsics.DataView.PrototypeObject,
static (engine, realm, state) => new DataViewInstance(engine));
static (Engine engine, Realm _, object _) => new DataViewInstance(engine));

if (buffer.IsDetachedBuffer)
{
Expand Down
2 changes: 1 addition & 1 deletion Jint/Native/Date/DateConstructor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ private ObjectInstance Construct(JsValue[] arguments, JsValue newTarget)
var o = OrdinaryCreateFromConstructor(
newTarget,
static intrinsics => intrinsics.Date.PrototypeObject,
static (engine, realm, _) => new DateInstance(engine));
static (Engine engine, Realm _, object _) => new DateInstance(engine));
o.DateValue = dv;
return o;
}
Expand Down
2 changes: 1 addition & 1 deletion Jint/Native/Error/ErrorConstructor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ private ObjectInstance Construct(JsValue[] arguments, JsValue newTarget)
var o = OrdinaryCreateFromConstructor(
newTarget,
_intrinsicDefaultProto,
static (engine, realm, state) => new ErrorInstance(engine));
static (Engine engine, Realm _, object _) => new ErrorInstance(engine));

var jsValue = arguments.At(0);
if (!jsValue.IsUndefined())
Expand Down
6 changes: 3 additions & 3 deletions Jint/Native/Function/FunctionInstance.cs
Original file line number Diff line number Diff line change
Expand Up @@ -227,11 +227,11 @@ internal void SetFunctionName(JsValue name, string prefix = null, bool force = f
/// In spec intrinsicDefaultProto is string pointing to intrinsic, but we do a selector.
/// </remarks>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal T OrdinaryCreateFromConstructor<T>(
internal T OrdinaryCreateFromConstructor<T, TState>(
JsValue constructor,
Func<Intrinsics, ObjectInstance> intrinsicDefaultProto,
Func<Engine, Realm, JsValue, T> objectCreator,
JsValue state = null) where T : ObjectInstance
Func<Engine, Realm, TState, T> objectCreator,
TState state = default) where T : ObjectInstance
{
var proto = GetPrototypeFromConstructor(constructor, intrinsicDefaultProto);

Expand Down
4 changes: 2 additions & 2 deletions Jint/Native/Function/ScriptFunctionInstance.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ namespace Jint.Native.Function
{
public sealed class ScriptFunctionInstance : FunctionInstance, IConstructor
{
internal bool _isClassConstructor;
private bool _isClassConstructor;

/// <summary>
/// http://www.ecma-international.org/ecma-262/5.1/#sec-13.2
Expand Down Expand Up @@ -121,7 +121,7 @@ ObjectInstance IConstructor.Construct(JsValue[] arguments, JsValue newTarget)
thisArgument = OrdinaryCreateFromConstructor(
newTarget,
static intrinsics => intrinsics.Object.PrototypeObject,
static (engine, realm, _) => new ObjectInstance(engine));
static (Engine engine, Realm _, object _) => new ObjectInstance(engine));
}

var calleeContext = PrepareForOrdinaryCall(newTarget);
Expand Down
3 changes: 2 additions & 1 deletion Jint/Native/Map/MapConstructor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@ ObjectInstance IConstructor.Construct(JsValue[] arguments, JsValue newTarget)
var map = OrdinaryCreateFromConstructor(
newTarget,
static intrinsics => intrinsics.Map.PrototypeObject,
static (engine, realm, _) => new MapInstance(engine, realm));
static (Engine engine, Realm realm, object _) => new MapInstance(engine, realm));

if (arguments.Length > 0 && !arguments[0].IsNullOrUndefined())
{
var adder = map.Get("set");
Expand Down
2 changes: 1 addition & 1 deletion Jint/Native/Object/ObjectConstructor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ private ObjectInstance Construct(JsValue[] arguments, JsValue newTarget)
return OrdinaryCreateFromConstructor(
newTarget,
static intrinsics => intrinsics.Object.PrototypeObject,
(engine, realm, state) => new ObjectInstance(engine));
static (Engine engine, Realm _, object _) => new ObjectInstance(engine));
}

if (arguments.Length > 0)
Expand Down
2 changes: 1 addition & 1 deletion Jint/Native/Promise/PromiseConstructor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ ObjectInstance IConstructor.Construct(JsValue[] arguments, JsValue newTarget)
var instance = OrdinaryCreateFromConstructor(
newTarget,
static intrinsics => intrinsics.Promise.PrototypeObject,
static(engine, realm, _) => new PromiseInstance(engine));
static (Engine engine, Realm _, object _) => new PromiseInstance(engine));

var (resolve, reject) = instance.CreateResolvingFunctions();
promiseExecutor.Call(Undefined, new JsValue[] {resolve, reject});
Expand Down
2 changes: 1 addition & 1 deletion Jint/Native/RegExp/RegExpConstructor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ private RegExpInstance RegExpAlloc(JsValue newTarget)
var r = OrdinaryCreateFromConstructor(
newTarget,
static intrinsics => intrinsics.RegExp.PrototypeObject,
static (engine, realm, _) => new RegExpInstance(engine));
static (Engine engine, Realm _, object _) => new RegExpInstance(engine));
return r;
}

Expand Down
3 changes: 2 additions & 1 deletion Jint/Native/Set/SetConstructor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@ ObjectInstance IConstructor.Construct(JsValue[] arguments, JsValue newTarget)
var set = OrdinaryCreateFromConstructor(
newTarget,
static intrinsics => intrinsics.Set.PrototypeObject,
static (engine, realm, _) => new SetInstance(engine));
static (Engine engine, Realm _, object _) => new SetInstance(engine));

if (arguments.Length > 0 && !arguments[0].IsNullOrUndefined())
{
var adderValue = set.Get("add");
Expand Down
1 change: 0 additions & 1 deletion Jint/Native/String/StringPrototype.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
Expand Down
2 changes: 1 addition & 1 deletion Jint/Native/WeakMap/WeakMapConstructor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ ObjectInstance IConstructor.Construct(JsValue[] arguments, JsValue newTarget)
var map = OrdinaryCreateFromConstructor(
newTarget,
static intrinsics => intrinsics.WeakMap.PrototypeObject,
static (engine, realm, _) => new WeakMapInstance(engine));
static (Engine engine, Realm _, object _) => new WeakMapInstance(engine));
if (arguments.Length > 0 && !arguments[0].IsNullOrUndefined())
{
var adder = map.Get("set");
Expand Down
3 changes: 2 additions & 1 deletion Jint/Native/WeakSet/WeakSetConstructor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ ObjectInstance IConstructor.Construct(JsValue[] arguments, JsValue newTarget)
var set = OrdinaryCreateFromConstructor(
newTarget,
static intrinsics => intrinsics.WeakSet.PrototypeObject,
static (engine, realm, _) => new WeakSetInstance(engine));
static (Engine engine, Realm _, object _) => new WeakSetInstance(engine));

if (arguments.Length > 0 && !arguments[0].IsNullOrUndefined())
{
var adder = set.Get("add") as ICallable;
Expand Down
Loading