From a9d061919c12b4e6f3ed2cde3210ec331f5901d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A1s=20Jank=C3=B3?= Date: Wed, 22 May 2024 12:39:52 +0200 Subject: [PATCH] #1408 write re-exports for non-bundled sitelet mode --- .../WebSharper.Compiler.CSharp/Compile.fs | 12 ++- .../WebSharper.Compiler.FSharp/Compile.fs | 13 ++- src/compiler/WebSharper.Compiler/FrontEnd.fs | 18 ++-- .../WebSharper.Compiler/JavaScriptPackager.fs | 84 +++++++++++++++++-- tests/Web/Web.csproj | 4 +- tests/Web/wsconfig.json | 4 +- 6 files changed, 114 insertions(+), 21 deletions(-) diff --git a/src/compiler/WebSharper.Compiler.CSharp/Compile.fs b/src/compiler/WebSharper.Compiler.CSharp/Compile.fs index 68fec97b..90b9f4a9 100644 --- a/src/compiler/WebSharper.Compiler.CSharp/Compile.fs +++ b/src/compiler/WebSharper.Compiler.CSharp/Compile.fs @@ -133,8 +133,18 @@ let Compile config (logger: LoggerBase) tryGetMetadata = | Some (Bundle | Website | Service) -> Some (config.RuntimeMetadata, metas) | _ -> None + let isSitelet = + match config.ProjectType with + | Some Html -> + true + | Some Website + | _ when Option.isSome config.OutputDir -> + true + | _ -> + false + let js, currentMeta, sources, res = - ModifyAssembly logger (Some comp) refMeta currentMeta config.SourceMap config.TypeScriptDeclaration config.TypeScriptOutput config.AnalyzeClosures runtimeMeta assem (config.ProjectType = None) config.PreBundle + ModifyAssembly logger (Some comp) refMeta currentMeta config.SourceMap config.TypeScriptDeclaration config.TypeScriptOutput config.AnalyzeClosures runtimeMeta assem (config.ProjectType = None) config.PreBundle isSitelet match config.ProjectType with | Some (Bundle | Website) -> diff --git a/src/compiler/WebSharper.Compiler.FSharp/Compile.fs b/src/compiler/WebSharper.Compiler.FSharp/Compile.fs index 759b2a9b..dcfde549 100644 --- a/src/compiler/WebSharper.Compiler.FSharp/Compile.fs +++ b/src/compiler/WebSharper.Compiler.FSharp/Compile.fs @@ -248,9 +248,18 @@ let Compile (config : WsConfig) (warnSettings: WarnSettings) (logger: LoggerBase let isLibrary = config.ProjectType = None - let js, currentMeta, sources, res = - ModifyAssembly logger (Some comp) (getRefMeta()) currentMeta config.SourceMap config.TypeScriptDeclaration config.TypeScriptOutput config.AnalyzeClosures runtimeMeta assem isLibrary config.PreBundle + let isSitelet = + match config.ProjectType with + | Some Html -> + true + | Some Website + | _ when Option.isSome config.OutputDir -> + true + | _ -> + false + let js, currentMeta, sources, res = + ModifyAssembly logger (Some comp) (getRefMeta()) currentMeta config.SourceMap config.TypeScriptDeclaration config.TypeScriptOutput config.AnalyzeClosures runtimeMeta assem isLibrary config.PreBundle isSitelet match config.ProjectType with | Some (Bundle | Website) -> let wsRefs = diff --git a/src/compiler/WebSharper.Compiler/FrontEnd.fs b/src/compiler/WebSharper.Compiler/FrontEnd.fs index f0610efd..a548b30b 100644 --- a/src/compiler/WebSharper.Compiler/FrontEnd.fs +++ b/src/compiler/WebSharper.Compiler/FrontEnd.fs @@ -115,7 +115,7 @@ let CreateBundleJSOutput (logger: LoggerBase) refMeta current entryPoint = Some ("", "") -let CreateResources (logger: LoggerBase) (comp: Compilation option) (refMeta: M.Info) (current: M.Info) sourceMap dts ts closures (runtimeMeta: option) (a: Mono.Cecil.AssemblyDefinition) isLibrary prebundle = +let CreateResources (logger: LoggerBase) (comp: Compilation option) (refMeta: M.Info) (current: M.Info) sourceMap dts ts closures (runtimeMeta: option) (a: Mono.Cecil.AssemblyDefinition) isLibrary prebundle isSitelet = let assemblyName = a.Name.Name let sourceMap = false // TODO what about source mapping with all the small files let currentPosFixed, sources = @@ -214,6 +214,14 @@ let CreateResources (logger: LoggerBase) (comp: Compilation option) (refMeta: M. bname, js, trAddrMap ) |> Array.ofSeq |> Some + elif isSitelet then + let rootJS, addrMap = JavaScriptPackager.packageEntryPointReexport meta + let program, _, trAddrMap = rootJS |> WebSharper.Compiler.JavaScriptWriter.transformProgramAndAddrMap O.JavaScript WebSharper.Core.JavaScript.Readable addrMap + let js, _, _ = WebSharper.Compiler.JavaScriptPackager.programToString WebSharper.Core.JavaScript.Readable WebSharper.Core.JavaScript.Writer.CodeWriter program false + logger.TimedStage (sprintf "Writing reexports all.js") + Some [| + "all", js, trAddrMap + |] else None let updated = @@ -382,16 +390,16 @@ let CreateResources (logger: LoggerBase) (comp: Compilation option) (refMeta: M. addMeta() None, currentPosFixed, sources, res.ToArray() -let ModifyCecilAssembly (logger: LoggerBase) (comp: Compilation option) (refMeta: M.Info) (current: M.Info) sourceMap dts ts closures runtimeMeta (a: Mono.Cecil.AssemblyDefinition) isLibrary prebundle = - let jsOpt, currentPosFixed, sources, res = CreateResources logger comp refMeta current sourceMap dts ts closures runtimeMeta a isLibrary prebundle +let ModifyCecilAssembly (logger: LoggerBase) (comp: Compilation option) (refMeta: M.Info) (current: M.Info) sourceMap dts ts closures runtimeMeta (a: Mono.Cecil.AssemblyDefinition) isLibrary prebundle isSitelet = + let jsOpt, currentPosFixed, sources, res = CreateResources logger comp refMeta current sourceMap dts ts closures runtimeMeta a isLibrary prebundle isSitelet let pub = Mono.Cecil.ManifestResourceAttributes.Public for name, contents in res do Mono.Cecil.EmbeddedResource(name, pub, contents) |> a.MainModule.Resources.Add jsOpt, currentPosFixed, sources, res -let ModifyAssembly (logger: LoggerBase) (comp: Compilation option) (refMeta: M.Info) (current: M.Info) sourceMap dts ts closures runtimeMeta (assembly : Assembly) isLibrary = - ModifyCecilAssembly logger comp refMeta current sourceMap dts ts closures runtimeMeta assembly.Raw isLibrary +let ModifyAssembly (logger: LoggerBase) (comp: Compilation option) (refMeta: M.Info) (current: M.Info) sourceMap dts ts closures runtimeMeta (assembly : Assembly) isLibrary prebundle isSitelet = + ModifyCecilAssembly logger comp refMeta current sourceMap dts ts closures runtimeMeta assembly.Raw isLibrary prebundle isSitelet let AddExtraAssemblyReferences (wsrefs: Assembly seq) (assembly : Assembly) = let a = assembly.Raw diff --git a/src/compiler/WebSharper.Compiler/JavaScriptPackager.fs b/src/compiler/WebSharper.Compiler/JavaScriptPackager.fs index 1192f4c8..1ff78ef3 100644 --- a/src/compiler/WebSharper.Compiler/JavaScriptPackager.fs +++ b/src/compiler/WebSharper.Compiler/JavaScriptPackager.fs @@ -1378,16 +1378,82 @@ let programToString pref (getWriter: unit -> WebSharper.Core.JavaScript.Writer.C WebSharper.Core.JavaScript.Writer.WriteProgram pref writer program writer.GetCodeFile(), writer.GetMapFile(), isJSX -let packageEntryPoint (runtimeMeta: M.Info) (graph: DependencyGraph.Graph) asmName = +let packageEntryPointReexport (runtimeMeta: M.Info) = + + let allBundleContent = ResizeArray() + let addresses = ResizeArray() - //let webControls = - // runtimeMeta.Classes |> Seq.choose (fun (KeyValue(td, (_, _, cls))) -> - // match cls with - // | Some cls when isWebControl cls -> - // Some td - // | _ -> None - // ) - // |> Array.ofSeq + for qi in runtimeMeta.Quotations.Values do + allBundleContent.Add(qi.TypeDefinition, Some qi.Method) + + for KeyValue((td, m), _) in runtimeMeta.QuotedMethods do + allBundleContent.Add(td, Some m) + + for wc in runtimeMeta.WebControls do + allBundleContent.Add(wc.Key.TypeDefinition, None) + + for td, m in allBundleContent do + match runtimeMeta.Classes.TryFind td with + | Some (addr, _, Some cls) -> + match m with + | Some m -> + match cls.Methods.TryFind m with + | Some mi -> + match mi.CompiledForm with + | M.Static (name, _, _) -> addresses.Add(addr) + | M.Func (name, _) -> addresses.Add(addr.Func(name)) + | M.GlobalFunc (faddr, _) -> addresses.Add(faddr) + | _ -> () + | _ -> () + | _ -> + addresses.Add(addr) + | _ -> () + + let addressMap = Dictionary() + + addressMap.Add("Runtime", Address.RuntimeAddr [ "default" ]) + + for a in Seq.distinct addresses do + addressMap |> Resolve.getRenamedInDict a.Address.Head a |> ignore + + let revAddressMap = addressMap |> Dict.swap + + let finalAddrMap = Dictionary() + + let rootJs = + revAddressMap |> Seq.groupBy (fun kv -> kv.Key.Module) + |> Seq.map (fun (m, addrs) -> + let namedImports = ResizeArray() + for KeyValue(a, n) in addrs do + match a.Address |> List.rev |> List.head with + | "default" -> + let newName = + match m with + | JavaScriptModule m -> + m.Name.Replace('.', '_').Replace('`', '_') + | DotNetType m -> + (m.Name.Split([| '/'; '.' |]) |> Array.last).Split('`') |> Array.head + | _ -> "default" + let x = Id.New newName + namedImports.Add("default", x) + finalAddrMap.Add(a, x) + | i -> + let x = Id.New n + namedImports.Add(i, Id.New n) + finalAddrMap.Add(a, x) + let moduleName = + match m with + | JavaScriptModule m + | DotNetType m -> + "../" + m.Assembly + "/" + m.Name + ".js" + | _ -> "" + ExportDecl (false, Import(None, None, List.ofSeq namedImports, moduleName)) + ) + |> List.ofSeq + + rootJs, finalAddrMap + +let packageEntryPoint (runtimeMeta: M.Info) (graph: DependencyGraph.Graph) asmName = let all = ResizeArray() let bundles = Dictionary() diff --git a/tests/Web/Web.csproj b/tests/Web/Web.csproj index d8361af2..94173176 100644 --- a/tests/Web/Web.csproj +++ b/tests/Web/Web.csproj @@ -38,9 +38,9 @@ - + \ No newline at end of file diff --git a/tests/Web/wsconfig.json b/tests/Web/wsconfig.json index 937a8a9a..d99bc8d3 100644 --- a/tests/Web/wsconfig.json +++ b/tests/Web/wsconfig.json @@ -4,8 +4,8 @@ "outputDir": "wwwroot", "downloadResources": true, "runtimeMetadata": "full", - "preBundle": true, + "preBundle": false, "release": { - "preBundle": true + "preBundle": false } }