agracio / edge-js

Run .NET and Node.js code in-process on Windows, macOS, and Linux

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Support for F#

andretrump opened this issue · comments

I tried to use edge-js to compile F# but when I proceed as described in the README.md I frist get the error Error: Unsupported language 'fs'. To compile script in language 'fs' an npm module 'edge-fs' must be installed.

When I then install edge-fsI am informed that edge-fs is deprecated and when I run the program, I get the following error:

/Users/andre/typeprovider-test/node_modules/edge-js/lib/edge.js:177
    return edge.initializeClrFunc(options);
                ^
Error: The given assembly name was invalid.
    at exports.func (/Users/andre/typeprovider-test/node_modules/edge-js/lib/edge.js:177:17)
    at Object.<anonymous> (/Users/andre/typeprovider-test/index.js:3:20)
    at Module._compile (node:internal/modules/cjs/loader:1254:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1308:10)
    at Module.load (node:internal/modules/cjs/loader:1117:32)
    at Module._load (node:internal/modules/cjs/loader:958:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12)
    at node:internal/main/run_main_module:23:47 {
  Message: 'The given assembly name was invalid.',
  FileName: '/Users/andre/typeprovider-test/node_modules/edge-fs/lib\\edge-fs.dll',
  FusionLog: null,
  TargetSite: {
    Name: '',
    DeclaringType: '',
    ReflectedType: '',
    MemberType: '',
    MetadataToken: '',
    Module: '',
    IsSecurityCritical: '',
    IsSecuritySafeCritical: '',
    IsSecurityTransparent: '',
    MethodHandle: '',
    Attributes: '',
    CallingConvention: '',
    ReturnType: '',
    ReturnTypeCustomAttributes: '',
    ReturnParameter: '',
    IsCollectible: '',
    IsGenericMethod: '',
    IsGenericMethodDefinition: '',
    ContainsGenericParameters: '',
    MethodImplementationFlags: '',
    IsAbstract: '',
    IsConstructor: '',
    IsFinal: '',
    IsHideBySig: '',
    IsSpecialName: '',
    IsStatic: '',
    IsVirtual: '',
    IsAssembly: '',
    IsFamily: '',
    IsFamilyAndAssembly: '',
    IsFamilyOrAssembly: '',
    IsPrivate: '',
    IsPublic: '',
    IsConstructedGenericMethod: '',
    CustomAttributes: ''
  },
  Data: {},
  InnerException: null,
  HelpLink: null,
  Source: 'System.Private.CoreLib',
  HResult: -2146232799,
  StackTrace: '   at System.Reflection.AssemblyNameParser.ThrowInvalidAssemblyName()\n' +
    '   at System.Reflection.AssemblyNameParser.GetNextToken(String& tokenString)\n' +
    '   at System.Reflection.AssemblyNameParser.Parse()\n' +
    '   at System.Reflection.AssemblyNameParser.Parse(String name)\n' +
    '   at System.Reflection.AssemblyName..ctor(String assemblyName)\n' +
    '   at CoreCLREmbedding.CompileFunc(IntPtr v8Options, Int32 payloadType, IntPtr exception)',
  Name: 'System.IO.FileLoadException',
  name: 'System.IO.FileLoadException'
}

The second error might be caused by the fact that I am on MacOs. If they are not, are these errors known and is it planned to support F#?

It is likely caused by MacOs currently M1/Mx macs are known to have issues. Unfortunately the only M1 mac i have has a defective dotnet install and I was unable to fix it using any available solutions.
If you create a fork will take a look at it on windows to see if it works at all.

Managed to fix my M1 dot net install by doing some correct linking to existing directories but stuck at dotnet version 7.0.101 as I am afraid to break it again when upgrading. edge-js-quick-start runs without any problems, try it out to see if it narrows down the problem to F#.

Thank you for investigating this issue so quickly. Just to clarify: I should try to run edge-js-quick-start with the version of edge-js currently available on npm to see F# causes the issue, right?

Correct, run vanilla edge-js-quick-start following the instructions in README just to verify if it runs at all for you.

I just tried it and except for the warning warning CS1998: This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread, it works fine.
I had also tried the C# example here before and it worked as well.

So the issue isnt Mx chip, create a fork for your F# code and I will take a look at.

I created the fork and added a simple sample of F# code that uses the features I will need (TypeProviders and Reflection) in main.js: https://github.com/andretrump/edge-js-quick-start.
For some reason the error meesage is now different, even if just enter a hello world program. It says:

