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

[wasm][draft] make JSObject dynamic #78853

Closed
wants to merge 2 commits into from
Closed
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
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ public sealed class Any : JSType
}

[Versioning.SupportedOSPlatformAttribute("browser")]
public class JSObject : IDisposable
public class JSObject : IDisposable, System.Dynamic.IDynamicMetaObjectProvider
{
internal JSObject() { throw null; }
public bool IsDisposed { get { throw null; } }
Expand All @@ -131,6 +131,8 @@ public class JSObject : IDisposable
public void SetProperty(string propertyName, string? value) { throw null; }
public void SetProperty(string propertyName, JSObject? value) { throw null; }
public void SetProperty(string propertyName, byte[]? value) { throw null; }

public System.Dynamic.DynamicMetaObject GetMetaObject(System.Linq.Expressions.Expression parameter) => throw null;
}

[Versioning.SupportedOSPlatformAttribute("browser")]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@
<ItemGroup>
<ProjectReference Include="..\..\System.Collections\ref\System.Collections.csproj" />
<ProjectReference Include="..\..\System.Runtime\ref\System.Runtime.csproj" />
<ProjectReference Include="..\..\System.Linq.Expressions\ref\System.Linq.Expressions.csproj" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

<ItemGroup>
<Compile Include="System.Runtime.InteropServices.JavaScript.SupportedOSPlatform.cs" />
<Compile Include="System\Runtime\InteropServices\JavaScript\JSObject.Dynamic.cs" />
</ItemGroup>

<ItemGroup Condition="'$(TargetPlatformIdentifier)' == 'Browser'">
Expand Down Expand Up @@ -76,6 +77,7 @@
<Reference Include="System.Threading" />
<Reference Include="System.Threading.Thread" />
<Reference Include="System.Threading.Channels" />
<Reference Include="System.Linq.Expressions" />
</ItemGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Dynamic;
using System.Linq.Expressions;

namespace System.Runtime.InteropServices.JavaScript
{
public partial class JSObject : IDynamicMetaObjectProvider
{
public DynamicMetaObject GetMetaObject(Expression parameter)
{
return new MetaDynamic(parameter, this);
}

private sealed class MetaDynamic : DynamicMetaObject
{
private JSObject proxy;

internal MetaDynamic(Expression expression, JSObject value)
: base(expression, BindingRestrictions.GetTypeRestriction(expression, typeof(JSObject)), value)
{
proxy = value;
}

public override DynamicMetaObject BindGetMember(GetMemberBinder binder)
{
var typeOf = proxy.GetTypeOfProperty(binder.Name);
switch (typeOf)
{
case "undefined":
case "null":
return new DynamicMetaObject(Expression.Constant(null), Restrictions);
case "string":
var str = proxy.GetPropertyAsString(binder.Name);
return new DynamicMetaObject(Expression.Constant(str), Restrictions);
case "number":
var num = proxy.GetPropertyAsDouble(binder.Name);
return new DynamicMetaObject(Expression.Constant(num), Restrictions);
case "object":
var obj = proxy.GetPropertyAsJSObject(binder.Name)!;
return new MetaDynamic(Expression.Constant(obj), obj);
case "function":
default:
throw new NotImplementedException(typeOf);
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,27 @@ public async Task MultipleImportAsync()
Assert.Same(instance1, instance2);
}

[Fact]
public async Task Dynamic()
{
dynamic globalThis = JSHost.GlobalThis;
Console.WriteLine("Hello from " + globalThis.os?.d8Path);
Console.WriteLine("Hello from " + globalThis.location?.href);

var first = await JSHost.ImportAsync("JavaScriptTestHelper", "./JavaScriptTestHelper.mjs");
Assert.NotNull(first);
dynamic instance1 = first.GetPropertyAsJSObject("instance");

//Assert.Null((object)instance1.missing);
//Assert.Null((object)instance1.nnn);
Assert.Equal("xxx", (string)instance1.xxx);
var yyy = instance1.yyy;
Assert.IsType<JSObject>(yyy);
//double zzz = yyy.zzz;
//Assert.Equal(3.14d, (double)zzz);
}


[Fact]
public unsafe void GlobalThis()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,13 @@ export function backback(arg1, arg2, arg3) {
}
}

export const instance = {}
export const instance = {
nnn:null,
xxx:"xxx",
yyy:{
zzz:3.14
}
}

globalThis.javaScriptTestHelper = instance;
globalThis.data = new JSData("i-n-s-t-a-n-c-e");
Expand Down