From f30e43c2e3c4274b5d6b60efd525e15f53c3a360 Mon Sep 17 00:00:00 2001 From: "Namhyeon, Go" Date: Mon, 8 Dec 2025 00:49:10 +0900 Subject: [PATCH 01/12] Introduce new package `Catswords.Phantomizer` Introduce new package `Catswords.Phantomizer` **Catswords.Phantomizer** is an HTTP-based dynamic-link library (DLL) loader designed for .NET applications. It allows your application to fetch and load assemblies directly from your CDN (Azure Blob, S3, Cloudflare R2, etc.) at runtime, with optional GZip compression support. --- .appveyor.yml | 1 + .../AssemblyLoader.cs | 71 ++++++------- .../Catswords.Phantomizer.csproj | 7 ++ .../Catswords.Phantomizer/LICENSE | 21 ++++ .../Catswords.Phantomizer/README.md | 93 ++++++++++++++++++ WelsonJS.Toolkit/WelsonJS.Launcher/Program.cs | 49 ++++++++- .../Properties/Resources.Designer.cs | 10 ++ .../Properties/Resources.resx | 3 + .../Resources/Catswords.Phantomizer.dll.gz | Bin 0 -> 6926 bytes .../WelsonJS.Launcher.csproj | 2 +- WelsonJS.Toolkit/WelsonJS.Toolkit.sln | 10 ++ 11 files changed, 227 insertions(+), 40 deletions(-) rename WelsonJS.Toolkit/{WelsonJS.Launcher => Catswords.Phantomizer}/AssemblyLoader.cs (84%) create mode 100644 WelsonJS.Toolkit/Catswords.Phantomizer/Catswords.Phantomizer.csproj create mode 100644 WelsonJS.Toolkit/Catswords.Phantomizer/LICENSE create mode 100644 WelsonJS.Toolkit/Catswords.Phantomizer/README.md create mode 100644 WelsonJS.Toolkit/WelsonJS.Launcher/Resources/Catswords.Phantomizer.dll.gz diff --git a/.appveyor.yml b/.appveyor.yml index aac253a..b68237e 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -25,6 +25,7 @@ after_build: #- cmd: xcopy /s /y WelsonJS.Toolkit\WelsonJS.Toolkit\bin\x86\%CONFIGURATION%\* artifacts\ - cmd: xcopy /s /y WelsonJS.Toolkit\WelsonJS.Service\bin\x86\%CONFIGURATION%\* artifacts\ - cmd: xcopy /s /y WelsonJS.Toolkit\WelsonJS.Launcher\bin\x86\%CONFIGURATION%\* artifacts\ + - cmd: xcopy /s /y WelsonJS.Toolkit\Catswords.Phantomizer\bin\x86\%CONFIGURATION%\* artifacts\ - cmd: nuget pack WelsonJS.Toolkit\WelsonJS.Toolkit\ -properties Configuration=%CONFIGURATION% -properties Platform=x86 -OutputDirectory artifacts\ - ps: Start-BitsTransfer -Source "https://catswords.blob.core.windows.net/welsonjs/welsonjs_setup_unsigned.exe" -Destination "artifacts\welsonjs_setup.exe" - ps: Start-BitsTransfer -Source "https://catswords.blob.core.windows.net/welsonjs/chakracore-build/x86_release/ChakraCore.dll" -Destination "artifacts\ChakraCore.dll" diff --git a/WelsonJS.Toolkit/WelsonJS.Launcher/AssemblyLoader.cs b/WelsonJS.Toolkit/Catswords.Phantomizer/AssemblyLoader.cs similarity index 84% rename from WelsonJS.Toolkit/WelsonJS.Launcher/AssemblyLoader.cs rename to WelsonJS.Toolkit/Catswords.Phantomizer/AssemblyLoader.cs index 28575be..abe4c2a 100644 --- a/WelsonJS.Toolkit/WelsonJS.Launcher/AssemblyLoader.cs +++ b/WelsonJS.Toolkit/Catswords.Phantomizer/AssemblyLoader.cs @@ -1,10 +1,11 @@ -๏ปฟ// AssemblyLoader.cs -// SPDX-License-Identifier: GPL-3.0-or-later +๏ปฟ// AssemblyLoader.cs (Catswords.Phantomizer) +// SPDX-License-Identifier: MIT // SPDX-FileCopyrightText: Namhyeon Go , 2025 Catswords OSS and WelsonJS Contributors // https://github.com/gnh1201/welsonjs // using System; using System.Collections.Generic; +using System.Diagnostics; using System.IO; using System.IO.Compression; using System.Net; @@ -12,14 +13,14 @@ using System.Net.Http; using System.Reflection; using System.Runtime.InteropServices; -namespace WelsonJS.Launcher +namespace Catswords.Phantomizer { /// /// Network-aware loader for managed (.NET) and native (C/C++) binaries. /// - Managed assemblies resolve via AssemblyResolve /// - Native modules explicitly loaded via LoadNativeModules(...) /// - All DLLs must have valid Authenticode signatures - /// - Cached at: %APPDATA%\WelsonJS\assembly\{Name}\{Version}\ + /// - Cached at: %APPDATA%\Catswords\assembly\{Name}\{Version}\ /// - BaseUrl must be set by Main() before calling Register() /// public static class AssemblyLoader @@ -30,12 +31,12 @@ namespace WelsonJS.Launcher /// Must be set before Register() or LoadNativeModules(). /// public static string BaseUrl { get; set; } = null; - public static ICompatibleLogger Logger { get; set; } = null; + public static string LoaderNamespace { get; set; } = typeof(AssemblyLoader).Namespace; + public static string AppName { get; set; } = "Catswords"; private static readonly object SyncRoot = new object(); private static bool _registered; - private static readonly string LoaderNamespace = typeof(AssemblyLoader).Namespace ?? "WelsonJS.Launcher"; private static readonly HttpClientHandler LegacyHttpHandler = new HttpClientHandler { AutomaticDecompression = DecompressionMethods.None @@ -168,20 +169,20 @@ namespace WelsonJS.Launcher if (string.IsNullOrWhiteSpace(BaseUrl)) { - Logger?.Error("AssemblyLoader.Register() called but BaseUrl is not set."); + Trace.TraceError("AssemblyLoader.Register() called but BaseUrl is not set."); throw new InvalidOperationException("AssemblyLoader.BaseUrl must be configured before Register()."); } if (!BaseUrl.StartsWith("https://", StringComparison.OrdinalIgnoreCase)) { - Logger?.Error("AssemblyLoader.BaseUrl must use HTTPS for security."); + Trace.TraceError("AssemblyLoader.BaseUrl must use HTTPS for security."); throw new InvalidOperationException("AssemblyLoader.BaseUrl must use HTTPS."); } AppDomain.CurrentDomain.AssemblyResolve += OnAssemblyResolve; _registered = true; - Logger?.Info("AssemblyLoader: AssemblyResolve handler registered."); + Trace.TraceInformation("AssemblyLoader: AssemblyResolve handler registered."); } } @@ -203,17 +204,17 @@ namespace WelsonJS.Launcher lock (SyncRoot) { string appData = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); - string cacheDir = Path.Combine(appData, "WelsonJS", "assembly", ownerAssemblyName, versionString); + string cacheDir = Path.Combine(appData, AppName, "assembly", ownerAssemblyName, versionString); Directory.CreateDirectory(cacheDir); try { if (!SetDllDirectory(cacheDir)) - Logger?.Warn("SetDllDirectory failed for: {0}", cacheDir); + Trace.TraceWarning("SetDllDirectory failed for: {0}", cacheDir); } catch (Exception ex) { - Logger?.Warn("SetDllDirectory threw exception: {0}", ex.Message); + Trace.TraceWarning("SetDllDirectory threw exception: {0}", ex.Message); } foreach (string raw in fileNames) @@ -228,11 +229,11 @@ namespace WelsonJS.Launcher { string url = $"{BaseUrl.TrimEnd('/')}/native/{ownerAssemblyName}/{versionString}/{fileName}"; DownloadFile(url, localPath); - Logger?.Info("Downloaded native module: {0}", fileName); + Trace.TraceInformation("Downloaded native module: {0}", fileName); } else { - Logger?.Info("Using cached native module: {0}", localPath); + Trace.TraceInformation("Using cached native module: {0}", localPath); } EnsureSignedFileOrThrow(localPath, fileName); @@ -241,12 +242,12 @@ namespace WelsonJS.Launcher if (h == IntPtr.Zero) { int errorCode = Marshal.GetLastWin32Error(); - Logger?.Error("LoadLibrary failed for {0} with error code {1}", localPath, errorCode); + Trace.TraceError("LoadLibrary failed for {0} with error code {1}", localPath, errorCode); throw new InvalidOperationException($"Failed to load native module: {fileName} (error: {errorCode})"); } else { - Logger?.Info("Loaded native module: {0}", fileName); + Trace.TraceInformation("Loaded native module: {0}", fileName); } } } @@ -277,7 +278,7 @@ namespace WelsonJS.Launcher private static Assembly OnAssemblyResolve(object sender, ResolveEventArgs args) { - Logger?.Info("AssemblyResolve: {0}", args.Name); + Trace.TraceInformation("AssemblyResolve: {0}", args.Name); AssemblyName req = new AssemblyName(args.Name); string simpleName = req.Name; @@ -290,7 +291,7 @@ namespace WelsonJS.Launcher var entryName = entry.GetName().Name; if (string.Equals(simpleName, entryName, StringComparison.OrdinalIgnoreCase)) { - Logger?.Info("AssemblyResolve: skipping entry assembly {0}", simpleName); + Trace.TraceInformation("AssemblyResolve: skipping entry assembly {0}", simpleName); return null; } } @@ -301,7 +302,7 @@ namespace WelsonJS.Launcher lock (SyncRoot) { string appData = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); - string cacheDir = Path.Combine(appData, "WelsonJS", "assembly", simpleName, versionStr); + string cacheDir = Path.Combine(appData, AppName, "assembly", simpleName, versionStr); string dllPath = Path.Combine(cacheDir, simpleName + ".dll"); Directory.CreateDirectory(cacheDir); @@ -310,16 +311,16 @@ namespace WelsonJS.Launcher { string url = $"{BaseUrl.TrimEnd('/')}/managed/{simpleName}/{versionStr}/{simpleName}.dll"; DownloadFile(url, dllPath); - Logger?.Info("Downloaded managed assembly: {0}", simpleName); + Trace.TraceInformation("Downloaded managed assembly: {0}", simpleName); } else { - Logger?.Info("Using cached managed assembly: {0}", dllPath); + Trace.TraceInformation("Using cached managed assembly: {0}", dllPath); } if (!File.Exists(dllPath)) { - Logger?.Warn("AssemblyResolve: managed assembly not found after download attempt: {0}", simpleName); + Trace.TraceWarning("AssemblyResolve: managed assembly not found after download attempt: {0}", simpleName); return null; } @@ -345,13 +346,13 @@ namespace WelsonJS.Launcher if (isDll && TryDownloadCompressedFile(gzUrl, dest)) { - Logger?.Info("Downloaded and decompressed file to: {0}", dest); + Trace.TraceInformation("Downloaded and decompressed file to: {0}", dest); downloaded = true; } if (!downloaded) { - Logger?.Info("Downloading file from: {0}", url); + Trace.TraceInformation("Downloading file from: {0}", url); res = Http.GetAsync(url).GetAwaiter().GetResult(); res.EnsureSuccessStatusCode(); @@ -361,7 +362,7 @@ namespace WelsonJS.Launcher s.CopyTo(fs); } - Logger?.Info("Downloaded file to: {0}", dest); + Trace.TraceInformation("Downloaded file to: {0}", dest); } if (!File.Exists(dest)) @@ -371,12 +372,12 @@ namespace WelsonJS.Launcher } catch (HttpRequestException ex) { - Logger?.Error("Network or I/O error downloading {0}: {1}", url, ex.Message); + Trace.TraceError("Network or I/O error downloading {0}: {1}", url, ex.Message); throw; } catch (Exception ex) { - Logger?.Error("Unexpected error downloading {0}: {1}", url, ex.Message); + Trace.TraceError("Unexpected error downloading {0}: {1}", url, ex.Message); throw; } finally @@ -396,7 +397,7 @@ namespace WelsonJS.Launcher { if (res.StatusCode == HttpStatusCode.NotFound) { - Logger?.Info("No gzipped variant at {0}; falling back to uncompressed URL.", gzUrl); + Trace.TraceInformation("No gzipped variant at {0}; falling back to uncompressed URL.", gzUrl); return false; } @@ -419,12 +420,12 @@ namespace WelsonJS.Launcher } catch (HttpRequestException ex) { - Logger?.Warn("Network or I/O error downloading compressed file from {0}: {1}", gzUrl, ex.Message); + Trace.TraceWarning("Network or I/O error downloading compressed file from {0}: {1}", gzUrl, ex.Message); throw; } catch (Exception ex) { - Logger?.Error("Unexpected error downloading compressed file from {0}: {1}", gzUrl, ex.Message); + Trace.TraceError("Unexpected error downloading compressed file from {0}: {1}", gzUrl, ex.Message); throw; } finally @@ -437,7 +438,7 @@ namespace WelsonJS.Launcher } catch (Exception ex) { - Logger?.Info("Failed to delete temporary file {0}: {1}", tempFile, ex.Message); + Trace.TraceInformation("Failed to delete temporary file {0}: {1}", tempFile, ex.Message); } } } @@ -461,7 +462,7 @@ namespace WelsonJS.Launcher { if (!File.Exists(path)) { - Logger?.Error("File does not exist for signature verification: {0}", logicalName); + Trace.TraceError("File does not exist for signature verification: {0}", logicalName); throw new FileNotFoundException("File not found for signature verification: " + logicalName, path); } @@ -469,17 +470,17 @@ namespace WelsonJS.Launcher if (status == FileSignatureStatus.Valid) { - Logger?.Info("Signature OK: {0}", logicalName); + Trace.TraceInformation("Signature OK: {0}", logicalName); return; } if (status == FileSignatureStatus.NoSignature) { - Logger?.Error("BLOCKED unsigned binary: {0}", logicalName); + Trace.TraceError("BLOCKED unsigned binary: {0}", logicalName); throw new InvalidOperationException("Unsigned binary blocked: " + logicalName); } - Logger?.Error("BLOCKED invalid signature: {0}", logicalName); + Trace.TraceError("BLOCKED invalid signature: {0}", logicalName); throw new InvalidOperationException("Invalid signature: " + logicalName); } diff --git a/WelsonJS.Toolkit/Catswords.Phantomizer/Catswords.Phantomizer.csproj b/WelsonJS.Toolkit/Catswords.Phantomizer/Catswords.Phantomizer.csproj new file mode 100644 index 0000000..dbdcea4 --- /dev/null +++ b/WelsonJS.Toolkit/Catswords.Phantomizer/Catswords.Phantomizer.csproj @@ -0,0 +1,7 @@ +๏ปฟ + + + netstandard2.0 + + + diff --git a/WelsonJS.Toolkit/Catswords.Phantomizer/LICENSE b/WelsonJS.Toolkit/Catswords.Phantomizer/LICENSE new file mode 100644 index 0000000..f144743 --- /dev/null +++ b/WelsonJS.Toolkit/Catswords.Phantomizer/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) Namhyeon Go , 2025 Catswords OSS and WelsonJS Contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/WelsonJS.Toolkit/Catswords.Phantomizer/README.md b/WelsonJS.Toolkit/Catswords.Phantomizer/README.md new file mode 100644 index 0000000..60451be --- /dev/null +++ b/WelsonJS.Toolkit/Catswords.Phantomizer/README.md @@ -0,0 +1,93 @@ +# Catswords.Phantomizer + +**Catswords.Phantomizer** is an HTTP-based dynamic-link library (DLL) loader designed for .NET applications. +It allows your application to fetch and load assemblies directly from your CDN (Azure Blob, S3, Cloudflare R2, etc.) at runtime, with optional GZip compression support. + +--- + +## ๐Ÿš€ Features + +* Load managed (`*.dll`) and native (`*.dll`) assemblies over HTTP +* Optional `.dll.gz` decompression for faster network delivery +* CDN-friendly URL structure +* Easy bootstrap through a small embedded loader + +--- + +## ๐Ÿ“ฆ How to Use + +### 1. Embed Phantomizer into your project + +Add `Catswords.Phantomizer.dll.gz` to your `Resources.resx` file. + +--- + +### 2. Initialize Phantomizer at application startup + +Place the following code inside your `Main` method, static constructor, or any early entry point: + +```csharp +static Program() { + InitializeAssemblyLoader(); +} + +private static void InitializeAssemblyLoader() +{ + byte[] gzBytes = Properties.Resources.Phantomizer; + + byte[] dllBytes; + using (var input = new MemoryStream(gzBytes)) + using (var gz = new GZipStream(input, CompressionMode.Decompress)) + using (var output = new MemoryStream()) + { + gz.CopyTo(output); + dllBytes = output.ToArray(); + } + + Assembly phantomAsm = Assembly.Load(dllBytes); + Type loaderType = phantomAsm.GetType("Catswords.Phantomizer.AssemblyLoader", true); + + loaderType.GetProperty("BaseUrl")?.SetValue(null, GetAppConfig("AssemblyBaseUrl")); // Set your CDN base URL + loaderType.GetProperty("AppName")?.SetValue(null, "WelsonJS"); // Set your application name + loaderType.GetMethod("Register")?.Invoke(null, null); + + var loadNativeModulesMethod = loaderType.GetMethod( + "LoadNativeModules", + BindingFlags.Public | BindingFlags.Static, + binder: null, + types: new[] { typeof(string), typeof(Version), typeof(string[]) }, + modifiers: null + ); + + if (loadNativeModulesMethod == null) + throw new InvalidOperationException("LoadNativeModules(string, Version, string[]) method not found."); + + loadNativeModulesMethod.Invoke(null, new object[] + { + "ChakraCore", + new Version(1, 13, 0, 0), + new[] { "ChakraCore.dll" } + }); +} +``` + +--- + +### 3. Upload your DLL files to a CDN + +Upload your managed and native assemblies to your CDN following the URL pattern below. + +#### ๐Ÿ“ URL Rules + +| Type | Example URL | Description | +| ------------------ | ----------------------------------------------------------------------------------- | ------------------------------- | +| Managed DLL | `https://example.cdn.tld/packages/managed/MyManagedLib/1.0.0.0/MyManagedLib.dll` | Normal .NET assembly | +| Managed DLL (GZip) | `https://example.cdn.tld/packages/managed/MyManagedLib/1.0.0.0/MyManagedLib.dll.gz` | GZip-compressed .NET assembly | +| Native DLL | `https://example.cdn.tld/packages/native/MyNativeLib/1.0.0.0/MyNativeLib.dll` | Native assembly | +| Native DLL (GZip) | `https://example.cdn.tld/packages/native/MyNativeLib/1.0.0.0/MyNativeLib.dll.gz` | GZip-compressed native assembly | + +--- + +### 4. ๐ŸŽ‰ Start loading assemblies over HTTP + +Once Phantomizer is initialized, your application will automatically fetch missing assemblies from your CDN. diff --git a/WelsonJS.Toolkit/WelsonJS.Launcher/Program.cs b/WelsonJS.Toolkit/WelsonJS.Launcher/Program.cs index bfac5b5..e42eae2 100644 --- a/WelsonJS.Toolkit/WelsonJS.Launcher/Program.cs +++ b/WelsonJS.Toolkit/WelsonJS.Launcher/Program.cs @@ -8,7 +8,9 @@ using System.Collections.Generic; using System.Configuration; using System.Diagnostics; using System.IO; +using System.IO.Compression; using System.Linq; +using System.Reflection; using System.Threading; using System.Windows.Forms; using WelsonJS.Launcher.Telemetry; @@ -33,10 +35,7 @@ namespace WelsonJS.Launcher _logger = new TraceLogger(); // load external assemblies - AssemblyLoader.BaseUrl = GetAppConfig("AssemblyBaseUrl"); - AssemblyLoader.Logger = _logger; - AssemblyLoader.Register(); - AssemblyLoader.LoadNativeModules("ChakraCore", new Version(1, 13, 0, 0), new[] { "ChakraCore.dll" }); + InitializeAssemblyLoader(); // telemetry try @@ -114,6 +113,48 @@ namespace WelsonJS.Launcher _mutex.Dispose(); } + private static void InitializeAssemblyLoader() + { + byte[] gzBytes = Properties.Resources.Phantomizer; + + byte[] dllBytes; + using (var input = new MemoryStream(gzBytes)) + using (var gz = new GZipStream(input, CompressionMode.Decompress)) + using (var output = new MemoryStream()) + { + gz.CopyTo(output); + dllBytes = output.ToArray(); + } + + Assembly phantomAsm = Assembly.Load(dllBytes); + Type loaderType = phantomAsm.GetType("Catswords.Phantomizer.AssemblyLoader", true); + + loaderType.GetProperty("BaseUrl")?.SetValue(null, GetAppConfig("AssemblyBaseUrl")); + loaderType.GetProperty("AppName")?.SetValue(null, "WelsonJS"); + loaderType.GetMethod("Register")?.Invoke(null, null); + + var loadNativeModulesMethod = loaderType.GetMethod( + "LoadNativeModules", + BindingFlags.Public | BindingFlags.Static, + binder: null, + types: new[] { typeof(string), typeof(Version), typeof(string[]) }, + modifiers: null + ); + + if (loadNativeModulesMethod == null) + { + throw new InvalidOperationException("LoadNativeModules(string, Version, string[]) method not found."); + } + + loadNativeModulesMethod.Invoke(null, new object[] + { + "ChakraCore", + new Version(1, 13, 0, 0), + new[] { "ChakraCore.dll" } + }); + } + + public static void RecordFirstDeployTime(string directory, string instanceId) { // get current time diff --git a/WelsonJS.Toolkit/WelsonJS.Launcher/Properties/Resources.Designer.cs b/WelsonJS.Toolkit/WelsonJS.Launcher/Properties/Resources.Designer.cs index b5f61ae..095137a 100644 --- a/WelsonJS.Toolkit/WelsonJS.Launcher/Properties/Resources.Designer.cs +++ b/WelsonJS.Toolkit/WelsonJS.Launcher/Properties/Resources.Designer.cs @@ -342,6 +342,16 @@ namespace WelsonJS.Launcher.Properties { } } + /// + /// System.Byte[] ํ˜•์‹์˜ ์ง€์—ญํ™”๋œ ๋ฆฌ์†Œ์Šค๋ฅผ ์ฐพ์Šต๋‹ˆ๋‹ค. + /// + internal static byte[] Phantomizer { + get { + object obj = ResourceManager.GetObject("Phantomizer", resourceCulture); + return ((byte[])(obj)); + } + } + /// /// https://github.com/gnh1201/welsonjs๊ณผ(์™€) ์œ ์‚ฌํ•œ ์ง€์—ญํ™”๋œ ๋ฌธ์ž์—ด์„ ์ฐพ์Šต๋‹ˆ๋‹ค. /// diff --git a/WelsonJS.Toolkit/WelsonJS.Launcher/Properties/Resources.resx b/WelsonJS.Toolkit/WelsonJS.Launcher/Properties/Resources.resx index d5d208a..5bc52ea 100644 --- a/WelsonJS.Toolkit/WelsonJS.Launcher/Properties/Resources.resx +++ b/WelsonJS.Toolkit/WelsonJS.Launcher/Properties/Resources.resx @@ -241,4 +241,7 @@ https://catswords.blob.core.windows.net/welsonjs/packages + + ..\Resources\Catswords.Phantomizer.dll.gz;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + \ No newline at end of file diff --git a/WelsonJS.Toolkit/WelsonJS.Launcher/Resources/Catswords.Phantomizer.dll.gz b/WelsonJS.Toolkit/WelsonJS.Launcher/Resources/Catswords.Phantomizer.dll.gz new file mode 100644 index 0000000000000000000000000000000000000000..3032827d43d340117b2d1f52cfa75f7f8bcc8384 GIT binary patch literal 6926 zcmV+p8}Z~HiwFqenKfwy07GGPb9ZlYWOFW1Xkl)2Z*6IMWpXZLY-|ASTXl3ZMG&96 zBo`}%q)>_n52cir;$A9HC@nNC&Vw|$wt+NP?vk$*EiMmtw}-pyH(8@297 z7VjU)II%I?8n%<8u~agbv+}V)GiDcZu}m)3-kXSxT4}R!uDL=>xjHuMAnMjUwCB~2 z-CWfB8Z8kEYfVI}f-n^C&VGOx%8o+LBe>3X^HZ+rEaCHmdF^-rMCD((=BoURL2oZ9 zz3+KupJWxP{sapBg$MQpD#!rnjVkEIyt!*0_5CZ0teUGnL&c7bwqvKrwQWatqN`7p zTOa=#Z8K{@uu5!pb*()^ZiDG&p6gC(BkAI!hZ~3vUWQ1czxOP-7kYZ@7u6@FUT`nn zC3Qu5TvBRVuXW}k3N5{)^u66)KVA*enj4^=XrU$#9YB&jvmgj{>(HU``D%C18IHdLe6GFjkn){-q=~td+#(1Dy9~qZ-mq zEn6`^!2FXuj(wem4t1bk4fz`kBfbF8m+Lhcq9e-t96})?wl_da>EilGg;`;H5xqEy zzCzeOhp7db^2{4wNJ-pV;&~zQY+1ru7*$ASAFi$PM|GL~VhhF>K{eMxhc5;9EL|Hs zXX*LlK8$$I(slL+=zY%83+U%8y`XVUd{M~Ncq88UVnCKb9fTNs@FS$=KfFr1N4)36 zV?4V>YkcA{-LKT9PS$#4qz)Gr&y0wG=Z05pN_AUz*Wi zBp6?Y{XVpaYpwWZ{=-)iVzCuZx0XdSW?&zPp)ms;*4rluz943_kc%%I37iv;Llg?< z=9r#VVJWvQhqmSCv!AbI2f>yuFei#m=o>(_S3Q{V<=Oe`#T(enkX`4cvAR+}*b@mI zwhE|o;wx~f%t3P`;PT>)V5yMWPkU#Y0q3m9K6&ovUw(PDHexjR!D-^G2{agfH-B2Y z)tWic-2!evSrlbnsN&`O3Q7}vHJ9$LYj;_1fpQo43xEi@{2Hv4on_CXh(2$;S*2CL zS4yNQX{B2$aatK*&f_cQreU>kuWG|u8FeW&`=<%0W=|Xz8TFF$H}F!&xb_*ovL`&& zDiBlNP`I-ykExV|C1;EVect-`YM`qE^Tt=_@frhSnh4c+{Sog%@imxVYu{g?+^_V` zTd#~+dWFz3wRoI0LCA`kOIA#cueQdB_@YMTqN(v0S53q}%d!D)!Jt|;OZ)953@rS$ zfU8^%xT`3jGCI5HA7yldAsOwj$mn22MuWeIjNvABKqdD2M#WT1dA+YOGtY{aEMVV1 zwNH%QQxkl3u}Hu#i4V!O!2_#G($S}qFcPe%)`eAGoq!U>OfJ;Q`LGsxs*CAnD3}47v2SjaE!(x69d)YvwlKzS`PQ4XxK7YNXp$JvMz{neftzdaBrZwET>27cKK)o$?ff;9pAqUjQWDG~;s6kR+n zHk;Nxl#fqC38P#{GVO^ye>bkse5SCv^=R|9K0CExZ(`S7HzO^ z3zcq6+v)ZrWvWNFUk4TMVWL&HzbFwa>vlL?B$n0fB}>GDy4_JC=F;OHWTR47KYx7< z^7B-VB%fVsIWA-G60TUP?h*U~cpk}JT`g2SUIRrTzRxsQ%~;y?#{4Zy+XGcI6&+b6 zipppBU9$*jb4?Wz|0MV>&vrWVVdTfX@Kn5)&xg$zY%bfD90$usH6vbIylU(P)m~g( zLts=H@dQ|b74+JAd@azzlP&uE^>y{4e=pbn^UD4CalNSD>IaZZw7neclKZnWz&tNw zTkvsJYi-F4qr_N1G5lcc#oRbBV=};`zeEOE=Q_~oY{kNCX#J!5w3+Q0;jO~6XOt_M z(VjJBbYAYm`JHVFKSFx&T;L5P=;bBU_rxVP9O!CC{SoNXJfJtoT7%_vs%^Q>Ig12&fqt*GP_0^Y zt?nMM0!l5)f+$-R*Btkg98$6#_baZ>wM%Pm396d4@op;;_j%JngBI{HjCv!%xoQ6( z^Vjhn>_dNFr{AEHy$rVy=m>mQ;4%XD2pwb?^o@r#Y#w+IoI67d`!(h_28H@@z}M8)0=`~g zUBC{3-}*NI{26fb$!n<-&;e|wgQ!b4j5}#leT&IXZ8N}!Jq){n8+1&lQ#adCL8PM6PdxET?Bb?SZi*bxj2&`meb&a-ksdbID5T_kn z>K!es>onw2-)n1OCFWde#FN!MRB)-hXDzJGJ%u`&t_zLnUiSsj(Xk`KOR8g$gc*b4y=18Fb}e= zyF^`~FDN;^o^LuF4>0WXFx*_=wHn2A8j&6ALFsj{hj+1O4d$E|WX@^8br)Yc!1x=2 zZzg;r%=pF?_$i|K6(4i96MS`n_lgY<`GfQh-Z4Y~u>%5zXgT6JGz(lqV5`6`ftw55 zT3|+c1vQ2fz~`fgwp4Io;0uPAqy@A?11r+v+CAE;w48QFU@dCa&b_-xGbfAoKES;>q>AwT;=J4Hg zwsu9}L9y^y$P_}4(pB0r;b-V3?L7~6QrPe+;H2jrx{22D><;*#@gd#e;;<8~dxlB7 zitdHv;#yWzX1cTQE{t+> z_yO%Z?F;=S?QCt#_ZHwz#)p7E1U>_tFn&hs^V;r|l-TX!!Y>VvzK_f$NO7vsgVaEE zdH^p)YXH}#MF7{QCBWZG;Ep0Q0zPj3g6}GDl9mPBpBnTSZHv~$1vcX3z7ep7?f_hf zUISc`-UnQsnmvuUD|Z8~MOy>5(GcJ!!cPFMFB)0}?kF%Ra8lq|0&f@CrlkNQ)S@p% z&3Zj-e1Sfrg|*|g$F!$4T~7TCjB9Zo{H!tD)pM=RTn~y4$i>Ge9-xlm2W|lV>|5G6 z1>Yq$&=Q)Zjce`LGmZ#r)Q;Wa;xM0(IFrIUc_*j8;XPT_XZZ=~H?e?><>fJWm7@4j z0w_V05K5R=IDMy-b#>$lqo$o4%$hqkQ-9Lg*{xc~lbO6}gDQ&TEup$IPM+&rzGWq9 z&p6z5)Ap5;x%8&(E7RJWTIoX8T$i@&>gn$rNc8W}-rC zx;E@-?H}mtC=0i?^>_95lgen1?b{(S(AL(GNYI>Q zwqWkC1C4FDMSpuTpQI5WiF`6|3N^NwmCd9k+LGDqU^2C{;w8E^Ys+TLT%O6I<~A#v zHN{A$aYHj_+L;vfnaOmkgZrkL9Bp+baw*!-%qwIE+Z@iIqiv>Xi)1#FhDYW|y_As!)AU58M{PHvxl6SJdD6_%S^7{E;!u~nN}V_ZD!59@+d5}CC{-`(ye)Xry4BeSz@p-Jj}i;^NNP`XY!To z{-lk0b=t6W+_HC`DbHSkB^UY+wb++(faVlsC+WvcXI?ldov)*wsv-R+|qc)9D?Gija#| zc8*ECx#^ruEr3L3H?w!BxaIVZ*w|pOz>5rb)JE4GXi;l&%cQLcOMUmHu@u%AyO*<# zhKk6B2#1x$nigt|0d@>$%M1{#EIY5zO_R1WlFZW1rkyjhEh{yqvsr3O<{gAF?KEyS zlFa3;QJ88=%XlW2=LOG%WU{+MkyC*W@5Zoz!e*&0lQ!HYGv=bLS^U`9X7SOosX0oW zwrQ3qclxr!5pPPoI4S9j!ukT(a7hB;A*`BqYc!e3i4|=H+vYvI%yHdDb5vbEGa4(l z5Vigam>>e1YBy8mCgtpk#GJC%$)Tc-F>H7xsyq%hJof|V{&&o&;Ekx7^VPj)Akqx`+(UJ?Y*g~yNhgn}w5-%&+m@{&rqJ>|MFcCT#*~6m zZHje;n*CTv@#ffXZI-wBK7*?0sP;?}o2r8Zafp*Kfi%HFqABUJshJgwr5st_a!5}}N9<*DWE(^>mhdUwZneR{ z9zC_+w6lb}PiM{8pBk}H!S2|lkjy%>T$m)^Tjc=9-iQb)PU-wnr#dnqsj{ph;gCXeGPafD6;|3Hia3VO z7sZQs0{6H+%gPhno@XDaQ&T)8y994MRv|B2cMtyfW7^e-^)NR*Uc%L7MkcOq4ZSv; zXpQ5JRyrq(YfU9--kvBjB=p^xK|5(rxRWd`WlEU&_H4FHTVp#&I5K&`yK-icqFq|a z!N;Ug8pIn^=p_r^$kO0o6;L1QVah-vFPu2OlgB6pi7Y-QEJK8dm98`n!U=1Y+2frLw=#J+Y(<#zP2C2)DMbV34}boHcF zcwP7IPEE8Yz7GFEe_$ibgZ(kUUD1ZG1mKF5m6{?eR(gRG(}S{BJIUOO9%DOx&tH`q z*Bc;5c~~u1l###EfBRyjyCFG8Jm?GCK+B++?u*Zsd z@uw|}QM_V|HA}je!|$Elf8AexWCz-)ZF-J1(uN%6VkWs8pv^p4;<@4|qBF}G+cixG zx4OM!u1BWiYiX+-<+>O**0kL3Eaa*7Z~e!T4($xhWB3&F!bF{S<2r41lr;w%WuwSq zRjr8Dq|9ZQXU%!qI%|$jm7A%(((;a3GWD-(nLP539q9p!~RC7~KI&TjZ2X?6!Cm3F3ic}Ra-EOuN8cMDU?qf+xK(=?WxSMD(+%VM;$ z*NW46{n03Eb*h%X;T1~s$nqGMWZ$`z^j%1p-f3GydbYWgtSB#Q+GGGNyorvfO_uHd zySk9ldGR<+^zhchky1;;)jCJEyNpCBucBPivle?o-G53W3`*MWT-?goOTQ7-0pw*j zFYP`5xsPTYVP+Q0=7GZB_vSwsb@Lh9zFGmo$#d`0TC&PVPFeR%jdLX+;kdo1W>ZL} zczj;@lA#nC1)dUpSvksR{v40Sz0@j{anj&#$#Zn)?UXJzwD@LfuI_f3EFIu&?v;j? z|1F75@MYsK#hHdn>qc_3Fsv>G)|iI(fD)hUPl%5S=`a z+ZT@d!_^Dx)z#6>=Zg+#)p!E<=|_)tMY}L)HHJX%t9+;y0fBC}qS8SvY|Iy(yhE$T zUp8^i8uEz(Z;XJF4n@8g#5}rD2U4%A!%w{UUC&cpz3{@&tb6@hbbA?U>*&_#72Tde z*WCV4bo=V)*41JaT449q0rG&rEc`LA7Qh30AhMu87&WW)`63xDYDPz;9*yo2EkrjD z#Wa}rx`uYYi@;Dwz)(YV;NeUkz~tLOG>Oot->sF*Xej34`M)2T{1~$VgB@61y(pX( zHI*8@H1LEPI=VTOMkc=saF9kLli&G>`v77Nn02Je@O$ba4Z#4r^QXu@8vGgnhIrHk z0`q7dZBhKt=?!U-c{oIM65oA%frodm`Q?!nUfEp!904uiNw3D3&R`w}oS)i!+VZ+l zts6)N-D5=8Kv_pOf*vE%sv7}RRVeeK)S)bl5<^)Eh5uMjV!TeYgKen}k|$UfX`Lt1 zz(3E23BHJS%@^HNtHv*a2!Nn|LIf9%CVhmNA^b4d6QJsV=Ki;sMftB~`t{l^?c`Wb z#d}J5!{KOf`;mOOYcJXcZqCLe({KKmsqh+ z45ABaG~ev+0jWwOe;n_Evv24 zG_=~PO)W!1=1QwJH?6ToYPICh5PrmTpQST99821!oAD&hM!7J7vP!X4{rXyivMfqh zKgz1*w(|c`DnEUR_C(W32k!CEWk%cKcR#qyHqE2Au#UDhw;OQak?qpvob7sZX1k4d zecOF_>5U)lf7*5%X7U>q2DckGvv{?;le68Hf^3{DAA7E4eLXEAA-jxzhWQ&N>qO_13+)&eU|j$TXEcE7KtR0Jn)+ z@Y~cqSH>v6YT{?+O`wrBbKj}uxfe#-jqgxwCF?4U-7fdN6x&pO5%iaJHc_BL=N405 zCGgXXzD>m?9!_MyawUFSLx>WhOCXfg&9rA%!bi7?=JoA zWb9s-pHX9%Y|s588&sTd_g1fT_t - @@ -171,6 +170,7 @@ + diff --git a/WelsonJS.Toolkit/WelsonJS.Toolkit.sln b/WelsonJS.Toolkit/WelsonJS.Toolkit.sln index 38c0f9a..74d1463 100644 --- a/WelsonJS.Toolkit/WelsonJS.Toolkit.sln +++ b/WelsonJS.Toolkit/WelsonJS.Toolkit.sln @@ -17,6 +17,8 @@ Project("{778DAE3C-4631-46EA-AA77-85C1314464D9}") = "WelsonJS.Cryptography", "We EndProject Project("{778DAE3C-4631-46EA-AA77-85C1314464D9}") = "WelsonJS.Cryptography.Test", "WelsonJS.Cryptography.Test\WelsonJS.Cryptography.Test.vbproj", "{C65EC34B-71C7-47CF-912E-D304283EB412}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Catswords.Phantomizer", "Catswords.Phantomizer\Catswords.Phantomizer.csproj", "{59C67003-C14E-4703-927F-318BFF15F903}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -81,6 +83,14 @@ Global {C65EC34B-71C7-47CF-912E-D304283EB412}.Release|Any CPU.Build.0 = Release|Any CPU {C65EC34B-71C7-47CF-912E-D304283EB412}.Release|x86.ActiveCfg = Release|x86 {C65EC34B-71C7-47CF-912E-D304283EB412}.Release|x86.Build.0 = Release|x86 + {59C67003-C14E-4703-927F-318BFF15F903}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {59C67003-C14E-4703-927F-318BFF15F903}.Debug|Any CPU.Build.0 = Debug|Any CPU + {59C67003-C14E-4703-927F-318BFF15F903}.Debug|x86.ActiveCfg = Debug|Any CPU + {59C67003-C14E-4703-927F-318BFF15F903}.Debug|x86.Build.0 = Debug|Any CPU + {59C67003-C14E-4703-927F-318BFF15F903}.Release|Any CPU.ActiveCfg = Release|Any CPU + {59C67003-C14E-4703-927F-318BFF15F903}.Release|Any CPU.Build.0 = Release|Any CPU + {59C67003-C14E-4703-927F-318BFF15F903}.Release|x86.ActiveCfg = Release|Any CPU + {59C67003-C14E-4703-927F-318BFF15F903}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From 136693127384c65fcf60912c1ab4e9ae13de2350 Mon Sep 17 00:00:00 2001 From: "Namhyeon, Go" Date: Mon, 8 Dec 2025 01:00:23 +0900 Subject: [PATCH 02/12] Update README.md --- WelsonJS.Toolkit/Catswords.Phantomizer/README.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/WelsonJS.Toolkit/Catswords.Phantomizer/README.md b/WelsonJS.Toolkit/Catswords.Phantomizer/README.md index 60451be..88da2b9 100644 --- a/WelsonJS.Toolkit/Catswords.Phantomizer/README.md +++ b/WelsonJS.Toolkit/Catswords.Phantomizer/README.md @@ -28,7 +28,9 @@ Place the following code inside your `Main` method, static constructor, or any e ```csharp static Program() { + // ... InitializeAssemblyLoader(); + // ... } private static void InitializeAssemblyLoader() @@ -91,3 +93,17 @@ Upload your managed and native assemblies to your CDN following the URL pattern ### 4. ๐ŸŽ‰ Start loading assemblies over HTTP Once Phantomizer is initialized, your application will automatically fetch missing assemblies from your CDN. + +--- + +## Report abuse +* [GitHub Security Advisories (gnh1201/welsonjs)](https://github.com/gnh1201/welsonjs/security) +* [abuse@catswords.re.kr](mailto:abuse@catswords.re.kr) + +## Join the community +I am always open. Collaboration, opportunities, and community activities are all welcome. + +* ActivityPub [@catswords_oss@catswords.social](https://catswords.social/@catswords_oss) +* XMPP [catswords@conference.omemo.id](xmpp:catswords@conference.omemo.id?join) +* [Join Catswords OSS on Microsoft Teams (teams.live.com)](https://teams.live.com/l/community/FEACHncAhq8ldnojAI) +* [Join Catswords OSS #welsonjs on Discord (discord.gg)](https://discord.gg/XKG5CjtXEj) From c357d6f944034bf477147a58e7c9879ed6903c0c Mon Sep 17 00:00:00 2001 From: "Namhyeon, Go" Date: Mon, 8 Dec 2025 01:13:08 +0900 Subject: [PATCH 03/12] Add description: Catswords.Phantomizer Add description: Catswords.Phantomizer --- .appveyor.yml | 4 ++-- .../Catswords.Phantomizer/Catswords.Phantomizer.csproj | 7 +++++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index b68237e..6ae1b2c 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -24,8 +24,8 @@ after_build: - cmd: mkdir artifacts #- cmd: xcopy /s /y WelsonJS.Toolkit\WelsonJS.Toolkit\bin\x86\%CONFIGURATION%\* artifacts\ - cmd: xcopy /s /y WelsonJS.Toolkit\WelsonJS.Service\bin\x86\%CONFIGURATION%\* artifacts\ - - cmd: xcopy /s /y WelsonJS.Toolkit\WelsonJS.Launcher\bin\x86\%CONFIGURATION%\* artifacts\ - - cmd: xcopy /s /y WelsonJS.Toolkit\Catswords.Phantomizer\bin\x86\%CONFIGURATION%\* artifacts\ + - cmd: xcopy /s /y WelsonJS.Toolkit\WelsonJS.Launcher\bin\%CONFIGURATION%\* artifacts\ + - cmd: xcopy /s /y WelsonJS.Toolkit\Catswords.Phantomizer\bin\%CONFIGURATION%\netstandard2.0\* artifacts\ - cmd: nuget pack WelsonJS.Toolkit\WelsonJS.Toolkit\ -properties Configuration=%CONFIGURATION% -properties Platform=x86 -OutputDirectory artifacts\ - ps: Start-BitsTransfer -Source "https://catswords.blob.core.windows.net/welsonjs/welsonjs_setup_unsigned.exe" -Destination "artifacts\welsonjs_setup.exe" - ps: Start-BitsTransfer -Source "https://catswords.blob.core.windows.net/welsonjs/chakracore-build/x86_release/ChakraCore.dll" -Destination "artifacts\ChakraCore.dll" diff --git a/WelsonJS.Toolkit/Catswords.Phantomizer/Catswords.Phantomizer.csproj b/WelsonJS.Toolkit/Catswords.Phantomizer/Catswords.Phantomizer.csproj index dbdcea4..2d69ee3 100644 --- a/WelsonJS.Toolkit/Catswords.Phantomizer/Catswords.Phantomizer.csproj +++ b/WelsonJS.Toolkit/Catswords.Phantomizer/Catswords.Phantomizer.csproj @@ -2,6 +2,13 @@ netstandard2.0 + Catswords Research + Namhyeon Go, 2025 Catswords OSS and WelsonJS Contributors + https://github.com/gnh1201/welsonjs + git + https://github.com/gnh1201/welsonjs + loader + Catswords.Phantomizer is an HTTP-based dynamic-link library (DLL) loader designed for .NET applications. It allows your application to fetch and load assemblies directly from your CDN (Azure Blob, S3, Cloudflare R2, etc.) at runtime, with optional GZip compression support. From 3b588c3446bc8c0b907b2dd77c53829559316db2 Mon Sep 17 00:00:00 2001 From: "Namhyeon, Go" Date: Mon, 8 Dec 2025 01:15:25 +0900 Subject: [PATCH 04/12] Update .appveyor.yml --- .appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.appveyor.yml b/.appveyor.yml index 6ae1b2c..65114a4 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -24,7 +24,7 @@ after_build: - cmd: mkdir artifacts #- cmd: xcopy /s /y WelsonJS.Toolkit\WelsonJS.Toolkit\bin\x86\%CONFIGURATION%\* artifacts\ - cmd: xcopy /s /y WelsonJS.Toolkit\WelsonJS.Service\bin\x86\%CONFIGURATION%\* artifacts\ - - cmd: xcopy /s /y WelsonJS.Toolkit\WelsonJS.Launcher\bin\%CONFIGURATION%\* artifacts\ + - cmd: xcopy /s /y WelsonJS.Toolkit\WelsonJS.Launcher\bin\x86\%CONFIGURATION%\* artifacts\ - cmd: xcopy /s /y WelsonJS.Toolkit\Catswords.Phantomizer\bin\%CONFIGURATION%\netstandard2.0\* artifacts\ - cmd: nuget pack WelsonJS.Toolkit\WelsonJS.Toolkit\ -properties Configuration=%CONFIGURATION% -properties Platform=x86 -OutputDirectory artifacts\ - ps: Start-BitsTransfer -Source "https://catswords.blob.core.windows.net/welsonjs/welsonjs_setup_unsigned.exe" -Destination "artifacts\welsonjs_setup.exe" From c68b73ce7b6cdd6fd94df95ad1d72759ca626a8c Mon Sep 17 00:00:00 2001 From: "Namhyeon, Go" Date: Mon, 8 Dec 2025 01:20:37 +0900 Subject: [PATCH 05/12] Update Catswords.Phantomizer.csproj --- .../Catswords.Phantomizer/Catswords.Phantomizer.csproj | 1 + 1 file changed, 1 insertion(+) diff --git a/WelsonJS.Toolkit/Catswords.Phantomizer/Catswords.Phantomizer.csproj b/WelsonJS.Toolkit/Catswords.Phantomizer/Catswords.Phantomizer.csproj index 2d69ee3..7f5a53b 100644 --- a/WelsonJS.Toolkit/Catswords.Phantomizer/Catswords.Phantomizer.csproj +++ b/WelsonJS.Toolkit/Catswords.Phantomizer/Catswords.Phantomizer.csproj @@ -9,6 +9,7 @@ https://github.com/gnh1201/welsonjs loader Catswords.Phantomizer is an HTTP-based dynamic-link library (DLL) loader designed for .NET applications. It allows your application to fetch and load assemblies directly from your CDN (Azure Blob, S3, Cloudflare R2, etc.) at runtime, with optional GZip compression support. + Namhyeon Go, 2025 Catswords OSS and WelsonJS Contributors From aafab2032c58b12717f587bf510e106083c8d1d1 Mon Sep 17 00:00:00 2001 From: "Namhyeon, Go" Date: Mon, 8 Dec 2025 01:31:37 +0900 Subject: [PATCH 06/12] Update README.md --- WelsonJS.Toolkit/Catswords.Phantomizer/README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/WelsonJS.Toolkit/Catswords.Phantomizer/README.md b/WelsonJS.Toolkit/Catswords.Phantomizer/README.md index 88da2b9..c95bb63 100644 --- a/WelsonJS.Toolkit/Catswords.Phantomizer/README.md +++ b/WelsonJS.Toolkit/Catswords.Phantomizer/README.md @@ -96,6 +96,11 @@ Once Phantomizer is initialized, your application will automatically fetch missi --- +## Download the pre-compiled `Catswords.Phantomizer.dll.gz` file +* https://catswords.blob.core.windows.net/welsonjs/packages/managed/Catswords.Phantomizer/1.0.0.0/Catswords.Phantomizer.dll.gz + +--- + ## Report abuse * [GitHub Security Advisories (gnh1201/welsonjs)](https://github.com/gnh1201/welsonjs/security) * [abuse@catswords.re.kr](mailto:abuse@catswords.re.kr) From c1448ead32238336178b3b115e840e40186111f8 Mon Sep 17 00:00:00 2001 From: "Namhyeon, Go" Date: Mon, 8 Dec 2025 01:33:33 +0900 Subject: [PATCH 07/12] Update README.md --- WelsonJS.Toolkit/Catswords.Phantomizer/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/WelsonJS.Toolkit/Catswords.Phantomizer/README.md b/WelsonJS.Toolkit/Catswords.Phantomizer/README.md index c95bb63..e16a0ab 100644 --- a/WelsonJS.Toolkit/Catswords.Phantomizer/README.md +++ b/WelsonJS.Toolkit/Catswords.Phantomizer/README.md @@ -11,6 +11,7 @@ It allows your application to fetch and load assemblies directly from your CDN ( * Optional `.dll.gz` decompression for faster network delivery * CDN-friendly URL structure * Easy bootstrap through a small embedded loader +* Loader is implemented using **pure .NET BCL only**, ensuring stable operation without external dependencies --- From 28776d7cad49138940fa66559c47bb5f939a7d4e Mon Sep 17 00:00:00 2001 From: "Namhyeon, Go" Date: Mon, 8 Dec 2025 01:34:49 +0900 Subject: [PATCH 08/12] Update Catswords.Phantomizer.dll.gz --- .../Resources/Catswords.Phantomizer.dll.gz | Bin 6926 -> 16865 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/WelsonJS.Toolkit/WelsonJS.Launcher/Resources/Catswords.Phantomizer.dll.gz b/WelsonJS.Toolkit/WelsonJS.Launcher/Resources/Catswords.Phantomizer.dll.gz index 3032827d43d340117b2d1f52cfa75f7f8bcc8384..57569a7f8108ac08a6722c3e9530a5691431d08b 100644 GIT binary patch literal 16865 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 literal 6926 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 Date: Mon, 8 Dec 2025 01:53:49 +0900 Subject: [PATCH 09/12] Fix namespace bug when use the assembly loader Fix namespace bug when use the assembly loader --- WelsonJS.Toolkit/WelsonJS.Launcher/Program.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/WelsonJS.Toolkit/WelsonJS.Launcher/Program.cs b/WelsonJS.Toolkit/WelsonJS.Launcher/Program.cs index e42eae2..965117a 100644 --- a/WelsonJS.Toolkit/WelsonJS.Launcher/Program.cs +++ b/WelsonJS.Toolkit/WelsonJS.Launcher/Program.cs @@ -130,6 +130,7 @@ namespace WelsonJS.Launcher Type loaderType = phantomAsm.GetType("Catswords.Phantomizer.AssemblyLoader", true); loaderType.GetProperty("BaseUrl")?.SetValue(null, GetAppConfig("AssemblyBaseUrl")); + loaderType.GetProperty("LoaderNamespace")?.SetValue(null, typeof(Program).Namespace); loaderType.GetProperty("AppName")?.SetValue(null, "WelsonJS"); loaderType.GetMethod("Register")?.Invoke(null, null); From ec79f1ab069ec5c06139ba0740aa1e3e7b096f53 Mon Sep 17 00:00:00 2001 From: "Namhyeon, Go" Date: Mon, 8 Dec 2025 01:55:10 +0900 Subject: [PATCH 10/12] Update README.md --- WelsonJS.Toolkit/Catswords.Phantomizer/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/WelsonJS.Toolkit/Catswords.Phantomizer/README.md b/WelsonJS.Toolkit/Catswords.Phantomizer/README.md index e16a0ab..59012cd 100644 --- a/WelsonJS.Toolkit/Catswords.Phantomizer/README.md +++ b/WelsonJS.Toolkit/Catswords.Phantomizer/README.md @@ -51,6 +51,7 @@ private static void InitializeAssemblyLoader() Type loaderType = phantomAsm.GetType("Catswords.Phantomizer.AssemblyLoader", true); loaderType.GetProperty("BaseUrl")?.SetValue(null, GetAppConfig("AssemblyBaseUrl")); // Set your CDN base URL + loaderType.GetProperty("LoaderNamespace")?.SetValue(null, typeof(Program).Namespace); loaderType.GetProperty("AppName")?.SetValue(null, "WelsonJS"); // Set your application name loaderType.GetMethod("Register")?.Invoke(null, null); From ac6df725f49e27f02a1e0d8a27eed5c5fce9712d Mon Sep 17 00:00:00 2001 From: "Namhyeon, Go" Date: Mon, 8 Dec 2025 02:06:17 +0900 Subject: [PATCH 11/12] Update README.md --- WelsonJS.Toolkit/Catswords.Phantomizer/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/WelsonJS.Toolkit/Catswords.Phantomizer/README.md b/WelsonJS.Toolkit/Catswords.Phantomizer/README.md index 59012cd..5a3c4ba 100644 --- a/WelsonJS.Toolkit/Catswords.Phantomizer/README.md +++ b/WelsonJS.Toolkit/Catswords.Phantomizer/README.md @@ -12,6 +12,7 @@ It allows your application to fetch and load assemblies directly from your CDN ( * CDN-friendly URL structure * Easy bootstrap through a small embedded loader * Loader is implemented using **pure .NET BCL only**, ensuring stable operation without external dependencies +* Built-in **code-signing verification** support to ensure assemblies are trusted and tamper-free --- From 037e6924324085ce5f347352dd75b9ec10643ccc Mon Sep 17 00:00:00 2001 From: "Namhyeon, Go" Date: Mon, 8 Dec 2025 02:13:16 +0900 Subject: [PATCH 12/12] Update README.md --- WelsonJS.Toolkit/Catswords.Phantomizer/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/WelsonJS.Toolkit/Catswords.Phantomizer/README.md b/WelsonJS.Toolkit/Catswords.Phantomizer/README.md index 5a3c4ba..0b223d7 100644 --- a/WelsonJS.Toolkit/Catswords.Phantomizer/README.md +++ b/WelsonJS.Toolkit/Catswords.Phantomizer/README.md @@ -99,8 +99,8 @@ Once Phantomizer is initialized, your application will automatically fetch missi --- -## Download the pre-compiled `Catswords.Phantomizer.dll.gz` file -* https://catswords.blob.core.windows.net/welsonjs/packages/managed/Catswords.Phantomizer/1.0.0.0/Catswords.Phantomizer.dll.gz +## Download the pre-compiled file +* [Download Catswords.Phantomizer.dll.gz (catswords.blob.core.windows.net)](https://catswords.blob.core.windows.net/welsonjs/packages/managed/Catswords.Phantomizer/1.0.0.0/Catswords.Phantomizer.dll.gz) ---