Error: Could not load file or assembly 'Edge.js.CSharp, Culture=neutral, PublicKeyToken=null'. The system cannot find the file specified.

    at exports.func (/Users/andre/edge-js-quick-start/node_modules/edge-js/lib/edge.js:177:17)
    at Object.<anonymous> (/Users/andre/edge-js-quick-start/main.js:95:25)
    at Module._compile (node:internal/modules/cjs/loader:1254:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1308:10)
    at Module.load (node:internal/modules/cjs/loader:1117:32)
    at Module._load (node:internal/modules/cjs/loader:958:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12)
    at node:internal/main/run_main_module:23:47 {
  Message: "Could not load file or assembly 'Edge.js.CSharp, Culture=neutral, PublicKeyToken=null'. The system cannot find the file specified.\n",
  FileName: 'Edge.js.CSharp, Culture=neutral, PublicKeyToken=null',
  FusionLog: null,
  TargetSite: {
    Name: '',
    DeclaringType: '',
    ReflectedType: '',
    MemberType: '',
    MetadataToken: '',
    Module: '',
    IsSecurityCritical: '',
    IsSecuritySafeCritical: '',
    IsSecurityTransparent: '',
    MethodHandle: '',
    Attributes: '',
    CallingConvention: '',
    ReturnType: '',
    ReturnTypeCustomAttributes: '',
    ReturnParameter: '',
    IsCollectible: '',
    IsGenericMethod: '',
    IsGenericMethodDefinition: '',
    ContainsGenericParameters: '',
    MethodImplementationFlags: '',
    IsAbstract: '',
    IsConstructor: '',
    IsFinal: '',
    IsHideBySig: '',
    IsSpecialName: '',
    IsStatic: '',
    IsVirtual: '',
    IsAssembly: '',
    IsFamily: '',
    IsFamilyAndAssembly: '',
    IsFamilyOrAssembly: '',
    IsPrivate: '',
    IsPublic: '',
    IsConstructedGenericMethod: '',
    CustomAttributes: ''
  },
  Data: {},
  InnerException: null,
  HelpLink: null,
  Source: 'System.Private.CoreLib',
  HResult: -2147024894,
  StackTrace: '   at System.Reflection.RuntimeAssembly.InternalLoad(AssemblyName assemblyName, StackCrawlMark& stackMark, AssemblyLoadContext assemblyLoadContext, RuntimeAssembly requestingAssembly, Boolean throwOnFileNotFound)\n' +
    '   at System.Reflection.Assembly.Load(AssemblyName assemblyRef)\n' +
    '   at CoreCLREmbedding.CompileFunc(IntPtr v8Options, Int32 payloadType, IntPtr exception) in /Users/andre/edge-js-quick-start/node_modules/edge-js/src/double/Edge.js/dotnetcore/coreclrembedding.cs:line 652',
  Name: 'System.IO.FileNotFoundException',
  name: 'System.IO.FileNotFoundException'
}

Maybe I am doing something wrong.

I meant to create a fork of edge-js where you were getting the original error.

Actually dont worry about it, i was able to recreate the original error in edge-js-quick-start

In case it helps: I originally got the error by just running the F# sample from the README.md

Managed to get to the bottom of the issue edge-fs is only compatible with .NET 4,x.

You can check out the project yourself at https://github.com/7sharp9/edge-fs. It has a dependency on FSharp.Build.dll from VS build tools which is then copied to edge-fs lib and to build the project it requires dlls from .NET 4.0 on Windows.
It uses various FSharp.Build methods to dynamically compile underlying 'f#' code when called which restricts it to .NET 4x.

If you desperately need f# integration your best option is to re-write a compiler based on edge-cs code https://github.com/tjanczuk/edge-cs.

Allright, thank you for your help.

If you can convert https://github.com/agracio/edge-js/blob/master/src/double/Edge.js.CSharp/EdgeCompiler.cs to F# I will give it a try. Just make sure that all regexes, etc are still valid.

I am currently not sure if I desparately need F# for my project and I am quite a newbe to .NET, so it will take me some time to convert it. If I figure out that I will definitely need F#, I will try to cenvert it. Thank you for the offer anyway.

F# should only be used for very specific applications that benefit from functional language approach for anything else you should always use C#.

If I use it, I use it because of the TypeProviders. I think there is no similar concept in C#.

It appears that there is a way to implement F# support using .NET Standard, will be looking at it in the coming weeks.

New version released with support for CoreCLR using netstandard 2.0 if you still need it.

I won‘t need it. But thanks for the update anyway.