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] cannot load assets by mono_download_assets at out of AppBundle #69259

Closed
yamachu opened this issue May 12, 2022 · 5 comments
Closed

[Wasm] cannot load assets by mono_download_assets at out of AppBundle #69259

yamachu opened this issue May 12, 2022 · 5 comments
Assignees
Milestone

Comments

@yamachu
Copy link
Contributor

yamachu commented May 12, 2022

Description

Summary: Cannot initialize dotnet runtime except at location AppBundle directory.

In the template, we can run the sample code by executing the following command in the directory where the assets exist after the build (AppBundle).

$ node main.cjs

https://github.com/dotnet/runtime/tree/51d51c1a6631b205b6ace381bbfd417b5c0e481d/src/mono/wasm/templates/templates/console

Then, from one directory up, run main.cjs in the following way to cause Failed to load config file ./mono-config.json Error: ENOENT: no such file or directory, open './mono-config.json'

I expected to find mono-config.json in the same path as the execution path, so I explicitly specified the path and it was successfully loaded.
The modified code is as follows...

const createDotnetRuntime = require("./dotnet.js");
const { resolve } = require("path");

async function main() {
  const { MONO } = await createDotnetRuntime({
    configSrc: resolve(__dirname, "mono-config.json"),
  });
  const app_args = process.argv.slice(2);
  await MONO.mono_run_main_and_exit("console.dll", app_args);
}
main();

But an error MONO_WASM: Error in mono_download_assets: Error: MONO_WASM: Fetch 'supportFiles/0_runtimeconfig.bin' for supportFiles/0_runtimeconfig.bin failed undefined undefined occurred.

Reproduction Steps

  1. dotnet new wasmconsole
  2. replace main.cjs with Snippet1 (below)
  3. dotnet publish -c Release
  4. cd bin/Release/net7.0/browser-wasm
  5. node AppBundle/main.cjs

Snippet1

const createDotnetRuntime = require("./dotnet.js");
const { resolve } = require("path");

async function main() {
  const { MONO } = await createDotnetRuntime({
    configSrc: resolve(__dirname, "mono-config.json"),
  });
  const app_args = process.argv.slice(2);
  await MONO.mono_run_main_and_exit("console.dll", app_args);
}
main();

Expected behavior

When initializing the dotnet runtime, it is possible to load assets other than assembly and resource even if the node runtime path is not the same path.

see:

