WS9 Using `ImportAttribute` on a `public static` method in a C# thrown an exception `invalid address import`
Hello,
In our project, we have a C# project with some API available in JavaScript
public class Delta
{
public static readonly ushort NHASH = 16;
[Require(typeof(JS.FossilDelta)), Inline("fossilDelta.create($origin,$target)")]
public static byte[] Create(byte[] origin, byte[] target) {
// ...
}
}
because we are upgrading to WS9 we want to use ESM instead of having a global fossilDelta register on globalThis.
However trying to use ImportAttribute lead to an exception from WS:
public class Delta
{
public static readonly ushort NHASH = 16;
[Import("create", "./js/fossilDelta.js")]
public static byte[] Create(byte[] origin, byte[] target) {
// ...
}
}
WebSharper error : Global error : System.Exception: invalid address import at WebSharper.Compiler.JavaScriptPackager.bodyTransformer@548-1.TransformGlobalAccessSet(Address a, Expression v) at WebSharper.Core.AST.Transformer.TransformExprStatement(Expression a) at WebSharper.Core.AST.Transformer.TransformClassStatic(Statement a) at Microsoft.FSharp.Primitives.Basics.List.map[T,TResult](FSharpFunc`2 mapping, FSharpList`1 x) in D:\a\_work\1\s\src\FSharp.Core\local.fs:line 247 at Microsoft.FSharp.Collections.ListModule.Map[T,TResult](FSharpFunc`2 mapping, FSharpList`1 list) in D:\a\_work\1\s\src\FSharp.Core\list.fs:line 98 at WebSharper.Core.AST.Transformer.TransformClass(Id a, FSharpOption`1 b, FSharpList`1 c, FSharpList`1 d, FSharpList`1 e, FSharpList`1 f) at WebSharper.Core.AST.Transformer.TransformStatement(Statement x) at WebSharper.Compiler.JavaScriptPackager.packageClass@1309-14(Output output, PackageContent content, Dictionary`2 imports, HashSet`1 jsUsed, Dictionary`2 addresses, List`1 statements, HashSet`1 currentScope, Boolean isSingleType, Dictionary`2 bundleExports, FSharpFunc`2 getOrImportAddress, TypeTranslator typeTranslator, FSharpFunc`2 resModule, Hashed`1 typ, Id outerClassId, Address currentClassAddr, Id classId, GenericParam[] gsArr, Statement classDecl) at WebSharper.Compiler.JavaScriptPackager.packageType(Output output, Info refMeta, Info current, String asmName, Boolean flattened, PackageContent content) at WebSharper.Compiler.JavaScriptPackager.pkgTyp@1589(Output output, Info refMeta, Info current, String asmName, Boolean flattened, List`1 pkgs, Hashed`1 typ) at WebSharper.Compiler.JavaScriptPackager.packageAssembly(Output output, Info refMeta, Info current, String asmName, Boolean flattened, FSharpOption`1 entryPoint, EntryPointStyle entryPointStyle) at WebSharper.Compiler.FrontEnd.CreateResources(LoggerBase logger, FSharpOption`1 comp, Info refMeta, Info current, Boolean sourceMap, Boolean dts, Boolean ts, Boolean dce, FSharpOption`1 closures, FSharpOption`1 runtimeMeta, AssemblyDefinition a, FSharpList`1 refAssemblies, Boolean isLibrary, Boolean prebundle, Boolean isSitelet) at WebSharper.Compiler.FrontEnd.ModifyCecilAssembly(LoggerBase logger, FSharpOption`1 comp, Info refMeta, Info current, Boolean sourceMap, Boolean dts, Boolean ts, Boolean dce, FSharpOption`1 closures, FSharpOption`1 runtimeMeta, AssemblyDefinition a, FSharpList`1 refAssemblies, Boolean isLibrary, Boolean prebundle, Boolean isSitelet) at WebSharper.Compiler.FrontEnd.ModifyAssembly(LoggerBase logger, FSharpOption`1 comp, Info refMeta, Info current, Boolean sourceMap, Boolean dts, Boolean ts, Boolean dce, FSharpOption`1 closures, FSharpOption`1 runtimeMeta, Assembly assembly, FSharpList`1 refAssemblies, Boolean isLibrary, Boolean prebundle, Boolean isSitelet) at WebSharper.Compiler.CSharp.Compile.Compile$cont@109-1(WsConfig config, LoggerBase logger, String thisName, Boolean isBundleOnly, AssemblyResolver aR, Loader loader, FSharpList`1 refs, FSharpList`1 wsRefs, FSharpList`1 metas, Info refMeta, FSharpOption`1 assem, Compilation comp, Unit unitVar) at WebSharper.Compiler.CSharp.Compile.Compile$cont@48(WsConfig config, LoggerBase logger, FSharpFunc`2 tryGetMetadata, String thisName, Boolean isBundleOnly, Unit unitVar) at WebSharper.Compiler.CSharp.Compile.compileMain$cont@270(String[] argv, FSharpFunc`2 tryGetMetadata, LoggerBase logger, Unit unitVar) at WebSharper.Compiler.CSharp.Compile.compileMain(String[] argv, FSharpFunc`2 tryGetMetadata, LoggerBase logger) at WebSharper.CSharp.Program.main(String[] argv) [/home/mmangel/Workspaces/Github/Experiad/Motivity/websharper-9/src/Scatter.Fossil/Scatter.Fossil.csproj]
The error is from:
https://github.com/dotnet-websharper/core/blob/c08607accedc47832691113afded30eaf4bb8569/src/compiler/WebSharper.Compiler/JavaScriptPackager.fs#L547-L580
Is it possible to use Import on a C# method?
It seems like the following works:
[Import("create", "./js/fossilDelta.js")]
[Inline("$import($origin, $target)")]
public static byte[] Create(byte[] origin, byte[] target) { }
Yes, the Import won't assume the JS inline by itself. However, adding Stub will, but take note that it also keeps exact casing, so you need to name your .NET method create for [Import("create", "./js/fossilDelta.js"), Stub] to work.