using System.Diagnostics;
using System.Security.Cryptography;
using System.Text.Json;
using AngleSharp.Html.Parser;
using Jint;
using XFESystem.Browser;
var root = Path.GetFullPath(args.Length > 0 ? args[0] : ".");
var assetRoot = Path.Combine(root, "assets/Browser/Monaco/0.52.2");
var run = Path.Combine(root, "build/BrowserProbe", "Run-" + DateTimeOffset.UtcNow.ToUnixTimeMilliseconds());
Directory.CreateDirectory(run);
var loaderPath = Path.Combine(assetRoot, "min/vs/loader.js");
var mainPath = Path.Combine(assetRoot, "min/vs/editor/editor.main.js");
var loader = File.ReadAllText(loaderPath);
var main = File.ReadAllText(mainPath);
var stages = new List<object>();
JavaScriptRuntime Create(bool expanded = false)
{
var limits = expanded ? new BrowserLimits {
MaximumScriptCharacters = 1_048_576, MaximumScriptMemoryBytes = 268_435_456,
MaximumStatements = 10_000_000, MaximumRecursionDepth = 256, ScriptTimeout = TimeSpan.FromSeconds(30)
} : new BrowserLimits();
var runtime = new JavaScriptRuntime(limits);
var document = new HtmlParser().ParseDocument("<!doctype html><html><head></head><body><div id='container' style='width:800px;height:600px'></div></body></html>");
_ = new DomBridge(runtime, document, new Uri("http://xfe.test/Monaco/"), limits);
return runtime;
}
bool Step(JavaScriptRuntime runtime, string name, string source, bool bypassCharacterLimit = false)
{
var timer = Stopwatch.StartNew();
bool success;
string error;
try
{
if (bypassCharacterLimit) { runtime.Engine.Execute(source); success = true; error = ""; }
else { var result = runtime.Evaluate(source); success = result.Success; error = result.Error; }
}
catch (Exception ex) { success = false; error = ex.ToString(); }
stages.Add(new { Name = name, SourceCharacters = source.Length, BypassCharacterLimit = bypassCharacterLimit,
Success = success, Error = error, ElapsedMilliseconds = timer.Elapsed.TotalMilliseconds });
Console.WriteLine(JsonSerializer.Serialize(new { Name = name, Success = success, Error = error.Length > 1500 ? error[..1500] : error }));
return success;
}
var current = Create();
Step(current, "ProductionProfile.RealLoader", loader);
Step(current, "ProductionProfile.RealEditorBundle", main);
var expanded = Create(true);
Step(expanded, "ExpandedProbe.RealLoader", loader);
Step(expanded, "ExpandedProbe.RealEditorBundle", main, true);
Step(expanded, "ExpandedProbe.RequireEditor", "require(['vs/editor/editor.main'],function(){globalThis.__xfeLoaded=true;},function(e){throw e;});");
Step(expanded, "ExpandedProbe.CreateRealEditor", "globalThis.__xfeEditor=monaco.editor.create(document.getElementById('container'),{value:'const answer = 42;',language:'javascript',automaticLayout:false});");
var withNavigator = Create(true);
Step(withNavigator, "NavigatorProbe.Platform", "globalThis.navigator={userAgent:'XFESystem/MonacoProbe',platform:'XFESystem',language:'en-US',languages:['en-US'],hardwareConcurrency:1,onLine:false};globalThis.location={href:'http://xfe.test/Monaco/',protocol:'http:',hostname:'xfe.test',host:'xfe.test',origin:'http://xfe.test',pathname:'/Monaco/',search:'',hash:''};");
Step(withNavigator, "NavigatorProbe.RealLoader", loader);
Step(withNavigator, "NavigatorProbe.RealEditorBundle", main, true);
var withoutCss = Create(true);
Step(withoutCss, "NoCssProbe.Platform", "globalThis.navigator={userAgent:'XFESystem/MonacoProbe',platform:'XFESystem',language:'en-US',languages:['en-US'],hardwareConcurrency:1,onLine:false};globalThis.location={href:'http://xfe.test/Monaco/',protocol:'http:',hostname:'xfe.test',host:'xfe.test',origin:'http://xfe.test',pathname:'/Monaco/',search:'',hash:''};");
Step(withoutCss, "NoCssProbe.RealLoader", loader);
Step(withoutCss, "NoCssProbe.OfficialCssPluginDisabledForDiagnosis", "require.config({'vs/css':{disabled:true}});");
Step(withoutCss, "NoCssProbe.RealEditorBundle", main, true);
var platform = "globalThis.navigator={userAgent:'XFESystem/MonacoProbe',platform:'XFESystem',language:'en-US',languages:['en-US'],hardwareConcurrency:1,onLine:false};globalThis.location={href:'http://xfe.test/Monaco/',protocol:'http:',hostname:'xfe.test',host:'xfe.test',origin:'http://xfe.test',pathname:'/Monaco/',search:'',hash:''};document.queryCommandSupported=function(command){return false;};";
var tasks = File.ReadAllText(Path.Combine(root, "Tools/BrowserCompatibility/ProbeTasks.js"));
var events = File.ReadAllText(Path.Combine(root, "Tools/BrowserCompatibility/ProbeWindowEvents.js"));
var tokens = File.ReadAllText(Path.Combine(root, "Tools/BrowserCompatibility/ProbeDomTokens.js"));
foreach (var diagnostic in new[] { (Name:"TaskProbe", Script:tasks), (Name:"WindowEventProbe", Script:tasks + "\n" + events), (Name:"DomTokenProbe", Script:tasks + "\n" + events + "\n" + tokens) })
{
var candidate = Create(true);
Step(candidate, diagnostic.Name + ".Platform", platform + diagnostic.Script);
Step(candidate, diagnostic.Name + ".RealLoader", loader);
Step(candidate, diagnostic.Name + ".OfficialCssPluginDisabledForDiagnosis", "require.config({'vs/css':{disabled:true}});");
if (Step(candidate, diagnostic.Name + ".RealEditorBundle", main, true))
{
Step(candidate, diagnostic.Name + ".RequireRealEditor", "require(['vs/editor/editor.main'],function(){globalThis.__xfeLoaded=true;},function(e){throw e;});__xfeCheckpoint();if(!globalThis.__xfeLoaded)throw new Error('Real editor.main has not completed');");
Step(candidate, diagnostic.Name + ".CreateRealEditor", "globalThis.__xfeEditor=monaco.editor.create(document.getElementById('container'),{value:'const answer = 42;',language:'javascript',automaticLayout:false});", true);
}
}
var resultPath = Path.Combine(run, "Result.json");
var result = new {
Kind = "RealMonacoJintCompatibilityProbe", MonacoVersion = "0.52.2", JintVersion = "4.11.0",
ProductionBrowserModified = false, ProbeOnly = true, NativeGuestTested = false, HostBrowserUsed = false,
FakeMonacoObjects = false, ExpandedBudgetIsProductionSupport = false,
LoaderSha256 = Convert.ToHexStringLower(SHA256.HashData(File.ReadAllBytes(loaderPath))),
EditorBundleSha256 = Convert.ToHexStringLower(SHA256.HashData(File.ReadAllBytes(mainPath))),
Baseline = Directory.GetFiles(Path.Combine(root, "build/BrowserProbe/InitialBaseline"), "*.cs")
.Select(p => new { Name = Path.GetFileName(p), Sha256 = Convert.ToHexStringLower(SHA256.HashData(File.ReadAllBytes(p))) }).ToArray(),
Stages = stages
};
File.WriteAllText(resultPath, JsonSerializer.Serialize(result, new JsonSerializerOptions { WriteIndented = true }));
Console.WriteLine(resultPath);
using System.Diagnostics;
using System.Security.Cryptography;
using System.Text.Json;
using AngleSharp.Html.Parser;
using Jint;
using XFESystem.Browser;
var root = Path.GetFullPath(args.Length > 0 ? args[0] : ".");
var assetRoot = Path.Combine(root, "assets/Browser/Monaco/0.52.2");
var run = Path.Combine(root, "build/BrowserProbe", "Run-" + DateTimeOffset.UtcNow.ToUnixTimeMilliseconds());
Directory.CreateDirectory(run);
var loaderPath = Path.Combine(assetRoot, "min/vs/loader.js");
var mainPath = Path.Combine(assetRoot, "min/vs/editor/editor.main.js");
var loader = File.ReadAllText(loaderPath);
var main = File.ReadAllText(mainPath);
var stages = new List<object>();
JavaScriptRuntime Create(bool expanded = false)
{
var limits = expanded ? new BrowserLimits {
MaximumScriptCharacters = 1_048_576, MaximumScriptMemoryBytes = 268_435_456,
MaximumStatements = 10_000_000, MaximumRecursionDepth = 256, ScriptTimeout = TimeSpan.FromSeconds(30)
} : new BrowserLimits();
var runtime = new JavaScriptRuntime(limits);
var document = new HtmlParser().ParseDocument("<!doctype html><html><head></head><body><div id='container' style='width:800px;height:600px'></div></body></html>");
_ = new DomBridge(runtime, document, new Uri("http://xfe.test/Monaco/"), limits);
return runtime;
}
bool Step(JavaScriptRuntime runtime, string name, string source, bool bypassCharacterLimit = false)
{
var timer = Stopwatch.StartNew();
bool success;
string error;
try
{
if (bypassCharacterLimit) { runtime.Engine.Execute(source); success = true; error = ""; }
else { var result = runtime.Evaluate(source); success = result.Success; error = result.Error; }
}
catch (Exception ex) { success = false; error = ex.ToString(); }
stages.Add(new { Name = name, SourceCharacters = source.Length, BypassCharacterLimit = bypassCharacterLimit,
Success = success, Error = error, ElapsedMilliseconds = timer.Elapsed.TotalMilliseconds });
Console.WriteLine(JsonSerializer.Serialize(new { Name = name, Success = success, Error = error.Length > 1500 ? error[..1500] : error }));
return success;
}
var current = Create();
Step(current, "ProductionProfile.RealLoader", loader);
Step(current, "ProductionProfile.RealEditorBundle", main);
var expanded = Create(true);
Step(expanded, "ExpandedProbe.RealLoader", loader);
Step(expanded, "ExpandedProbe.RealEditorBundle", main, true);
Step(expanded, "ExpandedProbe.RequireEditor", "require(['vs/editor/editor.main'],function(){globalThis.__xfeLoaded=true;},function(e){throw e;});");
Step(expanded, "ExpandedProbe.CreateRealEditor", "globalThis.__xfeEditor=monaco.editor.create(document.getElementById('container'),{value:'const answer = 42;',language:'javascript',automaticLayout:false});");
var withNavigator = Create(true);
Step(withNavigator, "NavigatorProbe.Platform", "globalThis.navigator={userAgent:'XFESystem/MonacoProbe',platform:'XFESystem',language:'en-US',languages:['en-US'],hardwareConcurrency:1,onLine:false};globalThis.location={href:'http://xfe.test/Monaco/',protocol:'http:',hostname:'xfe.test',host:'xfe.test',origin:'http://xfe.test',pathname:'/Monaco/',search:'',hash:''};");
Step(withNavigator, "NavigatorProbe.RealLoader", loader);
Step(withNavigator, "NavigatorProbe.RealEditorBundle", main, true);
var withoutCss = Create(true);
Step(withoutCss, "NoCssProbe.Platform", "globalThis.navigator={userAgent:'XFESystem/MonacoProbe',platform:'XFESystem',language:'en-US',languages:['en-US'],hardwareConcurrency:1,onLine:false};globalThis.location={href:'http://xfe.test/Monaco/',protocol:'http:',hostname:'xfe.test',host:'xfe.test',origin:'http://xfe.test',pathname:'/Monaco/',search:'',hash:''};");
Step(withoutCss, "NoCssProbe.RealLoader", loader);
Step(withoutCss, "NoCssProbe.OfficialCssPluginDisabledForDiagnosis", "require.config({'vs/css':{disabled:true}});");
Step(withoutCss, "NoCssProbe.RealEditorBundle", main, true);
var platform = "globalThis.navigator={userAgent:'XFESystem/MonacoProbe',platform:'XFESystem',language:'en-US',languages:['en-US'],hardwareConcurrency:1,onLine:false};globalThis.location={href:'http://xfe.test/Monaco/',protocol:'http:',hostname:'xfe.test',host:'xfe.test',origin:'http://xfe.test',pathname:'/Monaco/',search:'',hash:''};document.queryCommandSupported=function(command){return false;};";
var tasks = File.ReadAllText(Path.Combine(root, "Tools/BrowserCompatibility/ProbeTasks.js"));
var events = File.ReadAllText(Path.Combine(root, "Tools/BrowserCompatibility/ProbeWindowEvents.js"));
var tokens = File.ReadAllText(Path.Combine(root, "Tools/BrowserCompatibility/ProbeDomTokens.js"));
foreach (var diagnostic in new[] { (Name:"TaskProbe", Script:tasks), (Name:"WindowEventProbe", Script:tasks + "\n" + events), (Name:"DomTokenProbe", Script:tasks + "\n" + events + "\n" + tokens) })
{
var candidate = Create(true);
Step(candidate, diagnostic.Name + ".Platform", platform + diagnostic.Script);
Step(candidate, diagnostic.Name + ".RealLoader", loader);
Step(candidate, diagnostic.Name + ".OfficialCssPluginDisabledForDiagnosis", "require.config({'vs/css':{disabled:true}});");
if (Step(candidate, diagnostic.Name + ".RealEditorBundle", main, true))
{
Step(candidate, diagnostic.Name + ".RequireRealEditor", "require(['vs/editor/editor.main'],function(){globalThis.__xfeLoaded=true;},function(e){throw e;});__xfeCheckpoint();if(!globalThis.__xfeLoaded)throw new Error('Real editor.main has not completed');");
Step(candidate, diagnostic.Name + ".CreateRealEditor", "globalThis.__xfeEditor=monaco.editor.create(document.getElementById('container'),{value:'const answer = 42;',language:'javascript',automaticLayout:false});", true);
}
}
var resultPath = Path.Combine(run, "Result.json");
var result = new {
Kind = "RealMonacoJintCompatibilityProbe", MonacoVersion = "0.52.2", JintVersion = "4.11.0",
ProductionBrowserModified = false, ProbeOnly = true, NativeGuestTested = false, HostBrowserUsed = false,
FakeMonacoObjects = false, ExpandedBudgetIsProductionSupport = false,
LoaderSha256 = Convert.ToHexStringLower(SHA256.HashData(File.ReadAllBytes(loaderPath))),
EditorBundleSha256 = Convert.ToHexStringLower(SHA256.HashData(File.ReadAllBytes(mainPath))),
Baseline = Directory.GetFiles(Path.Combine(root, "build/BrowserProbe/InitialBaseline"), "*.cs")
.Select(p => new { Name = Path.GetFileName(p), Sha256 = Convert.ToHexStringLower(SHA256.HashData(File.ReadAllBytes(p))) }).ToArray(),
Stages = stages
};
File.WriteAllText(resultPath, JsonSerializer.Serialize(result, new JsonSerializerOptions { WriteIndented = true }));
Console.WriteLine(resultPath);