diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Comparers.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Comparers.cs index 3d710b6290e860..495deb4638662f 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Comparers.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Comparers.cs @@ -16,6 +16,10 @@ internal static class Comparers /// Comparer for an individual generated stub source as a syntax tree and the generated diagnostics for the stub. /// public static readonly IEqualityComparer<(MemberDeclarationSyntax Syntax, ImmutableArray Diagnostics)> GeneratedSyntax = new CustomValueTupleElementComparer>(SyntaxEquivalentComparer.Instance, new ImmutableArraySequenceEqualComparer(EqualityComparer.Default)); + public static readonly IEqualityComparer<(MemberDeclarationSyntax, StatementSyntax, AttributeListSyntax, ImmutableArray)> GeneratedSyntax4 = + new CustomValueTupleElementComparer>( + SyntaxEquivalentComparer.Instance, SyntaxEquivalentComparer.Instance, SyntaxEquivalentComparer.Instance, + new ImmutableArraySequenceEqualComparer(EqualityComparer.Default)); } /// @@ -67,4 +71,34 @@ public int GetHashCode((T, U) obj) throw new UnreachableException(); } } + + internal sealed class CustomValueTupleElementComparer : IEqualityComparer<(T, U, V, W)> + { + private readonly IEqualityComparer _item1Comparer; + private readonly IEqualityComparer _item2Comparer; + private readonly IEqualityComparer _item3Comparer; + private readonly IEqualityComparer _item4Comparer; + + public CustomValueTupleElementComparer(IEqualityComparer item1Comparer, IEqualityComparer item2Comparer, IEqualityComparer item3Comparer, IEqualityComparer item4Comparer) + { + _item1Comparer = item1Comparer; + _item2Comparer = item2Comparer; + _item3Comparer = item3Comparer; + _item4Comparer = item4Comparer; + } + + public bool Equals((T, U, V, W) x, (T, U, V, W) y) + { + return _item1Comparer.Equals(x.Item1, y.Item1) + && _item2Comparer.Equals(x.Item2, y.Item2) + && _item3Comparer.Equals(x.Item3, y.Item3) + && _item4Comparer.Equals(x.Item4, y.Item4) + ; + } + + public int GetHashCode((T, U, V, W) obj) + { + throw new UnreachableException(); + } + } } diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Constants.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Constants.cs index c0f661a1b93dc1..5a90431038ac2c 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Constants.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Constants.cs @@ -14,6 +14,7 @@ internal static class Constants public const string JSFunctionSignatureGlobal = "global::System.Runtime.InteropServices.JavaScript.JSFunctionBinding"; public const string JSMarshalerArgumentGlobal = "global::System.Runtime.InteropServices.JavaScript.JSMarshalerArgument"; public const string ModuleInitializerAttributeGlobal = "global::System.Runtime.CompilerServices.ModuleInitializerAttribute"; + public const string CompilerGeneratedAttributeGlobal = "global::System.Runtime.CompilerServices.CompilerGeneratedAttribute"; public const string DynamicDependencyAttributeGlobal = "global::System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute"; public const string ThreadStaticGlobal = "global::System.ThreadStaticAttribute"; public const string TaskGlobal = "global::System.Threading.Tasks.Task"; diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSExportCodeGenerator.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSExportCodeGenerator.cs index 614bad043f15af..c52b0580a8a176 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSExportCodeGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSExportCodeGenerator.cs @@ -123,27 +123,35 @@ public BlockSyntax GenerateJSExportBody() return Block(allStatements); } - public BlockSyntax GenerateJSExportRegistration() + public static StatementSyntax[] GenerateJSExportArchitectureCheck() { - var registrationStatements = new List(); - registrationStatements.Add(IfStatement( - BinaryExpression(SyntaxKind.NotEqualsExpression, - IdentifierName(Constants.OSArchitectureGlobal), - IdentifierName(Constants.ArchitectureWasmGlobal)), - ReturnStatement())); - - var signatureArgs = new List(); - - signatureArgs.Add(Argument(LiteralExpression(SyntaxKind.StringLiteralExpression, Literal(_signatureContext.QualifiedMethodName)))); - signatureArgs.Add(Argument(LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(_signatureContext.TypesHash)))); + return new StatementSyntax[]{ + IfStatement( + BinaryExpression(SyntaxKind.LogicalOrExpression, + IdentifierName("initialized"), + BinaryExpression(SyntaxKind.NotEqualsExpression, + IdentifierName(Constants.OSArchitectureGlobal), + IdentifierName(Constants.ArchitectureWasmGlobal))), + ReturnStatement()), + ExpressionStatement( + AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, + IdentifierName("initialized"), + LiteralExpression(SyntaxKind.TrueLiteralExpression))), + }; + } - signatureArgs.Add(CreateSignaturesSyntax()); + public StatementSyntax GenerateJSExportRegistration() + { + var signatureArgs = new List + { + Argument(LiteralExpression(SyntaxKind.StringLiteralExpression, Literal(_signatureContext.QualifiedMethodName))), + Argument(LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(_signatureContext.TypesHash))), + CreateSignaturesSyntax() + }; - registrationStatements.Add(ExpressionStatement(InvocationExpression(MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, + return ExpressionStatement(InvocationExpression(MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, IdentifierName(Constants.JSFunctionSignatureGlobal), IdentifierName(Constants.BindCSFunctionMethod))) - .WithArgumentList(ArgumentList(SeparatedList(signatureArgs))))); - - return Block(List(registrationStatements)); + .WithArgumentList(ArgumentList(SeparatedList(signatureArgs)))); } private ArgumentSyntax CreateSignaturesSyntax() diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSExportGenerator.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSExportGenerator.cs index 7cfbfdce165776..47c79a692173c3 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSExportGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSExportGenerator.cs @@ -5,11 +5,13 @@ using System.Collections.Immutable; using System.Diagnostics; using System.Linq; +using System.Text; using System.Threading; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; +using System.Collections.Generic; namespace Microsoft.Interop.JavaScript { @@ -73,7 +75,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context) return ImmutableArray.Create(Diagnostic.Create(GeneratorDiagnostics.JSExportRequiresAllowUnsafeBlocks, null)); })); - IncrementalValuesProvider<(MemberDeclarationSyntax, ImmutableArray)> generateSingleStub = methodsToGenerate + IncrementalValuesProvider<(MemberDeclarationSyntax, StatementSyntax, AttributeListSyntax, ImmutableArray)> generateSingleStub = methodsToGenerate .Combine(stubEnvironment) .Combine(stubOptions) .Select(static (data, ct) => new @@ -90,42 +92,64 @@ public void Initialize(IncrementalGeneratorInitializationContext context) .Select( static (data, ct) => GenerateSource(data) ) - .WithComparer(Comparers.GeneratedSyntax) + .WithComparer(Comparers.GeneratedSyntax4) .WithTrackingName(StepNames.GenerateSingleStub); - context.RegisterDiagnostics(generateSingleStub.SelectMany((stubInfo, ct) => stubInfo.Item2)); + context.RegisterDiagnostics(generateSingleStub.SelectMany((stubInfo, ct) => stubInfo.Item4)); + + IncrementalValueProvider> regSyntax = generateSingleStub + .Select( + static (data, ct) => (data.Item2, data.Item3)) + .Collect(); + + IncrementalValueProvider registration = regSyntax + .Select(static (data, ct) => GenerateRegSource(data)) + .Select(static (data, ct) => data.NormalizeWhitespace().ToFullString()); + + IncrementalValueProvider> generated = generateSingleStub + .Combine(registration) + .Select( + static (data, ct) => (data.Left.Item1.NormalizeWhitespace().ToFullString(), data.Right)) + .Collect(); + + + context.RegisterSourceOutput(generated, + (context, generatedSources) => + { + // Don't generate a file if we don't have to, to avoid the extra IDE overhead once we have generated + // files in play. + if (generatedSources.IsEmpty) + return; + + StringBuilder source = new(); + // Mark in source that the file is auto-generated. + source.AppendLine("// "); + // this is the assembly level registration + source.AppendLine(generatedSources[0].Item2); + // this is the method wrappers to be called from JS + foreach (var generated in generatedSources) + { + source.AppendLine(generated.Item1); + } + + // Once https://github.com/dotnet/roslyn/issues/61326 is resolved, we can avoid the ToString() here. + context.AddSource("JSExports.g.cs", source.ToString()); + }); - context.RegisterConcatenatedSyntaxOutputs(generateSingleStub.Select((data, ct) => data.Item1), "JSExports.g.cs"); } private static MemberDeclarationSyntax PrintGeneratedSource( - ContainingSyntax userDeclaredMethod, - JSSignatureContext stub, ContainingSyntaxContext containingSyntaxContext, - BlockSyntax wrapperStatements, BlockSyntax registerStatements) + BlockSyntax wrapperStatements, string wrapperName) { - var WrapperName = "__Wrapper_" + userDeclaredMethod.Identifier + "_" + stub.TypesHash; - var RegistrationName = "__Register_" + userDeclaredMethod.Identifier + "_" + stub.TypesHash; - MemberDeclarationSyntax wrappperMethod = MethodDeclaration(PredefinedType(Token(SyntaxKind.VoidKeyword)), Identifier(WrapperName)) + MemberDeclarationSyntax wrappperMethod = MethodDeclaration(PredefinedType(Token(SyntaxKind.VoidKeyword)), Identifier(wrapperName)) .WithModifiers(TokenList(new[] { Token(SyntaxKind.InternalKeyword), Token(SyntaxKind.StaticKeyword), Token(SyntaxKind.UnsafeKeyword) })) .WithParameterList(ParameterList(SingletonSeparatedList( Parameter(Identifier("__arguments_buffer")).WithType(PointerType(ParseTypeName(Constants.JSMarshalerArgumentGlobal)))))) .WithBody(wrapperStatements); - MemberDeclarationSyntax registerMethod = MethodDeclaration(PredefinedType(Token(SyntaxKind.VoidKeyword)), Identifier(RegistrationName)) - .WithAttributeLists(List(new AttributeListSyntax[]{ - AttributeList(SingletonSeparatedList(Attribute(IdentifierName(Constants.ModuleInitializerAttributeGlobal)))), - AttributeList(SingletonSeparatedList(Attribute(IdentifierName(Constants.DynamicDependencyAttributeGlobal)) - .WithArgumentList(AttributeArgumentList(SeparatedList(new[]{ - AttributeArgument(LiteralExpression(SyntaxKind.StringLiteralExpression, Literal(WrapperName))), - AttributeArgument(TypeOfExpression(ParseTypeName(stub.StubTypeFullName)))} - )))))})) - .WithModifiers(TokenList(new[] { Token(SyntaxKind.InternalKeyword), Token(SyntaxKind.StaticKeyword) })) - .WithBody(registerStatements); - - - MemberDeclarationSyntax toPrint = containingSyntaxContext.WrapMembersInContainingSyntaxWithUnsafeModifier(wrappperMethod, registerMethod); + MemberDeclarationSyntax toPrint = containingSyntaxContext.WrapMembersInContainingSyntaxWithUnsafeModifier(wrappperMethod); return toPrint; } @@ -197,7 +221,68 @@ private static IncrementalStubGenerationContext CalculateStubInformation( return MarshallingGeneratorFactoryKey.Create((env.TargetFramework, env.TargetFrameworkVersion, options), jsGeneratorFactory); } - private static (MemberDeclarationSyntax, ImmutableArray) GenerateSource( + private static NamespaceDeclarationSyntax GenerateRegSource( + ImmutableArray<(StatementSyntax Registration, AttributeListSyntax Attribute)> methods) + { + const string generatedNamespace = "System.Runtime.InteropServices.JavaScript"; + const string initializerClass = "__GeneratedInitializer"; + const string initializerName = "__Register_"; + const string selfInitName = "__Net7SelfInit_"; + + if (methods.IsEmpty) return NamespaceDeclaration(IdentifierName(generatedNamespace)); + + var registerStatements = new List(); + registerStatements.AddRange(JSExportCodeGenerator.GenerateJSExportArchitectureCheck()); + + var attributes = new List(); + foreach (var m in methods) + { + registerStatements.Add(m.Registration); + attributes.Add(m.Attribute); + } + + FieldDeclarationSyntax field = FieldDeclaration(VariableDeclaration(PredefinedType(Token(SyntaxKind.BoolKeyword))) + .WithVariables(SingletonSeparatedList( + VariableDeclarator(Identifier("initialized"))))) + .WithModifiers(TokenList(Token(SyntaxKind.StaticKeyword))); + + MemberDeclarationSyntax method = MethodDeclaration(PredefinedType(Token(SyntaxKind.VoidKeyword)), Identifier(initializerName)) + .WithAttributeLists(List(attributes)) + .WithModifiers(TokenList(new[] { Token(SyntaxKind.StaticKeyword) })) + .WithBody(Block(registerStatements)); + + // when we are running code generated by .NET8 on .NET7 runtime we need to auto initialize the assembly, because .NET7 doesn't call the registration from JS + // this also keeps the code protected from trimming + MemberDeclarationSyntax initializerMethod = MethodDeclaration(PredefinedType(Token(SyntaxKind.VoidKeyword)), Identifier(selfInitName)) + .WithAttributeLists(List(new[]{ + AttributeList(SingletonSeparatedList(Attribute(IdentifierName(Constants.ModuleInitializerAttributeGlobal)))), + })) + .WithModifiers(TokenList(new[] { + Token(SyntaxKind.StaticKeyword), + Token(SyntaxKind.InternalKeyword) + })) + .WithBody(Block( + IfStatement(BinaryExpression(SyntaxKind.EqualsExpression, + IdentifierName("Environment.Version.Major"), + LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(7))), + Block(SingletonList( + ExpressionStatement(InvocationExpression(IdentifierName(initializerName)))))))); + + var ns = NamespaceDeclaration(IdentifierName(generatedNamespace)) + .WithMembers( + SingletonList( + ClassDeclaration(initializerClass) + .WithModifiers(TokenList(new SyntaxToken[]{ + Token(SyntaxKind.UnsafeKeyword)})) + .WithMembers(List(new[] { field, initializerMethod, method })) + .WithAttributeLists(SingletonList(AttributeList(SingletonSeparatedList( + Attribute(IdentifierName(Constants.CompilerGeneratedAttributeGlobal))) + ))))); + + return ns; + } + + private static (MemberDeclarationSyntax, StatementSyntax, AttributeListSyntax, ImmutableArray) GenerateSource( IncrementalStubGenerationContext incrementalContext) { var diagnostics = new GeneratorDiagnostics(); @@ -215,10 +300,21 @@ private static (MemberDeclarationSyntax, ImmutableArray) GenerateSou }, incrementalContext.GeneratorFactoryKey.GeneratorFactory); - BlockSyntax wrapper = stubGenerator.GenerateJSExportBody(); - BlockSyntax registration = stubGenerator.GenerateJSExportRegistration(); + var wrapperName = "__Wrapper_" + incrementalContext.StubMethodSyntaxTemplate.Identifier + "_" + incrementalContext.SignatureContext.TypesHash; - return (PrintGeneratedSource(incrementalContext.StubMethodSyntaxTemplate, incrementalContext.SignatureContext, incrementalContext.ContainingSyntaxContext, wrapper, registration), incrementalContext.Diagnostics.Array.AddRange(diagnostics.Diagnostics)); + BlockSyntax wrapper = stubGenerator.GenerateJSExportBody(); + StatementSyntax registration = stubGenerator.GenerateJSExportRegistration(); + AttributeListSyntax registrationAttribute = AttributeList(SingletonSeparatedList(Attribute(IdentifierName(Constants.DynamicDependencyAttributeGlobal)) + .WithArgumentList(AttributeArgumentList(SeparatedList(new[]{ + AttributeArgument(LiteralExpression(SyntaxKind.StringLiteralExpression, Literal(wrapperName))), + AttributeArgument(LiteralExpression(SyntaxKind.StringLiteralExpression, Literal(incrementalContext.SignatureContext.StubTypeFullName))), + AttributeArgument(LiteralExpression(SyntaxKind.StringLiteralExpression, Literal(incrementalContext.SignatureContext.AssemblyName))), + } + ))))); + + return (PrintGeneratedSource(incrementalContext.ContainingSyntaxContext, wrapper, wrapperName), + registration, registrationAttribute, + incrementalContext.Diagnostics.Array.AddRange(diagnostics.Diagnostics)); } private static Diagnostic? GetDiagnosticIfInvalidMethodForGeneration(MethodDeclarationSyntax methodSyntax, IMethodSymbol method) diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSSignatureContext.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSSignatureContext.cs index ec2882849cb5d0..8f2922099dc623 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSSignatureContext.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSSignatureContext.cs @@ -67,7 +67,8 @@ public static JSSignatureContext Create( StubTypeFullName = stubTypeFullName, MethodName = fullName, QualifiedMethodName = qualifiedName, - BindingName = "__signature_" + method.Name + "_" + typesHash + BindingName = "__signature_" + method.Name + "_" + typesHash, + AssemblyName = env.Compilation.AssemblyName, }; } @@ -87,6 +88,7 @@ private static string GetFullyQualifiedMethodName(StubEnvironment env, IMethodSy public string MethodName { get; init; } public string QualifiedMethodName { get; init; } public string BindingName { get; init; } + public string AssemblyName { get; init; } public override int GetHashCode() { diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System.Runtime.InteropServices.JavaScript.Tests.csproj b/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System.Runtime.InteropServices.JavaScript.Tests.csproj index 8de6bddd05210e..e6e1d2adcf81ec 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System.Runtime.InteropServices.JavaScript.Tests.csproj +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System.Runtime.InteropServices.JavaScript.Tests.csproj @@ -1,4 +1,4 @@ - + true $(NetCoreAppCurrent)-Browser @@ -13,8 +13,8 @@ - - + + diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JavaScriptTestHelper.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JavaScriptTestHelper.cs index 7847d75bfe3945..c249358c708023 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JavaScriptTestHelper.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JavaScriptTestHelper.cs @@ -1011,12 +1011,12 @@ public static string EchoString(string message) return message + "11"; } - public partial class NestedClass + private partial class NestedClass { [System.Runtime.InteropServices.JavaScript.JSExport] public static string EchoString(string message) => message + "12"; - public partial class DoubleNestedClass + private partial class DoubleNestedClass { [System.Runtime.InteropServices.JavaScript.JSExport] public static string EchoString(string message) => message + "13"; diff --git a/src/mono/wasm/runtime/invoke-cs.ts b/src/mono/wasm/runtime/invoke-cs.ts index 293c6731dd433e..961e0a4e428068 100644 --- a/src/mono/wasm/runtime/invoke-cs.ts +++ b/src/mono/wasm/runtime/invoke-cs.ts @@ -8,9 +8,9 @@ import { get_arg, get_sig, get_signature_argument_count, is_args_exception, bound_cs_function_symbol, get_signature_version, alloc_stack_frame, get_signature_type, } from "./marshal"; -import { mono_wasm_new_external_root } from "./roots"; +import { mono_wasm_new_external_root, mono_wasm_new_root } from "./roots"; import { conv_string, conv_string_root } from "./strings"; -import { mono_assert, MonoObjectRef, MonoStringRef, MonoString, MonoObject, MonoMethod, JSMarshalerArguments, JSFunctionSignature, BoundMarshalerToCs, BoundMarshalerToJs } from "./types"; +import { mono_assert, MonoObjectRef, MonoStringRef, MonoString, MonoObject, MonoMethod, JSMarshalerArguments, JSFunctionSignature, BoundMarshalerToCs, BoundMarshalerToJs, VoidPtrNull, MonoObjectRefNull, MonoObjectNull } from "./types"; import { Int32Ptr } from "./types/emscripten"; import cwraps from "./cwraps"; import { assembly_load } from "./class-loader"; @@ -278,7 +278,30 @@ export async function mono_wasm_get_assembly_exports(assembly: string): Promise< const asm = assembly_load(assembly); if (!asm) throw new Error("Could not find assembly: " + assembly); - cwraps.mono_wasm_runtime_run_module_cctor(asm); + + const klass = cwraps.mono_wasm_assembly_find_class(asm, runtimeHelpers.runtime_interop_namespace, "__GeneratedInitializer"); + if (klass) { + const method = cwraps.mono_wasm_assembly_find_method(klass, "__Register_", -1); + if (method) { + const outException = mono_wasm_new_root(); + const outResult = mono_wasm_new_root(); + try { + cwraps.mono_wasm_invoke_method_ref(method, MonoObjectRefNull, VoidPtrNull, outException.address, outResult.address); + if (outException.value !== MonoObjectNull) { + const msg = conv_string_root(outResult)!; + throw new Error(msg); + } + } + finally { + outException.release(); + outResult.release(); + } + } + } else { + // this needs to stay here for compatibility with assemblies generated in Net7 + // it doesn't have the __GeneratedInitializer class + cwraps.mono_wasm_runtime_run_module_cctor(asm); + } endMeasure(mark, MeasuredBlock.getAssemblyExports, assembly); } diff --git a/src/mono/wasm/runtime/invoke-js.ts b/src/mono/wasm/runtime/invoke-js.ts index 07fe9fa5caa4c8..0cee2908032791 100644 --- a/src/mono/wasm/runtime/invoke-js.ts +++ b/src/mono/wasm/runtime/invoke-js.ts @@ -257,7 +257,7 @@ function mono_wasm_lookup_function(function_name: string, js_module_name: string const parts = function_name.split("."); if (js_module_name) { scope = importedModules.get(js_module_name); - mono_assert(scope, () => `ES6 module ${js_module_name} was not imported yet, please call JSHost.Import() first.`); + mono_assert(scope, () => `ES6 module ${js_module_name} was not imported yet, please call JSHost.ImportAsync() first.`); } else if (parts[0] === "INTERNAL") { scope = INTERNAL;