agracio / edge-js

Run .NET and Node.js code in-process on Windows, macOS, and Linux
MIT License
671 stars 97 forks source link

Is it possible to run edge-js using Module (import) syntax? #218

Closed sharky98 closed 1 month ago

sharky98 commented 1 month ago

I was playing around with the quick-start. After some issues initially with net8.0 (for some reason, I simply re-did the steps and it worked afterwards 🤷‍♂️), now everything works.

My next step would have been to use ESM with import statements. I simply did the following:

But now edge-js could not load file or assembly 'System.Runtime[...]'.

This is under Node v22.8.0 and dotnet 8.0.401 (runtime 8.0.8).

E:\[prj-home]\test-edge-js\edge-js-quick-start\node_modules\.pnpm\edge-js@22.7.0\node_modules\edge-js\lib\edge.js:174
    return edge.initializeClrFunc(options);
                ^
Error: Could not load file or assembly 'System.Runtime, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. The system cannot find the file specified.
    at exports.func (E:\[prj-home]\test-edge-js\edge-js-quick-start\node_modules\.pnpm\edge-js@22.7.0\node_modules\edge-js\lib\edge.js:174:17)
    at file:///E:/[prj-home]/test-edge-js/edge-js-quick-start/main.mjs:24:29
    at ModuleJob.run (node:internal/modules/esm/module_job:262:25)
    at async onImport.tracePromise.__proto__ (node:internal/modules/esm/loader:482:26)
    at async asyncRunEntryPointWithESMLoader (node:internal/modules/run_main:117:5) {
  Message: "Could not load file or assembly 'System.Runtime, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. The system cannot find the file specified.",
  FileName: 'System.Runtime, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a',
  FusionLog: '=== Pre-bind state information ===\r\n' +
    'LOG: DisplayName = System.Runtime, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a\n' +
    ' (Fully-specified)\r\n' +
    'LOG: Appbase = file:///C:/Users/[user]/AppData/Local/pnpm/\r\n' +
    'LOG: Initial PrivatePath = NULL\r\n' +
    'Calling assembly : QuickStart.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null.\r\n' +
    '===\r\n' +
    'LOG: This bind starts in LoadFrom load context.\r\n' +
    'WRN: Native image will not be probed in LoadFrom context. Native image will only be probed in default load context, like with Assembly.Load().\r\n' +
    'LOG: No application configuration file found.\r\n' +
    'LOG: Using host configuration file: \r\n' +
    'LOG: Using machine configuration file from C:\\Windows\\Microsoft.NET\\Framework64\\v4.0.30319\\config\\machine.config.\r\n' +
    'LOG: Post-policy reference: System.Runtime, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a\r\n' +
    'LOG: Attempting download of new URL file:///C:/Users/[user]/AppData/Local/pnpm/System.Runtime.DLL.\r\n' +
    'LOG: Attempting download of new URL file:///C:/Users/[user]/AppData/Local/pnpm/System.Runtime/System.Runtime.DLL.\r\n' +
    'LOG: Attempting download of new URL file:///C:/Users/[user]/AppData/Local/pnpm/System.Runtime.EXE.\r\n' +
    'LOG: Attempting download of new URL file:///C:/Users/[user]/AppData/Local/pnpm/System.Runtime/System.Runtime.EXE.\r\n' +
    'LOG: Attempting download of new URL file:///E:/[prj-home]/test-edge-js/edge-js-quick-start/src/QuickStart.Core/bin/Debug/net8.0/System.Runtime.DLL.\r\n' +
    'LOG: Attempting download of new URL file:///E:/[prj-home]/test-edge-js/edge-js-quick-start/src/QuickStart.Core/bin/Debug/net8.0/System.Runtime/System.Runtime.DLL.\r\n' +
    'LOG: Attempting download of new URL file:///E:/[prj-home]/test-edge-js/edge-js-quick-start/src/QuickStart.Core/bin/Debug/net8.0/System.Runtime.EXE.\r\n' +
    'LOG: Attempting download of new URL file:///E:/[prj-home]/test-edge-js/edge-js-quick-start/src/QuickStart.Core/bin/Debug/net8.0/System.Runtime/System.Runtime.EXE.\r\n',
  Data: {},
  InnerException: null,
  TargetSite: {},
  StackTrace: '   at System.Reflection.RuntimeAssembly.GetType(RuntimeAssembly assembly, String name, Boolean throwOnError, Boolean ignoreCase, ObjectHandleOnStack type)\r\n' +
    '   at System.Reflection.RuntimeAssembly.GetType(String name, Boolean throwOnError, Boolean ignoreCase)\r\n' +
    '   at ClrFuncReflectionWrap.Create(Assembly assembly, String typeName, String methodName)\r\n' +
    '   at ClrFunc.Initialize(FunctionCallbackInfo<v8::Value>* info)',
  HelpLink: null,
  Source: 'mscorlib',
  HResult: -2147024894,
  name: 'System.IO.FileNotFoundException'
}
agracio commented 1 month ago

Question regarding this line E:\[prj-home]\test-edge-js\edge-js-quick-start\node_modules\.pnpm\edge-js@22.7.0\node_modules\edge-js\lib\edge.js:174:17, usually it would be E:\[prj-home]\test-edge-js\edge-js-quick-start\node_modules\edge-js\lib\edge.js:174:17 did you change anything else besides just adapting it to use ESM with import?

When you use unmodified quick-start are modules also resolved that way?

EDIT: If you create a GitHub repo that reproduces the error I could take a look, fork quick-start and add your changes to it.

sharky98 commented 1 month ago

Yes, this is simply using pnmp instead of npm. pnpm does some linking under the hood, so both path you listed point the same exact file. This is how pnpm works, so using the quick-start without any modification the module resolve the same way. Basically, it isolate each package, so if you had a dependency on some other package, but not listed in your package.json, it would fail. But since the quick-start does work as-is, there is something else going on.

I'll do the fork in a bit.

agracio commented 1 month ago

If you can create a GitHub repo forked from quick-start with your changes I will take a look at it.

sharky98 commented 1 month ago

Here it is :) https://github.com/sharky98/edge-js-quick-start

I did remove the standard, since I am only using Core. But shouldn't change anything (I think?)

agracio commented 1 month ago

Looks like the issue is with edge-js processing environment variables when you call it this way.

process.env.EDGE_USE_CORECLR = 1;
process.env.EDGE_APP_ROOT = baseNetAppPath;

import { func } from 'edge-js';

process.env.EDGE_APP_ROOT is not important for Core since all the calls are done specifying assemblyFile: baseDll but process.env.EDGE_USE_CORECLR = 1; is not detected.

Running SET EDGE_USE_CORECLR=1 in cmd prompt fixes the issue for that particular cmd window allowing npm run start:module to execute correctly.

agracio commented 1 month ago

Let me know if that answers your question and whether you found a solution to the problem. I will add ESM example to quick-start if you update your repo with working example.

agracio commented 1 month ago

Closing due to inactivity.