if (sourcePrefix.trim() === "") {
if (asset.behavior === "assembly")
attemptUrl = locateFile(config.assembly_root + "/" + asset.name);
else if (asset.behavior === "resource") {
const path = asset.culture !== "" ? `${asset.culture}/${asset.name}` : asset.name;
attemptUrl = locateFile(config.assembly_root + "/" + path);
}
else
attemptUrl = asset.name;
} else {

Actual behavior

Only assembly can be resolved by path and cannot load vfs behavior file.

Regression?

No response

Known Workarounds

No response

Configuration

  • OS
    • macOS 12.3.1(21E258)
  • dotnet --version
    • 7.0.100-preview.4.22252.9
  • Node
    • v16.13.0

Other information

[2022-05-12T14:11:53.081Z] Worker process started and initialized.
[2022-05-12T14:11:54.118Z] Host lock lease acquired by instance ID '000000000000000000000000A572DD4C'.
[2022-05-12T14:13:04.993Z] Worker process started and initialized.
[2022-05-12T14:13:08.343Z] Executing 'Functions.HttpTrigger' (Reason='This function was programmatically called via the host APIs.', Id=f7e37082-4d19-45b3-ab6a-bebe8f2398e0)
[2022-05-12T14:13:08.362Z] HTTP trigger function processed a request.
[2022-05-12T14:13:08.366Z] {
[2022-05-12T14:13:08.366Z]   assembly_root: 'managed',
[2022-05-12T14:13:08.366Z]   debug_level: 0,
[2022-05-12T14:13:08.366Z]   assets: [
[2022-05-12T14:13:08.366Z]     { behavior: 'assembly', name: 'console.dll' },
[2022-05-12T14:13:08.366Z]     { behavior: 'assembly', name: 'System.Console.dll' },
[2022-05-12T14:13:08.366Z]     { behavior: 'assembly', name: 'System.Private.CoreLib.dll' },
[2022-05-12T14:13:08.367Z]     {
[2022-05-12T14:13:08.367Z]       behavior: 'assembly',
[2022-05-12T14:13:08.367Z]       name: 'System.Private.Runtime.InteropServices.JavaScript.dll'
[2022-05-12T14:13:08.367Z]     },
[2022-05-12T14:13:08.367Z]     { behavior: 'assembly', name: 'System.Private.Uri.dll' },
[2022-05-12T14:13:08.367Z]     { behavior: 'assembly', name: 'System.Runtime.dll' },
[2022-05-12T14:13:08.367Z]     {
[2022-05-12T14:13:08.367Z]       virtual_path: 'runtimeconfig.bin',
[2022-05-12T14:13:08.367Z]       behavior: 'vfs',
[2022-05-12T14:13:08.367Z]       name: 'supportFiles/0_runtimeconfig.bin'
[2022-05-12T14:13:08.367Z]     },
[2022-05-12T14:13:08.367Z]     { load_remote: false, behavior: 'icu', name: 'icudt.dat' },
[2022-05-12T14:13:08.367Z]     {
[2022-05-12T14:13:08.367Z]       virtual_path: '/usr/share/zoneinfo/',
[2022-05-12T14:13:08.367Z]       behavior: 'vfs',
[2022-05-12T14:13:08.367Z]       name: 'dotnet.timezones.blat'
[2022-05-12T14:13:08.367Z]     }
[2022-05-12T14:13:08.367Z]   ],
[2022-05-12T14:13:08.367Z]   remote_sources: [],
[2022-05-12T14:13:08.367Z]   environment_variables: {},
[2022-05-12T14:13:08.367Z]   runtime_options: [],
[2022-05-12T14:13:08.367Z]   globalization_mode: 'auto',
[2022-05-12T14:13:08.367Z]   diagnostic_tracing: false
[2022-05-12T14:13:08.368Z] }
[2022-05-12T14:13:08.368Z] '/Users/yk-yamada/Projects/github.com/yamachu/azure-functions-nodejs-with-csharp/dist/AppBundle/managed/console.dll' <- behavior: assembly
[2022-05-12T14:13:08.380Z] 'supportFiles/0_runtimeconfig.bin' <-  behavior: vfs
[2022-05-12T14:13:08.382Z] 'icudt.dat' <-  behavior: vfs
[2022-05-12T14:13:08.384Z] 'dotnet.timezones.blat' <-  behavior: vfs

I think we can run locateFile on any file type, but what is the reason for narrowing down the types?

if (sourcePrefix.trim() === "") {
if (asset.behavior === "assembly")
attemptUrl = locateFile(config.assembly_root + "/" + asset.name);
else if (asset.behavior === "resource") {
const path = asset.culture !== "" ? `${asset.culture}/${asset.name}` : asset.name;
attemptUrl = locateFile(config.assembly_root + "/" + path);
}
else
attemptUrl = asset.name;
} else {

@dotnet-issue-labeler
Copy link

I couldn't figure out the best area label to add to this issue. If you have write-permissions please help me learn by adding exactly one area label.

@ghost ghost added the untriaged New issue has not been triaged by the area owner label May 12, 2022
@radical radical added the arch-wasm WebAssembly architecture label May 12, 2022
@ghost
Copy link

ghost commented May 12, 2022

Tagging subscribers to 'arch-wasm': @lewing
See info in area-owners.md if you want to be subscribed.

Issue Details

Description

Summary: Cannot initialize dotnet runtime except at location AppBundle directory.

In the template, we can run the sample code by executing the following command in the directory where the assets exist after the build (AppBundle).

$ node main.cjs

https://github.com/dotnet/runtime/tree/51d51c1a6631b205b6ace381bbfd417b5c0e481d/src/mono/wasm/templates/templates/console

Then, from one directory up, run main.cjs in the following way to cause Failed to load config file ./mono-config.json Error: ENOENT: no such file or directory, open './mono-config.json'

I expected to find mono-config.json in the same path as the execution path, so I explicitly specified the path and it was successfully loaded.
The modified code is as follows...

const createDotnetRuntime = require("./dotnet.js");
const { resolve } = require("path");

async function main() {
  const { MONO } = await createDotnetRuntime({
    configSrc: resolve(__dirname, "mono-config.json"),
  });
  const app_args = process.argv.slice(2);
  await MONO.mono_run_main_and_exit("console.dll", app_args);
}
main();

But an error MONO_WASM: Error in mono_download_assets: Error: MONO_WASM: Fetch 'supportFiles/0_runtimeconfig.bin' for supportFiles/0_runtimeconfig.bin failed undefined undefined occurred.

Reproduction Steps

  1. dotnet new wasmconsole
  2. replace main.cjs with Snippet1 (below)
  3. dotnet publish -c Release
  4. cd bin/Release/net7.0/browser-wasm
  5. node AppBundle/main.cjs

Snippet1

const createDotnetRuntime = require("./dotnet.js");
const { resolve } = require("path");

async function main() {
  const { MONO } = await createDotnetRuntime({
    configSrc: resolve(__dirname, "mono-config.json"),
  });
  const app_args = process.argv.slice(2);
  await MONO.mono_run_main_and_exit("console.dll", app_args);
}
main();

Expected behavior

When initializing the dotnet runtime, it is possible to load assets other than assembly and resource even if the node runtime path is not the same path.

see:

if (sourcePrefix.trim() === "") {
if (asset.behavior === "assembly")
attemptUrl = locateFile(config.assembly_root + "/" + asset.name);
else if (asset.behavior === "resource") {
const path = asset.culture !== "" ? `${asset.culture}/${asset.name}` : asset.name;
attemptUrl = locateFile(config.assembly_root + "/" + path);
}
else
attemptUrl = asset.name;
} else {

Actual behavior

Only assembly can be resolved by path and cannot load vfs behavior file.

Regression?

No response

Known Workarounds

No response

Configuration

  • OS
    • macOS 12.3.1(21E258)
  • dotnet --version
    • 7.0.100-preview.4.22252.9
  • Node
    • v16.13.0

Other information

[2022-05-12T14:11:53.081Z] Worker process started and initialized.
[2022-05-12T14:11:54.118Z] Host lock lease acquired by instance ID '000000000000000000000000A572DD4C'.
[2022-05-12T14:13:04.993Z] Worker process started and initialized.
[2022-05-12T14:13:08.343Z] Executing 'Functions.HttpTrigger' (Reason='This function was programmatically called via the host APIs.', Id=f7e37082-4d19-45b3-ab6a-bebe8f2398e0)
[2022-05-12T14:13:08.362Z] HTTP trigger function processed a request.
[2022-05-12T14:13:08.366Z] {
[2022-05-12T14:13:08.366Z]   assembly_root: 'managed',
[2022-05-12T14:13:08.366Z]   debug_level: 0,
[2022-05-12T14:13:08.366Z]   assets: [
[2022-05-12T14:13:08.366Z]     { behavior: 'assembly', name: 'console.dll' },
[2022-05-12T14:13:08.366Z]     { behavior: 'assembly', name: 'System.Console.dll' },
[2022-05-12T14:13:08.366Z]     { behavior: 'assembly', name: 'System.Private.CoreLib.dll' },
[2022-05-12T14:13:08.367Z]     {
[2022-05-12T14:13:08.367Z]       behavior: 'assembly',
[2022-05-12T14:13:08.367Z]       name: 'System.Private.Runtime.InteropServices.JavaScript.dll'
[2022-05-12T14:13:08.367Z]     },
[2022-05-12T14:13:08.367Z]     { behavior: 'assembly', name: 'System.Private.Uri.dll' },
[2022-05-12T14:13:08.367Z]     { behavior: 'assembly', name: 'System.Runtime.dll' },
[2022-05-12T14:13:08.367Z]     {
[2022-05-12T14:13:08.367Z]       virtual_path: 'runtimeconfig.bin',
[2022-05-12T14:13:08.367Z]       behavior: 'vfs',
[2022-05-12T14:13:08.367Z]       name: 'supportFiles/0_runtimeconfig.bin'
[2022-05-12T14:13:08.367Z]     },
[2022-05-12T14:13:08.367Z]     { load_remote: false, behavior: 'icu', name: 'icudt.dat' },
[2022-05-12T14:13:08.367Z]     {
[2022-05-12T14:13:08.367Z]       virtual_path: '/usr/share/zoneinfo/',
[2022-05-12T14:13:08.367Z]       behavior: 'vfs',
[2022-05-12T14:13:08.367Z]       name: 'dotnet.timezones.blat'
[2022-05-12T14:13:08.367Z]     }
[2022-05-12T14:13:08.367Z]   ],
[2022-05-12T14:13:08.367Z]   remote_sources: [],
[2022-05-12T14:13:08.367Z]   environment_variables: {},
[2022-05-12T14:13:08.367Z]   runtime_options: [],
[2022-05-12T14:13:08.367Z]   globalization_mode: 'auto',
[2022-05-12T14:13:08.367Z]   diagnostic_tracing: false
[2022-05-12T14:13:08.368Z] }
[2022-05-12T14:13:08.368Z] '/Users/yk-yamada/Projects/github.com/yamachu/azure-functions-nodejs-with-csharp/dist/AppBundle/managed/console.dll' <- behavior: assembly
[2022-05-12T14:13:08.380Z] 'supportFiles/0_runtimeconfig.bin' <-  behavior: vfs
[2022-05-12T14:13:08.382Z] 'icudt.dat' <-  behavior: vfs
[2022-05-12T14:13:08.384Z] 'dotnet.timezones.blat' <-  behavior: vfs

I think we can run locateFile on any file type, but what is the reason for narrowing down the types?

if (sourcePrefix.trim() === "") {
if (asset.behavior === "assembly")
attemptUrl = locateFile(config.assembly_root + "/" + asset.name);
else if (asset.behavior === "resource") {
const path = asset.culture !== "" ? `${asset.culture}/${asset.name}` : asset.name;
attemptUrl = locateFile(config.assembly_root + "/" + path);
}
else
attemptUrl = asset.name;
} else {

Author: yamachu
Assignees: -
Labels:

arch-wasm, untriaged

Milestone: -

@radical
Copy link
Member

radical commented May 13, 2022

cc @pavelsavara @maraf

@pavelsavara
Copy link
Member

PR would be welcome.

Note that __dirname is not available on all platforms we have to support. Also webPack behavior could be interesting.

@radical perhaps your redesign of the bootstrap could consider this request.

yamachu added a commit to yamachu/dotnet-runtime that referenced this issue May 17, 2022
Use localeFile to resolve path for assets outside of remoteSources, so that we can run from a different path than locate that dotnet.js exists

ref:  dotnet#69259
@radical radical removed the untriaged New issue has not been triaged by the area owner label May 17, 2022
@lewing lewing added this to the 7.0.0 milestone Jul 8, 2022
@pavelsavara pavelsavara self-assigned this Jul 18, 2022
yamachu added a commit to yamachu/dotnet-runtime that referenced this issue Jul 26, 2022
…changes

Squashed commit of the following:

commit 8dd23f8
Merge: ffe4a2a 3ac1629
Author: yamachu <yamachu.dev@gmail.com>
Date:   Tue Jul 12 02:13:41 2022 +0900

    Merge branch 'main' into resolve-asset-path-by-locatefile

commit ffe4a2a
Merge: 357ca53 32d0360
Author: yamachu <yamachu.dev@gmail.com>
Date:   Tue Jul 5 01:50:45 2022 +0900

    Merge branch 'main' into resolve-asset-path-by-locatefile

commit 357ca53
Author: yamachu <yamachu.dev@gmail.com>
Date:   Fri Jul 1 02:24:48 2022 +0900

    If an absolute path is passed to configSrc, do not use locateFile to resolve the path, but fetch the path as is.

commit cf45c0d
Merge: 527ad98 85223ce
Author: yamachu <yamachu.dev@gmail.com>
Date:   Fri Jul 1 01:16:11 2022 +0900

    Merge branch 'main' into resolve-asset-path-by-locatefile

commit 527ad98
Author: yamachu <yamachu.dev@gmail.com>
Date:   Tue Jun 28 16:58:28 2022 +0900

    Remove toAbsoluteUrl from test code

commit c339a1a
Author: yamachu <yamachu.dev@gmail.com>
Date:   Tue Jun 28 16:58:10 2022 +0900

    Ported toAbsoluteUrl in the web environment to pre-module

commit 3b4f3f1
Author: yamachu <yamachu.dev@gmail.com>
Date:   Tue Jun 28 14:18:16 2022 +0900

    Remove unused variable

commit 2cdd2c7
Author: yamachu <yamachu.dev@gmail.com>
Date:   Tue Jun 28 14:14:54 2022 +0900

    Unassign toAbsoluteUrl to use locateFile to correct script directory in Node and V8 environments

commit e7a473a
Author: yamachu <yamachu.dev@gmail.com>
Date:   Tue Jun 28 14:13:05 2022 +0900

    Assign a locateFile to the Module that corrects the prefix

    Fix that prefix argument does not indicate the location where the script exists when dotnet.wasm is loaded

commit d54b143
Author: yamachu <yamachu.dev@gmail.com>
Date:   Tue Jun 28 14:05:06 2022 +0900

    Remove flags
     that is only used in certain scenarios

commit 71c1ff7
Author: yamachu <yamachu.dev@gmail.com>
Date:   Tue Jun 28 03:35:26 2022 +0900

    Refactor: use already implemented attributes

commit 86227f1
Author: yamachu <yamachu.dev@gmail.com>
Date:   Tue Jun 28 02:03:20 2022 +0900

    Add notes

commit bac891e
Author: yamachu <yamachu.dev@gmail.com>
Date:   Tue Jun 28 00:30:42 2022 +0900

    test all RunHost

    The project format changes depending on the host, so projects with the same id cannot be used interchangeably.
    Therefore, the project is re-created so that the test id changes, and the cache is also discarded.

commit f41fd42
Author: yamachu <yamachu.dev@gmail.com>
Date:   Tue Jun 28 00:29:53 2022 +0900

    Modified runtime to get the path starting from dotnet.js in shell environment and use that path in test

commit 3e2476c
Author: yamachu <yamachu.dev@gmail.com>
Date:   Tue Jun 28 00:25:02 2022 +0900

    "--run" prefix is reserved, so change flag name

commit ee820c5
Merge: 3076801 c9f80fd
Author: yamachu <yamachu.dev@gmail.com>
Date:   Mon Jun 27 09:43:29 2022 +0900

    Merge branch 'main' into resolve-asset-path-by-locatefile

commit 3076801
Merge: 8388525 cca6bb6
Author: yamachu <yamachu.dev@gmail.com>
Date:   Thu Jun 9 21:38:08 2022 +0900

    Merge branch 'main' into resolve-asset-path-by-locatefile

commit 8388525
Author: yamachu <yamachu.dev@gmail.com>
Date:   Thu May 26 03:34:56 2022 +0900

    Also use locateFile to resolve configFile paths

commit 97b2991
Author: yamachu <yamachu.dev@gmail.com>
Date:   Sat May 21 22:47:57 2022 +0900

    Add Unit test to run WasmApp outside of AppBundle directory

    V8: Could not determine scriptDirectory (always empty string). You must explicitly specify the base path within locateFile.
    Chrome: Failed to load dotnet.wasm

commit a1c3c7a
Author: yamachu <yamachu.dev@gmail.com>
Date:   Wed May 18 00:57:26 2022 +0900

    Use localeFile to resolve path for assets outside of remoteSources

    Use localeFile to resolve path for assets outside of remoteSources, so that we can run from a different path than locate that dotnet.js exists

    ref:  dotnet#69259
@pavelsavara
Copy link
Member

Fixed by #72275

@ghost ghost locked as resolved and limited conversation to collaborators Aug 25, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

6 participants