@tracecode/harness 0.6.6 → 0.7.0-beta8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +48 -0
- package/README.md +134 -15
- package/THIRD_PARTY_NOTICES.md +170 -0
- package/dist/browser.cjs +2361 -1033
- package/dist/browser.cjs.map +1 -1
- package/dist/browser.d.cts +33 -3
- package/dist/browser.d.ts +33 -3
- package/dist/browser.js +2357 -1033
- package/dist/browser.js.map +1 -1
- package/dist/cli.cjs +160 -23
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +161 -24
- package/dist/cli.js.map +1 -1
- package/dist/core.cjs +748 -867
- package/dist/core.cjs.map +1 -1
- package/dist/core.d.cts +21 -85
- package/dist/core.d.ts +21 -85
- package/dist/core.js +734 -855
- package/dist/core.js.map +1 -1
- package/dist/cpp-worker-client-Bn7kC0_L.d.ts +84 -0
- package/dist/cpp-worker-client-BzdJLuZa.d.cts +84 -0
- package/dist/cpp.cjs +1063 -0
- package/dist/cpp.cjs.map +1 -0
- package/dist/cpp.d.cts +7 -0
- package/dist/cpp.d.ts +7 -0
- package/dist/cpp.js +1035 -0
- package/dist/cpp.js.map +1 -0
- package/dist/csharp-worker-client-DMHIa2YG.d.cts +69 -0
- package/dist/csharp-worker-client-JwqS6LiX.d.ts +69 -0
- package/dist/csharp.cjs +1012 -0
- package/dist/csharp.cjs.map +1 -0
- package/dist/csharp.d.cts +7 -0
- package/dist/csharp.d.ts +7 -0
- package/dist/csharp.js +984 -0
- package/dist/csharp.js.map +1 -0
- package/dist/index.cjs +3142 -1160
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +13 -5
- package/dist/index.d.ts +13 -5
- package/dist/index.js +3117 -1148
- package/dist/index.js.map +1 -1
- package/dist/internal/browser.cjs +1639 -30
- package/dist/internal/browser.cjs.map +1 -1
- package/dist/internal/browser.d.cts +6 -199
- package/dist/internal/browser.d.ts +6 -199
- package/dist/internal/browser.js +1636 -30
- package/dist/internal/browser.js.map +1 -1
- package/dist/java-worker-client-BOwKW-11.d.cts +72 -0
- package/dist/java-worker-client-C97DDnCp.d.ts +72 -0
- package/dist/java.cjs +1225 -0
- package/dist/java.cjs.map +1 -0
- package/dist/java.d.cts +7 -0
- package/dist/java.d.ts +7 -0
- package/dist/java.js +1197 -0
- package/dist/java.js.map +1 -0
- package/dist/javascript-worker-client-CYBGEEvc.d.cts +51 -0
- package/dist/javascript-worker-client-DIX1Mp21.d.ts +51 -0
- package/dist/javascript.cjs +1063 -19
- package/dist/javascript.cjs.map +1 -1
- package/dist/javascript.d.cts +7 -4
- package/dist/javascript.d.ts +7 -4
- package/dist/javascript.js +1061 -19
- package/dist/javascript.js.map +1 -1
- package/dist/pyodide-worker-client-C-2rfHj9.d.ts +111 -0
- package/dist/pyodide-worker-client-Cn0a8Uv3.d.cts +111 -0
- package/dist/python.cjs +1282 -74
- package/dist/python.cjs.map +1 -1
- package/dist/python.d.cts +20 -14
- package/dist/python.d.ts +20 -14
- package/dist/python.js +1279 -74
- package/dist/python.js.map +1 -1
- package/dist/runtime-language-info-BFUSti3-.d.ts +43 -0
- package/dist/runtime-language-info-Bxza1cI2.d.cts +43 -0
- package/dist/runtime-types-2qM0MukN.d.cts +244 -0
- package/dist/runtime-types-2qM0MukN.d.ts +244 -0
- package/package.json +73 -8
- package/workers/cpp/cpp-compiler-frame.html +82 -0
- package/workers/cpp/cpp-compiler-worker.js +131 -0
- package/workers/cpp/cpp-worker.js +5790 -0
- package/workers/cpp/tracecode_runtime.hpp +6169 -0
- package/workers/csharp/csharp-worker.js +301 -0
- package/workers/java/.build/classes/harness/browser/JavaRewriteLibrary.class +0 -0
- package/workers/java/java-source-augmentations.js +907 -0
- package/workers/java/java-worker.js +2161 -177
- package/workers/java/src/harness/browser/JavaRewriteLibrary.java +1659 -32
- package/workers/java/src/javafx/util/Pair.java +42 -0
- package/workers/java/src/tracecode/browser/BrowserCompileAndTraceLibrary.java +714 -0
- package/workers/java/src/tracecode/browser/BrowserCompileAndTraceMain.java +76 -0
- package/workers/java/src/tracecode/browser/RuntimeProbeMain.java +14 -0
- package/workers/java/src/tracecode/user/TraceHooks.java +1414 -0
- package/workers/javascript/javascript-libraries-entry.js +71 -0
- package/workers/javascript/javascript-worker.js +2055 -424
- package/workers/python/generated-python-harness-snippets.js +4 -4
- package/workers/python/pyodide-worker.js +222 -61
- package/workers/python/runtime-core.js +1387 -301
- package/workers/vendor/csharp/.stamp +0 -0
- package/workers/vendor/csharp/TraceCode.CSharpHost.runtimeconfig.json +32 -0
- package/workers/vendor/csharp/_framework/Microsoft.CSharp.wasm +0 -0
- package/workers/vendor/csharp/_framework/Microsoft.CodeAnalysis.CSharp.wasm +0 -0
- package/workers/vendor/csharp/_framework/Microsoft.CodeAnalysis.wasm +0 -0
- package/workers/vendor/csharp/_framework/Microsoft.VisualBasic.Core.wasm +0 -0
- package/workers/vendor/csharp/_framework/Microsoft.VisualBasic.wasm +0 -0
- package/workers/vendor/csharp/_framework/Microsoft.Win32.Primitives.wasm +0 -0
- package/workers/vendor/csharp/_framework/Microsoft.Win32.Registry.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.AppContext.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Buffers.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Collections.Concurrent.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Collections.Immutable.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Collections.NonGeneric.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Collections.Specialized.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Collections.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.ComponentModel.Annotations.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.ComponentModel.DataAnnotations.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.ComponentModel.EventBasedAsync.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.ComponentModel.Primitives.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.ComponentModel.TypeConverter.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.ComponentModel.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Configuration.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Console.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Core.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Data.Common.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Data.DataSetExtensions.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Data.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Diagnostics.Contracts.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Diagnostics.Debug.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Diagnostics.DiagnosticSource.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Diagnostics.FileVersionInfo.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Diagnostics.Process.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Diagnostics.StackTrace.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Diagnostics.TextWriterTraceListener.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Diagnostics.Tools.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Diagnostics.TraceSource.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Diagnostics.Tracing.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Drawing.Primitives.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Drawing.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Dynamic.Runtime.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Formats.Asn1.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Formats.Tar.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Globalization.Calendars.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Globalization.Extensions.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Globalization.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.IO.Compression.Brotli.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.IO.Compression.FileSystem.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.IO.Compression.ZipFile.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.IO.Compression.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.IO.FileSystem.AccessControl.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.IO.FileSystem.DriveInfo.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.IO.FileSystem.Primitives.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.IO.FileSystem.Watcher.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.IO.FileSystem.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.IO.IsolatedStorage.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.IO.MemoryMappedFiles.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.IO.Pipelines.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.IO.Pipes.AccessControl.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.IO.Pipes.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.IO.UnmanagedMemoryStream.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.IO.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Linq.AsyncEnumerable.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Linq.Expressions.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Linq.Parallel.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Linq.Queryable.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Linq.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Memory.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Net.Http.Json.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Net.Http.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Net.HttpListener.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Net.Mail.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Net.NameResolution.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Net.NetworkInformation.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Net.Ping.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Net.Primitives.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Net.Quic.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Net.Requests.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Net.Security.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Net.ServerSentEvents.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Net.ServicePoint.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Net.Sockets.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Net.WebClient.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Net.WebHeaderCollection.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Net.WebProxy.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Net.WebSockets.Client.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Net.WebSockets.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Net.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Numerics.Vectors.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Numerics.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.ObjectModel.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Private.CoreLib.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Private.DataContractSerialization.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Private.Uri.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Private.Xml.Linq.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Private.Xml.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Reflection.DispatchProxy.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Reflection.Emit.ILGeneration.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Reflection.Emit.Lightweight.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Reflection.Emit.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Reflection.Extensions.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Reflection.Metadata.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Reflection.Primitives.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Reflection.TypeExtensions.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Reflection.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Resources.Reader.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Resources.ResourceManager.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Resources.Writer.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Runtime.CompilerServices.Unsafe.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Runtime.CompilerServices.VisualC.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Runtime.Extensions.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Runtime.Handles.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Runtime.InteropServices.JavaScript.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Runtime.InteropServices.RuntimeInformation.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Runtime.InteropServices.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Runtime.Intrinsics.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Runtime.Loader.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Runtime.Numerics.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Runtime.Serialization.Formatters.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Runtime.Serialization.Json.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Runtime.Serialization.Primitives.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Runtime.Serialization.Xml.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Runtime.Serialization.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Runtime.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Security.AccessControl.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Security.Claims.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Security.Cryptography.Algorithms.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Security.Cryptography.Cng.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Security.Cryptography.Csp.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Security.Cryptography.Encoding.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Security.Cryptography.OpenSsl.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Security.Cryptography.Primitives.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Security.Cryptography.X509Certificates.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Security.Cryptography.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Security.Principal.Windows.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Security.Principal.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Security.SecureString.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Security.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.ServiceModel.Web.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.ServiceProcess.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Text.Encoding.CodePages.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Text.Encoding.Extensions.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Text.Encoding.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Text.Encodings.Web.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Text.Json.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Text.RegularExpressions.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Threading.AccessControl.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Threading.Channels.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Threading.Overlapped.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Threading.Tasks.Dataflow.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Threading.Tasks.Extensions.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Threading.Tasks.Parallel.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Threading.Tasks.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Threading.Thread.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Threading.ThreadPool.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Threading.Timer.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Threading.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Transactions.Local.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Transactions.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.ValueTuple.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Web.HttpUtility.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Web.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Windows.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Xml.Linq.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Xml.ReaderWriter.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Xml.Serialization.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Xml.XDocument.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Xml.XPath.XDocument.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Xml.XPath.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Xml.XmlDocument.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Xml.XmlSerializer.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.Xml.wasm +0 -0
- package/workers/vendor/csharp/_framework/System.wasm +0 -0
- package/workers/vendor/csharp/_framework/TraceCode.CSharpHost.wasm +0 -0
- package/workers/vendor/csharp/_framework/WindowsBase.wasm +0 -0
- package/workers/vendor/csharp/_framework/cs/Microsoft.CodeAnalysis.CSharp.resources.wasm +0 -0
- package/workers/vendor/csharp/_framework/cs/Microsoft.CodeAnalysis.resources.wasm +0 -0
- package/workers/vendor/csharp/_framework/de/Microsoft.CodeAnalysis.CSharp.resources.wasm +0 -0
- package/workers/vendor/csharp/_framework/de/Microsoft.CodeAnalysis.resources.wasm +0 -0
- package/workers/vendor/csharp/_framework/dotnet.boot.js +1958 -0
- package/workers/vendor/csharp/_framework/dotnet.js +4 -0
- package/workers/vendor/csharp/_framework/dotnet.js.map +1 -0
- package/workers/vendor/csharp/_framework/dotnet.native.js +6687 -0
- package/workers/vendor/csharp/_framework/dotnet.native.wasm +0 -0
- package/workers/vendor/csharp/_framework/dotnet.runtime.js +4 -0
- package/workers/vendor/csharp/_framework/dotnet.runtime.js.map +1 -0
- package/workers/vendor/csharp/_framework/es/Microsoft.CodeAnalysis.CSharp.resources.wasm +0 -0
- package/workers/vendor/csharp/_framework/es/Microsoft.CodeAnalysis.resources.wasm +0 -0
- package/workers/vendor/csharp/_framework/fr/Microsoft.CodeAnalysis.CSharp.resources.wasm +0 -0
- package/workers/vendor/csharp/_framework/fr/Microsoft.CodeAnalysis.resources.wasm +0 -0
- package/workers/vendor/csharp/_framework/it/Microsoft.CodeAnalysis.CSharp.resources.wasm +0 -0
- package/workers/vendor/csharp/_framework/it/Microsoft.CodeAnalysis.resources.wasm +0 -0
- package/workers/vendor/csharp/_framework/ja/Microsoft.CodeAnalysis.CSharp.resources.wasm +0 -0
- package/workers/vendor/csharp/_framework/ja/Microsoft.CodeAnalysis.resources.wasm +0 -0
- package/workers/vendor/csharp/_framework/ko/Microsoft.CodeAnalysis.CSharp.resources.wasm +0 -0
- package/workers/vendor/csharp/_framework/ko/Microsoft.CodeAnalysis.resources.wasm +0 -0
- package/workers/vendor/csharp/_framework/mscorlib.wasm +0 -0
- package/workers/vendor/csharp/_framework/netstandard.wasm +0 -0
- package/workers/vendor/csharp/_framework/pl/Microsoft.CodeAnalysis.CSharp.resources.wasm +0 -0
- package/workers/vendor/csharp/_framework/pl/Microsoft.CodeAnalysis.resources.wasm +0 -0
- package/workers/vendor/csharp/_framework/pt-BR/Microsoft.CodeAnalysis.CSharp.resources.wasm +0 -0
- package/workers/vendor/csharp/_framework/pt-BR/Microsoft.CodeAnalysis.resources.wasm +0 -0
- package/workers/vendor/csharp/_framework/ru/Microsoft.CodeAnalysis.CSharp.resources.wasm +0 -0
- package/workers/vendor/csharp/_framework/ru/Microsoft.CodeAnalysis.resources.wasm +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/0_Microsoft.CodeAnalysis.CSharp.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/100_System.Reflection.Emit.ILGeneration.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/101_System.Reflection.Emit.Lightweight.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/102_System.Reflection.Extensions.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/103_System.Reflection.Metadata.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/104_System.Reflection.Primitives.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/105_System.Reflection.TypeExtensions.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/106_System.Resources.Reader.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/107_System.Resources.ResourceManager.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/108_System.Resources.Writer.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/109_System.Runtime.CompilerServices.Unsafe.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/10_System.Buffers.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/110_System.Runtime.CompilerServices.VisualC.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/111_System.Runtime.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/112_System.Runtime.Extensions.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/113_System.Runtime.Handles.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/114_System.Runtime.InteropServices.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/115_System.Runtime.InteropServices.JavaScript.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/116_System.Runtime.InteropServices.RuntimeInformation.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/117_System.Runtime.Intrinsics.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/118_System.Runtime.Loader.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/119_System.Runtime.Numerics.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/11_System.Collections.Concurrent.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/120_System.Runtime.Serialization.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/121_System.Runtime.Serialization.Formatters.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/122_System.Runtime.Serialization.Json.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/123_System.Runtime.Serialization.Primitives.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/124_System.Runtime.Serialization.Xml.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/125_System.Security.AccessControl.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/126_System.Security.Claims.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/127_System.Security.Cryptography.Algorithms.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/128_System.Security.Cryptography.Cng.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/129_System.Security.Cryptography.Csp.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/12_System.Collections.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/130_System.Security.Cryptography.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/131_System.Security.Cryptography.Encoding.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/132_System.Security.Cryptography.OpenSsl.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/133_System.Security.Cryptography.Primitives.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/134_System.Security.Cryptography.X509Certificates.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/135_System.Security.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/136_System.Security.Principal.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/137_System.Security.Principal.Windows.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/138_System.Security.SecureString.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/139_System.ServiceModel.Web.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/13_System.Collections.Immutable.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/140_System.ServiceProcess.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/141_System.Text.Encoding.CodePages.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/142_System.Text.Encoding.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/143_System.Text.Encoding.Extensions.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/144_System.Text.Encodings.Web.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/145_System.Text.Json.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/146_System.Text.RegularExpressions.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/147_System.Threading.AccessControl.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/148_System.Threading.Channels.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/149_System.Threading.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/14_System.Collections.NonGeneric.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/150_System.Threading.Overlapped.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/151_System.Threading.Tasks.Dataflow.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/152_System.Threading.Tasks.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/153_System.Threading.Tasks.Extensions.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/154_System.Threading.Tasks.Parallel.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/155_System.Threading.Thread.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/156_System.Threading.ThreadPool.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/157_System.Threading.Timer.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/158_System.Transactions.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/159_System.Transactions.Local.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/15_System.Collections.Specialized.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/160_System.ValueTuple.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/161_System.Web.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/162_System.Web.HttpUtility.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/163_System.Windows.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/164_System.Xml.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/165_System.Xml.Linq.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/166_System.Xml.ReaderWriter.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/167_System.Xml.Serialization.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/168_System.Xml.XDocument.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/169_System.Xml.XmlDocument.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/16_System.ComponentModel.Annotations.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/170_System.Xml.XmlSerializer.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/171_System.Xml.XPath.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/172_System.Xml.XPath.XDocument.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/173_TraceCode.CSharpHost.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/174_WindowsBase.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/17_System.ComponentModel.DataAnnotations.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/18_System.ComponentModel.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/19_System.ComponentModel.EventBasedAsync.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/1_Microsoft.CodeAnalysis.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/20_System.ComponentModel.Primitives.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/21_System.ComponentModel.TypeConverter.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/22_System.Configuration.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/23_System.Console.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/24_System.Core.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/25_System.Data.Common.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/26_System.Data.DataSetExtensions.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/27_System.Data.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/28_System.Diagnostics.Contracts.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/29_System.Diagnostics.Debug.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/2_Microsoft.CSharp.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/30_System.Diagnostics.DiagnosticSource.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/31_System.Diagnostics.FileVersionInfo.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/32_System.Diagnostics.Process.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/33_System.Diagnostics.StackTrace.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/34_System.Diagnostics.TextWriterTraceListener.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/35_System.Diagnostics.Tools.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/36_System.Diagnostics.TraceSource.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/37_System.Diagnostics.Tracing.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/38_System.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/39_System.Drawing.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/3_Microsoft.VisualBasic.Core.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/40_System.Drawing.Primitives.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/41_System.Dynamic.Runtime.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/42_System.Formats.Asn1.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/43_System.Formats.Tar.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/44_System.Globalization.Calendars.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/45_System.Globalization.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/46_System.Globalization.Extensions.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/47_System.IO.Compression.Brotli.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/48_System.IO.Compression.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/49_System.IO.Compression.FileSystem.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/4_Microsoft.VisualBasic.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/50_System.IO.Compression.ZipFile.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/51_System.IO.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/52_System.IO.FileSystem.AccessControl.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/53_System.IO.FileSystem.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/54_System.IO.FileSystem.DriveInfo.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/55_System.IO.FileSystem.Primitives.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/56_System.IO.FileSystem.Watcher.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/57_System.IO.IsolatedStorage.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/58_System.IO.MemoryMappedFiles.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/59_System.IO.Pipelines.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/5_Microsoft.Win32.Primitives.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/60_System.IO.Pipes.AccessControl.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/61_System.IO.Pipes.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/62_System.IO.UnmanagedMemoryStream.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/63_System.Linq.AsyncEnumerable.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/64_System.Linq.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/65_System.Linq.Expressions.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/66_System.Linq.Parallel.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/67_System.Linq.Queryable.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/68_System.Memory.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/69_System.Net.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/6_Microsoft.Win32.Registry.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/70_System.Net.Http.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/71_System.Net.Http.Json.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/72_System.Net.HttpListener.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/73_System.Net.Mail.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/74_System.Net.NameResolution.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/75_System.Net.NetworkInformation.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/76_System.Net.Ping.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/77_System.Net.Primitives.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/78_System.Net.Quic.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/79_System.Net.Requests.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/7_mscorlib.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/80_System.Net.Security.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/81_System.Net.ServerSentEvents.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/82_System.Net.ServicePoint.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/83_System.Net.Sockets.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/84_System.Net.WebClient.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/85_System.Net.WebHeaderCollection.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/86_System.Net.WebProxy.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/87_System.Net.WebSockets.Client.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/88_System.Net.WebSockets.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/89_System.Numerics.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/8_netstandard.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/90_System.Numerics.Vectors.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/91_System.ObjectModel.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/92_System.Private.CoreLib.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/93_System.Private.DataContractSerialization.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/94_System.Private.Uri.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/95_System.Private.Xml.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/96_System.Private.Xml.Linq.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/97_System.Reflection.DispatchProxy.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/98_System.Reflection.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/99_System.Reflection.Emit.dll +0 -0
- package/workers/vendor/csharp/_framework/supportFiles/9_System.AppContext.dll +0 -0
- package/workers/vendor/csharp/_framework/tr/Microsoft.CodeAnalysis.CSharp.resources.wasm +0 -0
- package/workers/vendor/csharp/_framework/tr/Microsoft.CodeAnalysis.resources.wasm +0 -0
- package/workers/vendor/csharp/_framework/zh-Hans/Microsoft.CodeAnalysis.CSharp.resources.wasm +0 -0
- package/workers/vendor/csharp/_framework/zh-Hans/Microsoft.CodeAnalysis.resources.wasm +0 -0
- package/workers/vendor/csharp/_framework/zh-Hant/Microsoft.CodeAnalysis.CSharp.resources.wasm +0 -0
- package/workers/vendor/csharp/_framework/zh-Hant/Microsoft.CodeAnalysis.resources.wasm +0 -0
- package/workers/vendor/csharp/main.mjs +5 -0
- package/workers/vendor/csharp/package.json +1 -0
- package/workers/vendor/java-browser-helper.jar +0 -0
- package/workers/vendor/java-rewriter.jar +0 -0
- package/workers/vendor/javascript-libraries.js +10106 -0
- package/dist/runtime-types-89nchXlY.d.cts +0 -89
- package/dist/runtime-types-CCQ-ZLc9.d.ts +0 -89
- package/dist/types-zyvpJKCi.d.cts +0 -100
- package/dist/types-zyvpJKCi.d.ts +0 -100
- package/workers/java/java-source-augmentations.cjs +0 -242
- package/workers/java/src/spike/user/TraceHooks.java +0 -619
- package/workers/vendor/java-browser-spike-helper.jar +0 -0
- package/workers/vendor/java-practice-rewriter.jar +0 -0
- package/workers/vendor/java-rewrite-bridge.jar +0 -0
|
@@ -1,23 +1,51 @@
|
|
|
1
1
|
const CHEERPJ_LOADER_URL = 'https://cjrtnc.leaningtech.com/4.2/loader.js';
|
|
2
|
-
const HELPER_JAR_PATH = '/app/workers/vendor/java-browser-
|
|
2
|
+
const HELPER_JAR_PATH = '/app/workers/vendor/java-browser-helper.jar';
|
|
3
3
|
const JDK17_COMPILER_JAR_PATH = '/app/workers/vendor/jdk.compiler-17.jar';
|
|
4
|
-
const REWRITER_JAR_PATH = '/app/workers/vendor/java-
|
|
5
|
-
const REWRITER_BRIDGE_JAR_PATH = '/app/workers/vendor/java-rewrite-bridge.jar';
|
|
4
|
+
const REWRITER_JAR_PATH = '/app/workers/vendor/java-rewriter.jar';
|
|
6
5
|
const JAVAPARSER_JAR_PATH = '/app/workers/vendor/javaparser-core-3.25.10.jar';
|
|
7
6
|
const FULL_CLASSPATH = [
|
|
8
7
|
HELPER_JAR_PATH,
|
|
9
8
|
JDK17_COMPILER_JAR_PATH,
|
|
10
9
|
REWRITER_JAR_PATH,
|
|
11
|
-
REWRITER_BRIDGE_JAR_PATH,
|
|
12
10
|
JAVAPARSER_JAR_PATH,
|
|
13
11
|
].join(':');
|
|
14
12
|
const DEFAULT_COMPILER_DEBUG_PROFILE = 'full';
|
|
13
|
+
const DEFAULT_EXECUTE_COMPILER_DEBUG_PROFILE = 'none';
|
|
15
14
|
const DEFAULT_MAX_STORED_EVENTS = 50_000;
|
|
16
|
-
const
|
|
15
|
+
const DEFAULT_IDLE_TIMEOUT_MS = 300_000;
|
|
17
16
|
const SCRIPT_METHOD_NAME = '__tracecodeScript';
|
|
17
|
+
const DYNAMIC_INPUT_PREFIX = '/str/tracecode-java-input';
|
|
18
|
+
const JAVA_DEFAULT_IMPORTS = [
|
|
19
|
+
'import java.util.*;',
|
|
20
|
+
'import java.io.*;',
|
|
21
|
+
'import java.math.*;',
|
|
22
|
+
'import java.util.stream.*;',
|
|
23
|
+
'import javafx.util.Pair;',
|
|
24
|
+
];
|
|
25
|
+
const WORKER_DEBUG = (() => {
|
|
26
|
+
try {
|
|
27
|
+
return typeof self !== 'undefined' && typeof self.location?.search === 'string' && self.location.search.includes('dev=');
|
|
28
|
+
} catch {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
})();
|
|
32
|
+
|
|
33
|
+
function emitRuntimeDiagnostic(level, phase, message, detail) {
|
|
34
|
+
if (!WORKER_DEBUG && level !== 'error') return;
|
|
35
|
+
const method = level === 'error' ? 'error' : level === 'warn' ? 'warn' : level === 'debug' ? 'debug' : 'info';
|
|
36
|
+
console[method]('[TraceRuntime]', {
|
|
37
|
+
schema: 'tracecode.runtime-diagnostic.v1',
|
|
38
|
+
source: 'harness',
|
|
39
|
+
component: 'JavaWorker',
|
|
40
|
+
runtime: 'java',
|
|
41
|
+
phase,
|
|
42
|
+
message,
|
|
43
|
+
...(detail === undefined ? {} : { detail }),
|
|
44
|
+
});
|
|
45
|
+
}
|
|
18
46
|
|
|
19
47
|
if (typeof self.importScripts === 'function') {
|
|
20
|
-
self.importScripts('java-source-augmentations.
|
|
48
|
+
self.importScripts('java-source-augmentations.js');
|
|
21
49
|
}
|
|
22
50
|
|
|
23
51
|
let workerReadyPromise = null;
|
|
@@ -27,13 +55,26 @@ let helperLibraryPromise = null;
|
|
|
27
55
|
let compileLibraryClassPromise = null;
|
|
28
56
|
let rewriteLibraryClassPromise = null;
|
|
29
57
|
let idleGeneration = 0;
|
|
30
|
-
let hostWarmupPromise = null;
|
|
31
58
|
let initLoadTimeMs = null;
|
|
59
|
+
let idleTimeoutMs = DEFAULT_IDLE_TIMEOUT_MS;
|
|
60
|
+
let runWarmupPromise = null;
|
|
32
61
|
|
|
33
62
|
function postMessageResponse(message) {
|
|
34
63
|
self.postMessage(message);
|
|
35
64
|
}
|
|
36
65
|
|
|
66
|
+
function javaDefaultImportsBlock() {
|
|
67
|
+
return JAVA_DEFAULT_IMPORTS.join('\n');
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function addJavaDefaultImportsToPackagedSource(source) {
|
|
71
|
+
const importBlock = javaDefaultImportsBlock();
|
|
72
|
+
return String(source).replace(
|
|
73
|
+
/^(package\s+[A-Za-z_][A-Za-z0-9_.]*\s*;\s*\n+)/,
|
|
74
|
+
`$1${importBlock}\n`
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
|
|
37
78
|
function formatWorkerErrorMessage(error) {
|
|
38
79
|
if (error instanceof Error && typeof error.message === 'string' && error.message.length > 0) {
|
|
39
80
|
return error.message;
|
|
@@ -119,7 +160,14 @@ function resetIdleTimer() {
|
|
|
119
160
|
if (generation !== idleGeneration) return;
|
|
120
161
|
postMessageResponse({ type: 'idle-timeout' });
|
|
121
162
|
self.close();
|
|
122
|
-
},
|
|
163
|
+
}, idleTimeoutMs);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
function applyWorkerOptions(payload) {
|
|
167
|
+
const nextIdleTimeoutMs = Number(payload?.idleTimeoutMs);
|
|
168
|
+
if (Number.isFinite(nextIdleTimeoutMs) && nextIdleTimeoutMs > 0) {
|
|
169
|
+
idleTimeoutMs = Math.max(1_000, Math.floor(nextIdleTimeoutMs));
|
|
170
|
+
}
|
|
123
171
|
}
|
|
124
172
|
|
|
125
173
|
function assertSupportedExecutionStyle(executionStyle) {
|
|
@@ -150,6 +198,8 @@ function isRecord(value) {
|
|
|
150
198
|
|
|
151
199
|
function isListNodeShape(value) {
|
|
152
200
|
if (!isRecord(value)) return false;
|
|
201
|
+
const typeName = typeof value.__type__ === 'string' ? value.__type__ : typeof value.__class__ === 'string' ? value.__class__ : null;
|
|
202
|
+
if (typeName && typeName !== 'ListNode' && typeName !== 'object') return false;
|
|
153
203
|
if (!('val' in value || 'value' in value)) return false;
|
|
154
204
|
if ('next' in value) return true;
|
|
155
205
|
return typeof value.__id__ === 'string' && value.__id__.startsWith('list-');
|
|
@@ -157,19 +207,43 @@ function isListNodeShape(value) {
|
|
|
157
207
|
|
|
158
208
|
function isTreeNodeShape(value) {
|
|
159
209
|
if (!isRecord(value)) return false;
|
|
210
|
+
const typeName = typeof value.__type__ === 'string' ? value.__type__ : typeof value.__class__ === 'string' ? value.__class__ : null;
|
|
211
|
+
if (typeName && typeName !== 'TreeNode' && typeName !== 'object') return false;
|
|
160
212
|
if (!('val' in value || 'value' in value)) return false;
|
|
161
213
|
if ('left' in value || 'right' in value) return true;
|
|
162
214
|
return typeof value.__id__ === 'string' && value.__id__.startsWith('tree-');
|
|
163
215
|
}
|
|
164
216
|
|
|
165
|
-
function detectFeatures(source, input) {
|
|
217
|
+
function detectFeatures(source, input, options = {}) {
|
|
166
218
|
const values = Object.values(input ?? {});
|
|
167
219
|
return {
|
|
168
220
|
hasList: /\bListNode\b/.test(source) || values.some((value) => isListNodeShape(value)),
|
|
169
221
|
hasTree: /\bTreeNode\b/.test(source) || values.some((value) => isTreeNodeShape(value)),
|
|
222
|
+
hasCustomObject: values.some((value) => containsCustomObjectLiteral(value)),
|
|
223
|
+
hasMap: values.some((value) => containsPlainObjectLiteral(value)),
|
|
224
|
+
hasDynamicInputs: options.hasDynamicInputs === true,
|
|
170
225
|
};
|
|
171
226
|
}
|
|
172
227
|
|
|
228
|
+
function containsCustomObjectLiteral(value) {
|
|
229
|
+
if (Array.isArray(value)) return value.some((entry) => containsCustomObjectLiteral(entry));
|
|
230
|
+
if (!isRecord(value)) return false;
|
|
231
|
+
const typeName = typeof value.__type__ === 'string' ? value.__type__ : typeof value.__class__ === 'string' ? value.__class__ : null;
|
|
232
|
+
if (typeName && typeName !== 'TreeNode' && typeName !== 'ListNode' && typeName !== 'object') return true;
|
|
233
|
+
return Object.values(value).some((entry) => containsCustomObjectLiteral(entry));
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
function containsPlainObjectLiteral(value) {
|
|
237
|
+
if (Array.isArray(value)) return value.some((entry) => containsPlainObjectLiteral(entry));
|
|
238
|
+
if (!isRecord(value)) return false;
|
|
239
|
+
const typeName = typeof value.__type__ === 'string' ? value.__type__ : typeof value.__class__ === 'string' ? value.__class__ : null;
|
|
240
|
+
if (!typeName) return true;
|
|
241
|
+
if (typeName !== 'TreeNode' && typeName !== 'ListNode' && typeName !== 'object') return false;
|
|
242
|
+
return Object.entries(value)
|
|
243
|
+
.filter(([key]) => key !== '__type__' && key !== '__class__' && key !== '__id__')
|
|
244
|
+
.some(([, entry]) => containsPlainObjectLiteral(entry));
|
|
245
|
+
}
|
|
246
|
+
|
|
173
247
|
function toJavaScalarLiteral(value) {
|
|
174
248
|
if (value === null) return 'null';
|
|
175
249
|
if (typeof value === 'number' || typeof value === 'boolean') return String(value);
|
|
@@ -177,6 +251,23 @@ function toJavaScalarLiteral(value) {
|
|
|
177
251
|
throw new Error(`Unsupported scalar literal: ${JSON.stringify(value)}`);
|
|
178
252
|
}
|
|
179
253
|
|
|
254
|
+
function toJavaScalarLiteralForType(value, expectedType) {
|
|
255
|
+
const normalized = expectedType ? stripGenericType(expectedType) : null;
|
|
256
|
+
if ((normalized === 'long' || normalized === 'Long') && typeof value === 'number' && Number.isInteger(value)) {
|
|
257
|
+
return `${String(value)}L`;
|
|
258
|
+
}
|
|
259
|
+
if ((normalized === 'double' || normalized === 'Double') && typeof value === 'number') {
|
|
260
|
+
return Number.isInteger(value) ? `${String(value)}.0` : String(value);
|
|
261
|
+
}
|
|
262
|
+
if ((normalized === 'float' || normalized === 'Float') && typeof value === 'number') {
|
|
263
|
+
return `${Number.isInteger(value) ? `${String(value)}.0` : String(value)}f`;
|
|
264
|
+
}
|
|
265
|
+
if (normalized === 'char' && typeof value === 'string' && value.length === 1) {
|
|
266
|
+
return `'${value.replace(/\\/g, '\\\\').replace(/'/g, "\\'")}'`;
|
|
267
|
+
}
|
|
268
|
+
return toJavaScalarLiteral(value);
|
|
269
|
+
}
|
|
270
|
+
|
|
180
271
|
function toJavaArrayLiteral(value) {
|
|
181
272
|
if (value.length === 0) return 'new int[] {}';
|
|
182
273
|
if (value.every((entry) => typeof entry === 'number' && Number.isInteger(entry))) {
|
|
@@ -226,6 +317,78 @@ function extractTypeArguments(typeSource) {
|
|
|
226
317
|
return parts.map((part) => part.trim()).filter(Boolean);
|
|
227
318
|
}
|
|
228
319
|
|
|
320
|
+
function splitTopLevelCommaList(source) {
|
|
321
|
+
const parts = [];
|
|
322
|
+
let depth = 0;
|
|
323
|
+
let current = '';
|
|
324
|
+
for (const ch of source) {
|
|
325
|
+
if (ch === '<' || ch === '(' || ch === '[') depth += 1;
|
|
326
|
+
if (ch === '>' || ch === ')' || ch === ']') depth -= 1;
|
|
327
|
+
if (ch === ',' && depth === 0) {
|
|
328
|
+
parts.push(current);
|
|
329
|
+
current = '';
|
|
330
|
+
continue;
|
|
331
|
+
}
|
|
332
|
+
current += ch;
|
|
333
|
+
}
|
|
334
|
+
if (current) parts.push(current);
|
|
335
|
+
return parts.map((part) => part.trim()).filter(Boolean);
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
function normalizedJavaInputType(typeSource) {
|
|
339
|
+
return String(typeSource || 'Object')
|
|
340
|
+
.replace(/\bfinal\b/g, '')
|
|
341
|
+
.replace(/\s+/g, '')
|
|
342
|
+
.replace(/\.\.\.$/, '[]');
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
function isDynamicJavaScalarType(typeSource, value) {
|
|
346
|
+
const normalized = normalizedJavaInputType(typeSource);
|
|
347
|
+
if (
|
|
348
|
+
['byte', 'Byte', 'short', 'Short', 'int', 'Integer', 'long', 'Long', 'float', 'Float', 'double', 'Double'].includes(normalized)
|
|
349
|
+
) {
|
|
350
|
+
return typeof value === 'number';
|
|
351
|
+
}
|
|
352
|
+
if (normalized === 'boolean' || normalized === 'Boolean') {
|
|
353
|
+
return typeof value === 'boolean';
|
|
354
|
+
}
|
|
355
|
+
if (normalized === 'String') {
|
|
356
|
+
return typeof value === 'string';
|
|
357
|
+
}
|
|
358
|
+
if (normalized === 'char' || normalized === 'Character') {
|
|
359
|
+
return typeof value === 'string' && value.length === 1;
|
|
360
|
+
}
|
|
361
|
+
return false;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
function isDynamicJavaInputType(typeSource, value) {
|
|
365
|
+
const normalized = normalizedJavaInputType(typeSource);
|
|
366
|
+
if (normalized.endsWith('[]')) {
|
|
367
|
+
if (!Array.isArray(value)) return false;
|
|
368
|
+
const elementType = normalized.slice(0, -2);
|
|
369
|
+
return value.every((entry) => isDynamicJavaInputType(elementType, entry));
|
|
370
|
+
}
|
|
371
|
+
return isDynamicJavaScalarType(normalized, value);
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
function dynamicJavaInputExpression(typeSource, inputPath) {
|
|
375
|
+
const normalized = normalizedJavaInputType(typeSource);
|
|
376
|
+
const quotedPath = JSON.stringify(inputPath);
|
|
377
|
+
if (normalized.endsWith('[]')) {
|
|
378
|
+
return `((${normalized}) readJsonInput(${quotedPath}, ${normalized}.class))`;
|
|
379
|
+
}
|
|
380
|
+
if (normalized === 'byte' || normalized === 'Byte') return `((Number) readJsonInput(${quotedPath}, Byte.class)).byteValue()`;
|
|
381
|
+
if (normalized === 'short' || normalized === 'Short') return `((Number) readJsonInput(${quotedPath}, Short.class)).shortValue()`;
|
|
382
|
+
if (normalized === 'int' || normalized === 'Integer') return `((Number) readJsonInput(${quotedPath}, Integer.class)).intValue()`;
|
|
383
|
+
if (normalized === 'long' || normalized === 'Long') return `((Number) readJsonInput(${quotedPath}, Long.class)).longValue()`;
|
|
384
|
+
if (normalized === 'float' || normalized === 'Float') return `((Number) readJsonInput(${quotedPath}, Float.class)).floatValue()`;
|
|
385
|
+
if (normalized === 'double' || normalized === 'Double') return `((Number) readJsonInput(${quotedPath}, Double.class)).doubleValue()`;
|
|
386
|
+
if (normalized === 'boolean' || normalized === 'Boolean') return `((Boolean) readJsonInput(${quotedPath}, Boolean.class)).booleanValue()`;
|
|
387
|
+
if (normalized === 'char' || normalized === 'Character') return `((Character) readJsonInput(${quotedPath}, Character.class)).charValue()`;
|
|
388
|
+
if (normalized === 'String') return `((String) readJsonInput(${quotedPath}, String.class))`;
|
|
389
|
+
return null;
|
|
390
|
+
}
|
|
391
|
+
|
|
229
392
|
function toJavaTypedArrayLiteral(value, expectedType) {
|
|
230
393
|
const normalized = stripGenericType(expectedType);
|
|
231
394
|
if (!normalized.endsWith('[]')) {
|
|
@@ -268,7 +431,81 @@ function toJavaTypedArrayLiteral(value, expectedType) {
|
|
|
268
431
|
|
|
269
432
|
function toJavaListLiteral(value, expectedType) {
|
|
270
433
|
const [elementType = 'Object'] = extractTypeArguments(expectedType);
|
|
271
|
-
return `java.util.
|
|
434
|
+
return `new java.util.ArrayList<${elementType}>(java.util.Arrays.asList(${value.map((entry) => buildJavaExpression(entry, elementType)).join(', ')}))`;
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
function toJavaMapLiteral(value, expectedType) {
|
|
438
|
+
const [keyType = 'String', valueType = 'Object'] = extractTypeArguments(expectedType);
|
|
439
|
+
const entries = Object.entries(value)
|
|
440
|
+
.map(([key, child]) => `new Object[] { ${buildJavaExpression(key, keyType)}, ${buildJavaExpression(child, valueType)} }`);
|
|
441
|
+
return `typedMap(new Object[][] { ${entries.join(', ')} })`;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
function toJavaObjectExpression(value) {
|
|
445
|
+
if (Array.isArray(value)) {
|
|
446
|
+
return `new java.util.ArrayList<Object>(java.util.Arrays.asList(${value.map((entry) => toJavaObjectExpression(entry)).join(', ')}))`;
|
|
447
|
+
}
|
|
448
|
+
if (isRecord(value)) {
|
|
449
|
+
return toJavaDynamicObjectExpression(value);
|
|
450
|
+
}
|
|
451
|
+
return toJavaScalarLiteral(value);
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
function customObjectTypeName(value) {
|
|
455
|
+
if (!isRecord(value)) return null;
|
|
456
|
+
const typeName = typeof value.__type__ === 'string' ? value.__type__ : typeof value.__class__ === 'string' ? value.__class__ : null;
|
|
457
|
+
if (!typeName || typeName === 'TreeNode' || typeName === 'ListNode' || typeName === 'object') return null;
|
|
458
|
+
return typeName;
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
function toJavaObjectFieldsExpression(value) {
|
|
462
|
+
const entries = Object.entries(value)
|
|
463
|
+
.filter(([key]) => key !== '__type__' && key !== '__class__' && key !== '__id__')
|
|
464
|
+
.map(([key, child]) => `new Object[] { ${JSON.stringify(key)}, ${toJavaDynamicObjectExpression(child)} }`);
|
|
465
|
+
return `objectFields(new Object[][] { ${entries.join(', ')} })`;
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
function toJavaDynamicObjectExpression(value) {
|
|
469
|
+
if (value === null) return 'null';
|
|
470
|
+
if (Array.isArray(value)) {
|
|
471
|
+
return `new java.util.ArrayList<Object>(java.util.Arrays.asList(${value.map((entry) => toJavaDynamicObjectExpression(entry)).join(', ')}))`;
|
|
472
|
+
}
|
|
473
|
+
if (isRecord(value)) {
|
|
474
|
+
const typeName = customObjectTypeName(value);
|
|
475
|
+
if (typeName) {
|
|
476
|
+
return `materializeObject(${JSON.stringify(typeName)}, ${toJavaObjectFieldsExpression(value)})`;
|
|
477
|
+
}
|
|
478
|
+
const entries = Object.entries(value)
|
|
479
|
+
.filter(([key]) => key !== '__type__' && key !== '__class__' && key !== '__id__')
|
|
480
|
+
.map(([key, child]) => `new Object[] { ${JSON.stringify(key)}, ${toJavaDynamicObjectExpression(child)} }`);
|
|
481
|
+
return `objectFields(new Object[][] { ${entries.join(', ')} })`;
|
|
482
|
+
}
|
|
483
|
+
return toJavaScalarLiteral(value);
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
function inputValueForParameter(input, key, index) {
|
|
487
|
+
if (Object.prototype.hasOwnProperty.call(input, key)) return input[key];
|
|
488
|
+
return Object.values(input)[index];
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
function inputArgumentsForParameters(rawArgs, parameters) {
|
|
492
|
+
if (parameters.length === 0) return [];
|
|
493
|
+
if (Array.isArray(rawArgs)) return rawArgs;
|
|
494
|
+
if (isRecord(rawArgs) && parameters.length > 0) {
|
|
495
|
+
return parameters.map((parameter, index) => inputValueForParameter(rawArgs, parameter.name, index));
|
|
496
|
+
}
|
|
497
|
+
return [];
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
function uniqueJavaIdentifier(baseName, usedNames) {
|
|
501
|
+
let candidate = baseName;
|
|
502
|
+
let suffix = 0;
|
|
503
|
+
while (usedNames.has(candidate)) {
|
|
504
|
+
suffix += 1;
|
|
505
|
+
candidate = `${baseName}${suffix}`;
|
|
506
|
+
}
|
|
507
|
+
usedNames.add(candidate);
|
|
508
|
+
return candidate;
|
|
272
509
|
}
|
|
273
510
|
|
|
274
511
|
function listLiteral(value) {
|
|
@@ -320,17 +557,18 @@ function listGraphExpression(head) {
|
|
|
320
557
|
|
|
321
558
|
const values = nodes.map((node) => {
|
|
322
559
|
const rawVal = node.val ?? node.value ?? 0;
|
|
323
|
-
if (typeof rawVal !== 'number' || !Number.isInteger(rawVal)) {
|
|
324
|
-
throw new Error(`Unsupported list node value: ${JSON.stringify(rawVal)}`);
|
|
325
|
-
}
|
|
326
560
|
return rawVal;
|
|
327
561
|
});
|
|
328
562
|
|
|
329
|
-
return `buildList(new
|
|
563
|
+
return `buildList(new Object[] { ${values.map((value) => toJavaScalarLiteral(value)).join(', ')} }, new int[] { ${nextIndices.join(', ')} })`;
|
|
330
564
|
}
|
|
331
565
|
|
|
332
566
|
function listExpression(value) {
|
|
333
|
-
return
|
|
567
|
+
return listGraphExpression(value);
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
function listArrayExpression(value) {
|
|
571
|
+
return `buildList(new Object[] { ${value.map((entry) => toJavaScalarLiteral(entry)).join(', ')} }, sequentialNextIndices(${value.length}))`;
|
|
334
572
|
}
|
|
335
573
|
|
|
336
574
|
function treeExpression(value) {
|
|
@@ -340,9 +578,29 @@ function treeExpression(value) {
|
|
|
340
578
|
return `tree(${toJavaScalarLiteral(rawVal)}, ${left}, ${right})`;
|
|
341
579
|
}
|
|
342
580
|
|
|
581
|
+
function treeLevelOrderExpression(value) {
|
|
582
|
+
if (!value.every((entry) => entry === null || (typeof entry === 'number' && Number.isInteger(entry)))) {
|
|
583
|
+
throw new Error(`Unsupported tree node value: ${JSON.stringify(value.find((entry) => entry !== null && (typeof entry !== 'number' || !Number.isInteger(entry))))}`);
|
|
584
|
+
}
|
|
585
|
+
const values = value.map((entry) => (entry === null ? 'null' : String(entry))).join(', ');
|
|
586
|
+
return `buildTree(new Integer[] { ${values} })`;
|
|
587
|
+
}
|
|
588
|
+
|
|
343
589
|
function buildJavaExpression(value, expectedType) {
|
|
344
590
|
const normalizedType = expectedType ? stripGenericType(expectedType) : null;
|
|
591
|
+
if (value === null || typeof value !== 'object') {
|
|
592
|
+
return toJavaScalarLiteralForType(value, normalizedType);
|
|
593
|
+
}
|
|
345
594
|
if (Array.isArray(value)) {
|
|
595
|
+
if (normalizedType === 'Object') {
|
|
596
|
+
return toJavaObjectExpression(value);
|
|
597
|
+
}
|
|
598
|
+
if (normalizedType === 'ListNode') {
|
|
599
|
+
return listArrayExpression(value);
|
|
600
|
+
}
|
|
601
|
+
if (normalizedType === 'TreeNode') {
|
|
602
|
+
return treeLevelOrderExpression(value);
|
|
603
|
+
}
|
|
346
604
|
if (normalizedType?.startsWith('List<')) {
|
|
347
605
|
return toJavaListLiteral(value, normalizedType);
|
|
348
606
|
}
|
|
@@ -353,34 +611,299 @@ function buildJavaExpression(value, expectedType) {
|
|
|
353
611
|
}
|
|
354
612
|
if (isRecord(value) && normalizedType === 'ListNode') return listExpression(value);
|
|
355
613
|
if (isRecord(value) && normalizedType === 'TreeNode') return treeExpression(value);
|
|
614
|
+
if (isRecord(value) && normalizedType?.startsWith('Map<')) return toJavaMapLiteral(value, normalizedType);
|
|
615
|
+
if (isRecord(value) && customObjectTypeName(value)) {
|
|
616
|
+
return `((${normalizedType ?? customObjectTypeName(value)}) ${toJavaDynamicObjectExpression(value)})`;
|
|
617
|
+
}
|
|
356
618
|
if (isListNodeShape(value)) return listExpression(value);
|
|
357
619
|
if (isTreeNodeShape(value)) return treeExpression(value);
|
|
358
620
|
return toJavaScalarLiteral(value);
|
|
359
621
|
}
|
|
360
622
|
|
|
623
|
+
function buildDynamicInputHelperMethods() {
|
|
624
|
+
return `
|
|
625
|
+
private static Object readJsonInput(String path, Class<?> targetType) {
|
|
626
|
+
try {
|
|
627
|
+
String source = java.nio.file.Files.readString(java.nio.file.Paths.get(path), java.nio.charset.StandardCharsets.UTF_8);
|
|
628
|
+
return coerceJsonInput(new __TracecodeJsonParser(source).parse(), targetType);
|
|
629
|
+
} catch (java.io.IOException error) {
|
|
630
|
+
throw new RuntimeException("Unable to read TraceCode input " + path, error);
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
private static Object coerceJsonInput(Object value, Class<?> targetType) {
|
|
635
|
+
if (value == null) return null;
|
|
636
|
+
if (targetType.isArray()) {
|
|
637
|
+
java.util.List<?> list = (java.util.List<?>) value;
|
|
638
|
+
Class<?> componentType = targetType.getComponentType();
|
|
639
|
+
Object array = java.lang.reflect.Array.newInstance(componentType, list.size());
|
|
640
|
+
for (int i = 0; i < list.size(); i++) {
|
|
641
|
+
java.lang.reflect.Array.set(array, i, coerceJsonInput(list.get(i), componentType));
|
|
642
|
+
}
|
|
643
|
+
return array;
|
|
644
|
+
}
|
|
645
|
+
if ((targetType == byte.class || targetType == Byte.class) && value instanceof Number) return ((Number) value).byteValue();
|
|
646
|
+
if ((targetType == short.class || targetType == Short.class) && value instanceof Number) return ((Number) value).shortValue();
|
|
647
|
+
if ((targetType == int.class || targetType == Integer.class) && value instanceof Number) return ((Number) value).intValue();
|
|
648
|
+
if ((targetType == long.class || targetType == Long.class) && value instanceof Number) return ((Number) value).longValue();
|
|
649
|
+
if ((targetType == float.class || targetType == Float.class) && value instanceof Number) return ((Number) value).floatValue();
|
|
650
|
+
if ((targetType == double.class || targetType == Double.class) && value instanceof Number) return ((Number) value).doubleValue();
|
|
651
|
+
if ((targetType == boolean.class || targetType == Boolean.class) && value instanceof Boolean) return value;
|
|
652
|
+
if ((targetType == char.class || targetType == Character.class) && value instanceof String && ((String) value).length() == 1) {
|
|
653
|
+
return ((String) value).charAt(0);
|
|
654
|
+
}
|
|
655
|
+
if (targetType == String.class && value instanceof String) return value;
|
|
656
|
+
return value;
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
private static final class __TracecodeJsonParser {
|
|
660
|
+
private final String source;
|
|
661
|
+
private int index = 0;
|
|
662
|
+
|
|
663
|
+
__TracecodeJsonParser(String source) {
|
|
664
|
+
this.source = source == null || source.isEmpty() ? "null" : source;
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
Object parse() {
|
|
668
|
+
skipWhitespace();
|
|
669
|
+
Object value = parseValue();
|
|
670
|
+
skipWhitespace();
|
|
671
|
+
if (index != source.length()) {
|
|
672
|
+
throw new IllegalArgumentException("Unexpected trailing JSON input");
|
|
673
|
+
}
|
|
674
|
+
return value;
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
private Object parseValue() {
|
|
678
|
+
skipWhitespace();
|
|
679
|
+
char ch = peek();
|
|
680
|
+
if (ch == '"') return parseString();
|
|
681
|
+
if (ch == '[') return parseArray();
|
|
682
|
+
if (ch == '{') return parseObject();
|
|
683
|
+
if (ch == '-' || (ch >= '0' && ch <= '9')) return parseNumber();
|
|
684
|
+
if (consume("true")) return Boolean.TRUE;
|
|
685
|
+
if (consume("false")) return Boolean.FALSE;
|
|
686
|
+
if (consume("null")) return null;
|
|
687
|
+
throw new IllegalArgumentException("Invalid JSON input");
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
private java.util.List<Object> parseArray() {
|
|
691
|
+
expect('[');
|
|
692
|
+
java.util.ArrayList<Object> values = new java.util.ArrayList<>();
|
|
693
|
+
skipWhitespace();
|
|
694
|
+
if (peek() == ']') {
|
|
695
|
+
index++;
|
|
696
|
+
return values;
|
|
697
|
+
}
|
|
698
|
+
while (true) {
|
|
699
|
+
values.add(parseValue());
|
|
700
|
+
skipWhitespace();
|
|
701
|
+
char separator = take();
|
|
702
|
+
if (separator == ']') return values;
|
|
703
|
+
if (separator != ',') throw new IllegalArgumentException("Invalid JSON array");
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
private java.util.LinkedHashMap<String, Object> parseObject() {
|
|
708
|
+
expect('{');
|
|
709
|
+
java.util.LinkedHashMap<String, Object> values = new java.util.LinkedHashMap<>();
|
|
710
|
+
skipWhitespace();
|
|
711
|
+
if (peek() == '}') {
|
|
712
|
+
index++;
|
|
713
|
+
return values;
|
|
714
|
+
}
|
|
715
|
+
while (true) {
|
|
716
|
+
skipWhitespace();
|
|
717
|
+
String key = parseString();
|
|
718
|
+
skipWhitespace();
|
|
719
|
+
expect(':');
|
|
720
|
+
values.put(key, parseValue());
|
|
721
|
+
skipWhitespace();
|
|
722
|
+
char separator = take();
|
|
723
|
+
if (separator == '}') return values;
|
|
724
|
+
if (separator != ',') throw new IllegalArgumentException("Invalid JSON object");
|
|
725
|
+
}
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
private String parseString() {
|
|
729
|
+
expect('"');
|
|
730
|
+
StringBuilder out = new StringBuilder();
|
|
731
|
+
while (true) {
|
|
732
|
+
char ch = take();
|
|
733
|
+
if (ch == '"') return out.toString();
|
|
734
|
+
if (ch != '\\\\') {
|
|
735
|
+
out.append(ch);
|
|
736
|
+
continue;
|
|
737
|
+
}
|
|
738
|
+
char escaped = take();
|
|
739
|
+
switch (escaped) {
|
|
740
|
+
case '"': out.append('"'); break;
|
|
741
|
+
case '\\\\': out.append('\\\\'); break;
|
|
742
|
+
case '/': out.append('/'); break;
|
|
743
|
+
case 'b': out.append('\\b'); break;
|
|
744
|
+
case 'f': out.append('\\f'); break;
|
|
745
|
+
case 'n': out.append('\\n'); break;
|
|
746
|
+
case 'r': out.append('\\r'); break;
|
|
747
|
+
case 't': out.append('\\t'); break;
|
|
748
|
+
case 'u':
|
|
749
|
+
int codePoint = 0;
|
|
750
|
+
for (int i = 0; i < 4; i++) {
|
|
751
|
+
codePoint = (codePoint << 4) + Character.digit(take(), 16);
|
|
752
|
+
}
|
|
753
|
+
out.append((char) codePoint);
|
|
754
|
+
break;
|
|
755
|
+
default:
|
|
756
|
+
throw new IllegalArgumentException("Invalid JSON string escape");
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
private Number parseNumber() {
|
|
762
|
+
int start = index;
|
|
763
|
+
if (peek() == '-') index++;
|
|
764
|
+
while (peek() >= '0' && peek() <= '9') index++;
|
|
765
|
+
boolean floating = false;
|
|
766
|
+
if (peek() == '.') {
|
|
767
|
+
floating = true;
|
|
768
|
+
index++;
|
|
769
|
+
while (peek() >= '0' && peek() <= '9') index++;
|
|
770
|
+
}
|
|
771
|
+
if (peek() == 'e' || peek() == 'E') {
|
|
772
|
+
floating = true;
|
|
773
|
+
index++;
|
|
774
|
+
if (peek() == '+' || peek() == '-') index++;
|
|
775
|
+
while (peek() >= '0' && peek() <= '9') index++;
|
|
776
|
+
}
|
|
777
|
+
String raw = source.substring(start, index);
|
|
778
|
+
return floating ? Double.valueOf(raw) : Long.valueOf(raw);
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
private boolean consume(String literal) {
|
|
782
|
+
if (!source.startsWith(literal, index)) return false;
|
|
783
|
+
index += literal.length();
|
|
784
|
+
return true;
|
|
785
|
+
}
|
|
786
|
+
|
|
787
|
+
private void skipWhitespace() {
|
|
788
|
+
while (index < source.length() && Character.isWhitespace(source.charAt(index))) index++;
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
private char peek() {
|
|
792
|
+
return index < source.length() ? source.charAt(index) : '\\0';
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
private char take() {
|
|
796
|
+
if (index >= source.length()) throw new IllegalArgumentException("Unexpected end of JSON input");
|
|
797
|
+
return source.charAt(index++);
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
private void expect(char expected) {
|
|
801
|
+
char actual = take();
|
|
802
|
+
if (actual != expected) throw new IllegalArgumentException("Unexpected JSON character");
|
|
803
|
+
}
|
|
804
|
+
}`;
|
|
805
|
+
}
|
|
806
|
+
|
|
361
807
|
function buildHelperMethods(features) {
|
|
808
|
+
if (features.skipInputMaterializers) {
|
|
809
|
+
return '';
|
|
810
|
+
}
|
|
362
811
|
const members = [];
|
|
812
|
+
if (features.hasDynamicInputs) {
|
|
813
|
+
members.push(buildDynamicInputHelperMethods());
|
|
814
|
+
}
|
|
815
|
+
if (features.hasList || features.hasCustomObject) {
|
|
816
|
+
members.push(`
|
|
817
|
+
private static Object coerceMaterializedValue(Object value, Class<?> targetType) {
|
|
818
|
+
if (value == null) {
|
|
819
|
+
return null;
|
|
820
|
+
}
|
|
821
|
+
if (targetType.isInstance(value)) {
|
|
822
|
+
return value;
|
|
823
|
+
}
|
|
824
|
+
if (targetType.isArray() && value instanceof java.util.List<?>) {
|
|
825
|
+
java.util.List<?> list = (java.util.List<?>) value;
|
|
826
|
+
Class<?> componentType = targetType.getComponentType();
|
|
827
|
+
Object array = java.lang.reflect.Array.newInstance(componentType, list.size());
|
|
828
|
+
for (int i = 0; i < list.size(); i++) {
|
|
829
|
+
java.lang.reflect.Array.set(array, i, coerceMaterializedValue(list.get(i), componentType));
|
|
830
|
+
}
|
|
831
|
+
return array;
|
|
832
|
+
}
|
|
833
|
+
if ((targetType == int.class || targetType == Integer.class) && value instanceof Number) return ((Number) value).intValue();
|
|
834
|
+
if ((targetType == long.class || targetType == Long.class) && value instanceof Number) return ((Number) value).longValue();
|
|
835
|
+
if ((targetType == double.class || targetType == Double.class) && value instanceof Number) return ((Number) value).doubleValue();
|
|
836
|
+
if ((targetType == float.class || targetType == Float.class) && value instanceof Number) return ((Number) value).floatValue();
|
|
837
|
+
if ((targetType == short.class || targetType == Short.class) && value instanceof Number) return ((Number) value).shortValue();
|
|
838
|
+
if ((targetType == byte.class || targetType == Byte.class) && value instanceof Number) return ((Number) value).byteValue();
|
|
839
|
+
if ((targetType == boolean.class || targetType == Boolean.class) && value instanceof Boolean) return value;
|
|
840
|
+
if ((targetType == char.class || targetType == Character.class) && value instanceof String && ((String) value).length() == 1) {
|
|
841
|
+
return ((String) value).charAt(0);
|
|
842
|
+
}
|
|
843
|
+
return value;
|
|
844
|
+
}`);
|
|
845
|
+
}
|
|
363
846
|
if (features.hasList) {
|
|
364
847
|
members.push(`
|
|
365
|
-
private static ListNode list(
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
848
|
+
private static ListNode list(Object val, ListNode next) {
|
|
849
|
+
try {
|
|
850
|
+
for (java.lang.reflect.Constructor<?> ctor : ListNode.class.getDeclaredConstructors()) {
|
|
851
|
+
Class<?>[] parameterTypes = ctor.getParameterTypes();
|
|
852
|
+
if (parameterTypes.length == 2 && parameterTypes[1] == ListNode.class) {
|
|
853
|
+
ctor.setAccessible(true);
|
|
854
|
+
return (ListNode) ctor.newInstance(coerceMaterializedValue(val, parameterTypes[0]), next);
|
|
855
|
+
}
|
|
856
|
+
}
|
|
857
|
+
for (java.lang.reflect.Constructor<?> ctor : ListNode.class.getDeclaredConstructors()) {
|
|
858
|
+
Class<?>[] parameterTypes = ctor.getParameterTypes();
|
|
859
|
+
if (parameterTypes.length == 1) {
|
|
860
|
+
ctor.setAccessible(true);
|
|
861
|
+
ListNode node = (ListNode) ctor.newInstance(coerceMaterializedValue(val, parameterTypes[0]));
|
|
862
|
+
try {
|
|
863
|
+
java.lang.reflect.Field nextField = ListNode.class.getDeclaredField("next");
|
|
864
|
+
nextField.setAccessible(true);
|
|
865
|
+
nextField.set(node, next);
|
|
866
|
+
} catch (Exception ignored) {
|
|
867
|
+
}
|
|
868
|
+
return node;
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
java.lang.reflect.Constructor<ListNode> ctor = ListNode.class.getDeclaredConstructor();
|
|
872
|
+
ctor.setAccessible(true);
|
|
873
|
+
ListNode node = ctor.newInstance();
|
|
874
|
+
java.lang.reflect.Field valField = ListNode.class.getDeclaredField("val");
|
|
875
|
+
valField.setAccessible(true);
|
|
876
|
+
valField.set(node, coerceMaterializedValue(val, valField.getType()));
|
|
877
|
+
java.lang.reflect.Field nextField = ListNode.class.getDeclaredField("next");
|
|
878
|
+
nextField.setAccessible(true);
|
|
879
|
+
nextField.set(node, next);
|
|
880
|
+
return node;
|
|
881
|
+
} catch (Exception error) {
|
|
882
|
+
throw new RuntimeException("Unable to materialize ListNode", error);
|
|
883
|
+
}
|
|
369
884
|
}
|
|
370
885
|
|
|
371
|
-
private static ListNode buildList(
|
|
886
|
+
private static ListNode buildList(Object[] values, int[] nextIndices) {
|
|
372
887
|
if (values.length == 0) {
|
|
373
888
|
return null;
|
|
374
889
|
}
|
|
375
890
|
ListNode[] nodes = new ListNode[values.length];
|
|
376
891
|
for (int i = 0; i < values.length; i++) {
|
|
377
|
-
nodes[i] =
|
|
892
|
+
nodes[i] = list(values[i], null);
|
|
378
893
|
}
|
|
379
894
|
for (int i = 0; i < values.length; i++) {
|
|
380
895
|
int nextIndex = nextIndices[i];
|
|
381
896
|
nodes[i].next = nextIndex >= 0 ? nodes[nextIndex] : null;
|
|
382
897
|
}
|
|
383
898
|
return nodes[0];
|
|
899
|
+
}
|
|
900
|
+
|
|
901
|
+
private static int[] sequentialNextIndices(int length) {
|
|
902
|
+
int[] indices = new int[length];
|
|
903
|
+
for (int i = 0; i < length; i++) {
|
|
904
|
+
indices[i] = i + 1 < length ? i + 1 : -1;
|
|
905
|
+
}
|
|
906
|
+
return indices;
|
|
384
907
|
}`);
|
|
385
908
|
}
|
|
386
909
|
if (features.hasTree) {
|
|
@@ -390,33 +913,220 @@ function buildHelperMethods(features) {
|
|
|
390
913
|
node.left = left;
|
|
391
914
|
node.right = right;
|
|
392
915
|
return node;
|
|
916
|
+
}
|
|
917
|
+
|
|
918
|
+
private static TreeNode buildTree(Integer[] values) {
|
|
919
|
+
if (values.length == 0 || values[0] == null) {
|
|
920
|
+
return null;
|
|
921
|
+
}
|
|
922
|
+
TreeNode root = new TreeNode(values[0]);
|
|
923
|
+
java.util.Queue<TreeNode> queue = new java.util.ArrayDeque<>();
|
|
924
|
+
queue.add(root);
|
|
925
|
+
int index = 1;
|
|
926
|
+
while (!queue.isEmpty() && index < values.length) {
|
|
927
|
+
TreeNode current = queue.remove();
|
|
928
|
+
if (values[index] != null) {
|
|
929
|
+
current.left = new TreeNode(values[index]);
|
|
930
|
+
queue.add(current.left);
|
|
931
|
+
}
|
|
932
|
+
index++;
|
|
933
|
+
if (index < values.length && values[index] != null) {
|
|
934
|
+
current.right = new TreeNode(values[index]);
|
|
935
|
+
queue.add(current.right);
|
|
936
|
+
}
|
|
937
|
+
index++;
|
|
938
|
+
}
|
|
939
|
+
return root;
|
|
393
940
|
}`);
|
|
941
|
+
}
|
|
942
|
+
if (features.hasMap || features.hasCustomObject) {
|
|
943
|
+
members.push(`
|
|
944
|
+
@SuppressWarnings({"unchecked", "rawtypes"})
|
|
945
|
+
private static <K, V> java.util.LinkedHashMap<K, V> typedMap(Object[][] entries) {
|
|
946
|
+
java.util.LinkedHashMap<K, V> map = new java.util.LinkedHashMap<>();
|
|
947
|
+
for (Object[] entry : entries) {
|
|
948
|
+
map.put((K) entry[0], (V) entry[1]);
|
|
949
|
+
}
|
|
950
|
+
return map;
|
|
951
|
+
}
|
|
952
|
+
`);
|
|
953
|
+
}
|
|
954
|
+
if (features.hasCustomObject) {
|
|
955
|
+
members.push(`
|
|
956
|
+
|
|
957
|
+
private static java.util.LinkedHashMap<String, Object> objectFields(Object[][] entries) {
|
|
958
|
+
java.util.LinkedHashMap<String, Object> fields = new java.util.LinkedHashMap<>();
|
|
959
|
+
for (Object[] entry : entries) {
|
|
960
|
+
fields.put((String) entry[0], entry[1]);
|
|
961
|
+
}
|
|
962
|
+
return fields;
|
|
963
|
+
}
|
|
964
|
+
|
|
965
|
+
private static Object materializeObject(String typeName, java.util.LinkedHashMap<String, Object> fields) {
|
|
966
|
+
try {
|
|
967
|
+
Class<?> cls = Class.forName(new Object() {}.getClass().getPackageName() + "." + typeName);
|
|
968
|
+
Object[] values = fields.values().toArray();
|
|
969
|
+
for (java.lang.reflect.Constructor<?> ctor : cls.getDeclaredConstructors()) {
|
|
970
|
+
if (ctor.getParameterCount() != values.length) {
|
|
971
|
+
continue;
|
|
972
|
+
}
|
|
973
|
+
try {
|
|
974
|
+
Class<?>[] parameterTypes = ctor.getParameterTypes();
|
|
975
|
+
Object[] args = new Object[values.length];
|
|
976
|
+
for (int i = 0; i < values.length; i++) {
|
|
977
|
+
args[i] = coerceMaterializedValue(values[i], parameterTypes[i]);
|
|
978
|
+
}
|
|
979
|
+
ctor.setAccessible(true);
|
|
980
|
+
return ctor.newInstance(args);
|
|
981
|
+
} catch (Exception ignored) {
|
|
982
|
+
}
|
|
983
|
+
}
|
|
984
|
+
for (java.lang.reflect.Constructor<?> ctor : cls.getDeclaredConstructors()) {
|
|
985
|
+
if (ctor.getParameterCount() != 1 || values.length == 0) {
|
|
986
|
+
continue;
|
|
987
|
+
}
|
|
988
|
+
try {
|
|
989
|
+
Class<?>[] parameterTypes = ctor.getParameterTypes();
|
|
990
|
+
ctor.setAccessible(true);
|
|
991
|
+
Object instance = ctor.newInstance(coerceMaterializedValue(values[0], parameterTypes[0]));
|
|
992
|
+
for (java.util.Map.Entry<String, Object> entry : fields.entrySet()) {
|
|
993
|
+
try {
|
|
994
|
+
java.lang.reflect.Field field = cls.getDeclaredField(entry.getKey());
|
|
995
|
+
field.setAccessible(true);
|
|
996
|
+
field.set(instance, coerceMaterializedValue(entry.getValue(), field.getType()));
|
|
997
|
+
} catch (NoSuchFieldException ignored) {
|
|
998
|
+
}
|
|
999
|
+
}
|
|
1000
|
+
return instance;
|
|
1001
|
+
} catch (Exception ignored) {
|
|
1002
|
+
}
|
|
1003
|
+
}
|
|
1004
|
+
java.lang.reflect.Constructor<?> noArg = cls.getDeclaredConstructor();
|
|
1005
|
+
noArg.setAccessible(true);
|
|
1006
|
+
Object instance = noArg.newInstance();
|
|
1007
|
+
for (java.util.Map.Entry<String, Object> entry : fields.entrySet()) {
|
|
1008
|
+
java.lang.reflect.Field field = cls.getDeclaredField(entry.getKey());
|
|
1009
|
+
field.setAccessible(true);
|
|
1010
|
+
field.set(instance, coerceMaterializedValue(entry.getValue(), field.getType()));
|
|
1011
|
+
}
|
|
1012
|
+
return instance;
|
|
1013
|
+
} catch (Exception error) {
|
|
1014
|
+
throw new RuntimeException("Unable to materialize " + typeName, error);
|
|
1015
|
+
}
|
|
1016
|
+
}
|
|
1017
|
+
|
|
1018
|
+
`);
|
|
394
1019
|
}
|
|
395
1020
|
return members.join('\n');
|
|
396
1021
|
}
|
|
397
1022
|
|
|
1023
|
+
function sourceDeclaresJavaClass(source, className) {
|
|
1024
|
+
const escapedName = String(className).replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
1025
|
+
return new RegExp(`\\bclass\\s+${escapedName}\\b`).test(String(source ?? ''));
|
|
1026
|
+
}
|
|
1027
|
+
|
|
1028
|
+
function buildNodePreludeSource(source, options = {}) {
|
|
1029
|
+
if (options.scriptMode === true) {
|
|
1030
|
+
return '';
|
|
1031
|
+
}
|
|
1032
|
+
|
|
1033
|
+
const declarations = [];
|
|
1034
|
+
if (!sourceDeclaresJavaClass(source, 'ListNode')) {
|
|
1035
|
+
declarations.push(`class ListNode {
|
|
1036
|
+
int val;
|
|
1037
|
+
int value;
|
|
1038
|
+
ListNode next;
|
|
1039
|
+
|
|
1040
|
+
ListNode() {
|
|
1041
|
+
this(0, null);
|
|
1042
|
+
}
|
|
1043
|
+
|
|
1044
|
+
ListNode(int val) {
|
|
1045
|
+
this(val, null);
|
|
1046
|
+
}
|
|
1047
|
+
|
|
1048
|
+
ListNode(int val, ListNode next) {
|
|
1049
|
+
this.val = val;
|
|
1050
|
+
this.value = val;
|
|
1051
|
+
this.next = next;
|
|
1052
|
+
}
|
|
1053
|
+
}`);
|
|
1054
|
+
}
|
|
1055
|
+
|
|
1056
|
+
if (!sourceDeclaresJavaClass(source, 'TreeNode')) {
|
|
1057
|
+
declarations.push(`class TreeNode {
|
|
1058
|
+
int val;
|
|
1059
|
+
int value;
|
|
1060
|
+
TreeNode left;
|
|
1061
|
+
TreeNode right;
|
|
1062
|
+
|
|
1063
|
+
TreeNode() {
|
|
1064
|
+
this(0, null, null);
|
|
1065
|
+
}
|
|
1066
|
+
|
|
1067
|
+
TreeNode(int val) {
|
|
1068
|
+
this(val, null, null);
|
|
1069
|
+
}
|
|
1070
|
+
|
|
1071
|
+
TreeNode(int val, TreeNode left, TreeNode right) {
|
|
1072
|
+
this.val = val;
|
|
1073
|
+
this.value = val;
|
|
1074
|
+
this.left = left;
|
|
1075
|
+
this.right = right;
|
|
1076
|
+
}
|
|
1077
|
+
}`);
|
|
1078
|
+
}
|
|
1079
|
+
|
|
1080
|
+
return declarations.length > 0 ? `${declarations.join('\n\n')}\n\n` : '';
|
|
1081
|
+
}
|
|
1082
|
+
|
|
398
1083
|
function extractMethodParameters(source, methodName) {
|
|
1084
|
+
return extractMethodParameterOverloads(source, methodName)[0] ?? [];
|
|
1085
|
+
}
|
|
1086
|
+
|
|
1087
|
+
function extractMethodParameterOverloads(source, methodName) {
|
|
399
1088
|
const compact = source.replace(/\s+/g, ' ');
|
|
400
1089
|
const escapedMethod = methodName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
401
|
-
const
|
|
402
|
-
|
|
403
|
-
|
|
1090
|
+
const overloads = [];
|
|
1091
|
+
const pattern = new RegExp(`\\b${escapedMethod}\\s*\\(([^)]*)\\)`, 'g');
|
|
1092
|
+
for (const match of compact.matchAll(pattern)) {
|
|
1093
|
+
const rawParameters = match[1]?.trim();
|
|
1094
|
+
if (!rawParameters) {
|
|
1095
|
+
overloads.push([]);
|
|
1096
|
+
continue;
|
|
1097
|
+
}
|
|
1098
|
+
overloads.push(
|
|
1099
|
+
splitTopLevelCommaList(rawParameters)
|
|
1100
|
+
.map((segment) => segment.trim())
|
|
1101
|
+
.filter(Boolean)
|
|
1102
|
+
.map((segment) => {
|
|
1103
|
+
const lastSpace = segment.lastIndexOf(' ');
|
|
1104
|
+
if (lastSpace === -1) {
|
|
1105
|
+
return { type: segment, name: segment };
|
|
1106
|
+
}
|
|
1107
|
+
return {
|
|
1108
|
+
type: segment.slice(0, lastSpace).trim(),
|
|
1109
|
+
name: segment.slice(lastSpace + 1).trim(),
|
|
1110
|
+
};
|
|
1111
|
+
})
|
|
1112
|
+
);
|
|
404
1113
|
}
|
|
1114
|
+
return overloads;
|
|
1115
|
+
}
|
|
405
1116
|
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
});
|
|
1117
|
+
function extractMethodParametersForArguments(source, methodName, rawArgs) {
|
|
1118
|
+
const args = Array.isArray(rawArgs) ? rawArgs : [];
|
|
1119
|
+
const overloads = extractMethodParameterOverloads(source, methodName);
|
|
1120
|
+
return overloads.find((parameters) => parameters.length === args.length) ?? overloads[0] ?? [];
|
|
1121
|
+
}
|
|
1122
|
+
|
|
1123
|
+
function extractMethodReturnType(source, methodName) {
|
|
1124
|
+
const compact = source.replace(/\s+/g, ' ');
|
|
1125
|
+
const escapedMethod = methodName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
1126
|
+
const match = compact.match(
|
|
1127
|
+
new RegExp(`\\b(?:public|private|protected|static|final|synchronized|abstract|native|strictfp|\\s)*([A-Za-z_][A-Za-z0-9_<>,.?\\[\\]\\s]*)\\s+${escapedMethod}\\s*\\(`)
|
|
1128
|
+
);
|
|
1129
|
+
return match?.[1]?.trim() ?? null;
|
|
420
1130
|
}
|
|
421
1131
|
|
|
422
1132
|
function indentBlock(source, spaces = 2) {
|
|
@@ -507,7 +1217,68 @@ function findMatchingParen(source, openIndex) {
|
|
|
507
1217
|
return closeIndex;
|
|
508
1218
|
}
|
|
509
1219
|
|
|
1220
|
+
function findMatchingBrace(source, openIndex) {
|
|
1221
|
+
let depth = 0;
|
|
1222
|
+
let closeIndex = -1;
|
|
1223
|
+
scanJavaCode(source, openIndex, source.length, (index, ch) => {
|
|
1224
|
+
if (ch === '{') depth += 1;
|
|
1225
|
+
if (ch === '}') {
|
|
1226
|
+
depth -= 1;
|
|
1227
|
+
if (depth === 0) {
|
|
1228
|
+
closeIndex = index;
|
|
1229
|
+
return false;
|
|
1230
|
+
}
|
|
1231
|
+
}
|
|
1232
|
+
return undefined;
|
|
1233
|
+
});
|
|
1234
|
+
return closeIndex;
|
|
1235
|
+
}
|
|
1236
|
+
|
|
510
1237
|
function findSingleStatementEnd(source, bodyStart) {
|
|
1238
|
+
let cursor = bodyStart;
|
|
1239
|
+
while (/\s/.test(source[cursor] ?? '')) cursor += 1;
|
|
1240
|
+
if (startsWithJavaKeyword(source, cursor, 'if')) {
|
|
1241
|
+
let headerStart = cursor + 'if'.length;
|
|
1242
|
+
while (/\s/.test(source[headerStart] ?? '')) headerStart += 1;
|
|
1243
|
+
if (source[headerStart] === '(') {
|
|
1244
|
+
const closeParen = findMatchingParen(source, headerStart);
|
|
1245
|
+
if (closeParen >= 0) {
|
|
1246
|
+
let nestedBodyStart = closeParen + 1;
|
|
1247
|
+
while (/\s/.test(source[nestedBodyStart] ?? '')) nestedBodyStart += 1;
|
|
1248
|
+
if (source[nestedBodyStart] === '{') {
|
|
1249
|
+
const closeBrace = findMatchingBrace(source, nestedBodyStart);
|
|
1250
|
+
if (closeBrace >= 0) return closeBrace;
|
|
1251
|
+
}
|
|
1252
|
+
if (source[nestedBodyStart] && source[nestedBodyStart] !== ';') {
|
|
1253
|
+
return findSingleStatementEnd(source, nestedBodyStart);
|
|
1254
|
+
}
|
|
1255
|
+
}
|
|
1256
|
+
}
|
|
1257
|
+
}
|
|
1258
|
+
const loopKeyword = startsWithJavaKeyword(source, cursor, 'for')
|
|
1259
|
+
? 'for'
|
|
1260
|
+
: startsWithJavaKeyword(source, cursor, 'while')
|
|
1261
|
+
? 'while'
|
|
1262
|
+
: null;
|
|
1263
|
+
if (loopKeyword) {
|
|
1264
|
+
let headerStart = cursor + loopKeyword.length;
|
|
1265
|
+
while (/\s/.test(source[headerStart] ?? '')) headerStart += 1;
|
|
1266
|
+
if (source[headerStart] === '(') {
|
|
1267
|
+
const closeParen = findMatchingParen(source, headerStart);
|
|
1268
|
+
if (closeParen >= 0) {
|
|
1269
|
+
let nestedBodyStart = closeParen + 1;
|
|
1270
|
+
while (/\s/.test(source[nestedBodyStart] ?? '')) nestedBodyStart += 1;
|
|
1271
|
+
if (source[nestedBodyStart] === '{') {
|
|
1272
|
+
const closeBrace = findMatchingBrace(source, nestedBodyStart);
|
|
1273
|
+
if (closeBrace >= 0) return closeBrace;
|
|
1274
|
+
}
|
|
1275
|
+
if (source[nestedBodyStart] && source[nestedBodyStart] !== ';') {
|
|
1276
|
+
return findSingleStatementEnd(source, nestedBodyStart);
|
|
1277
|
+
}
|
|
1278
|
+
}
|
|
1279
|
+
}
|
|
1280
|
+
}
|
|
1281
|
+
|
|
511
1282
|
let parenDepth = 0;
|
|
512
1283
|
let bracketDepth = 0;
|
|
513
1284
|
let braceDepth = 0;
|
|
@@ -537,14 +1308,64 @@ function startsWithJavaKeyword(source, index, keyword) {
|
|
|
537
1308
|
return !after || !isJavaIdentifierPart(after);
|
|
538
1309
|
}
|
|
539
1310
|
|
|
540
|
-
function
|
|
541
|
-
|
|
1311
|
+
function braceDeltaForLine(line) {
|
|
1312
|
+
let delta = 0;
|
|
1313
|
+
scanJavaCode(line, 0, line.length, (_index, ch) => {
|
|
1314
|
+
if (ch === '{') delta += 1;
|
|
1315
|
+
if (ch === '}') delta -= 1;
|
|
1316
|
+
return undefined;
|
|
1317
|
+
});
|
|
1318
|
+
return delta;
|
|
1319
|
+
}
|
|
1320
|
+
|
|
1321
|
+
function isUnbracedLoopHeaderLine(line) {
|
|
1322
|
+
const trimmed = line.trim();
|
|
1323
|
+
return /^(?:for|while)\s*\(.*\)\s*$/.test(trimmed) && !trimmed.includes('{') && !trimmed.endsWith(';');
|
|
1324
|
+
}
|
|
1325
|
+
|
|
1326
|
+
function startsBracedLoopLine(line) {
|
|
1327
|
+
const trimmed = line.trim();
|
|
1328
|
+
return /^(?:for|while)\s*\(.*\)\s*\{/.test(trimmed);
|
|
1329
|
+
}
|
|
1330
|
+
|
|
1331
|
+
function wrapNestedBracedLoopBodies(source) {
|
|
1332
|
+
const lines = source.split(/\r?\n/);
|
|
1333
|
+
const output = [];
|
|
1334
|
+
let changed = false;
|
|
1335
|
+
for (let index = 0; index < lines.length; index += 1) {
|
|
1336
|
+
const line = lines[index] ?? '';
|
|
1337
|
+
const next = lines[index + 1] ?? '';
|
|
1338
|
+
if (!isUnbracedLoopHeaderLine(line) || !startsBracedLoopLine(next)) {
|
|
1339
|
+
output.push(line);
|
|
1340
|
+
continue;
|
|
1341
|
+
}
|
|
1342
|
+
|
|
1343
|
+
changed = true;
|
|
1344
|
+
output.push(`${line} {`);
|
|
1345
|
+
index += 1;
|
|
1346
|
+
let depth = 0;
|
|
1347
|
+
for (; index < lines.length; index += 1) {
|
|
1348
|
+
const nestedLine = lines[index] ?? '';
|
|
1349
|
+
output.push(nestedLine);
|
|
1350
|
+
depth += braceDeltaForLine(nestedLine);
|
|
1351
|
+
if (depth <= 0) break;
|
|
1352
|
+
}
|
|
1353
|
+
output.push(`${line.match(/^\s*/)?.[0] ?? ''}}`);
|
|
1354
|
+
}
|
|
1355
|
+
return changed ? output.join('\n') : source;
|
|
1356
|
+
}
|
|
1357
|
+
|
|
1358
|
+
function wrapSingleStatementLoopBodies(source) {
|
|
1359
|
+
source = wrapNestedBracedLoopBodies(source);
|
|
1360
|
+
const inserts = [];
|
|
542
1361
|
scanJavaCode(source, 0, source.length, (index) => {
|
|
543
1362
|
const keyword = source.startsWith('for', index)
|
|
544
1363
|
? 'for'
|
|
545
1364
|
: source.startsWith('while', index)
|
|
546
1365
|
? 'while'
|
|
547
|
-
:
|
|
1366
|
+
: source.startsWith('if', index)
|
|
1367
|
+
? 'if'
|
|
1368
|
+
: null;
|
|
548
1369
|
if (!keyword) return undefined;
|
|
549
1370
|
|
|
550
1371
|
const before = index > 0 ? source[index - 1] : '';
|
|
@@ -565,7 +1386,6 @@ function wrapSingleStatementLoopBodies(source) {
|
|
|
565
1386
|
const bodyChar = source[bodyStart];
|
|
566
1387
|
if (!bodyChar || bodyChar === '{' || bodyChar === ';') return closeParen;
|
|
567
1388
|
if (
|
|
568
|
-
startsWithJavaKeyword(source, bodyStart, 'if') ||
|
|
569
1389
|
startsWithJavaKeyword(source, bodyStart, 'switch') ||
|
|
570
1390
|
startsWithJavaKeyword(source, bodyStart, 'synchronized') ||
|
|
571
1391
|
startsWithJavaKeyword(source, bodyStart, 'try')
|
|
@@ -593,7 +1413,7 @@ function wrapSingleStatementLoopBodies(source) {
|
|
|
593
1413
|
output += insertsByIndex.get(index) ?? '';
|
|
594
1414
|
if (index < source.length) output += source[index];
|
|
595
1415
|
}
|
|
596
|
-
return output;
|
|
1416
|
+
return output === source ? output : wrapSingleStatementLoopBodies(output);
|
|
597
1417
|
}
|
|
598
1418
|
|
|
599
1419
|
function splitTopLevelJavaList(value) {
|
|
@@ -675,12 +1495,18 @@ function escapeRegExp(value) {
|
|
|
675
1495
|
return String(value).replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
676
1496
|
}
|
|
677
1497
|
|
|
1498
|
+
function parseNativeTraceLine(line) {
|
|
1499
|
+
const match = line.match(/TraceHooks\.emit(?:Line|Call|Return)AtLine\((\d+)\b/);
|
|
1500
|
+
if (!match) return null;
|
|
1501
|
+
const lineNumber = Number.parseInt(match[1], 10);
|
|
1502
|
+
return Number.isFinite(lineNumber) && lineNumber > 0 ? lineNumber : null;
|
|
1503
|
+
}
|
|
1504
|
+
|
|
678
1505
|
function augmentTraceCallArgumentSnapshots(source) {
|
|
679
1506
|
const lines = source.split('\n');
|
|
680
1507
|
const methodStack = [];
|
|
681
1508
|
const methodStartPattern =
|
|
682
1509
|
/^(\s*)(?:(?:public|private|protected|static|final|synchronized)\s+)*(?:[A-Za-z_][A-Za-z0-9_<>\[\], ?]*\s+)+([A-Za-z_][A-Za-z0-9_]*)\s*\(([^)]*)\)\s*\{\s*$/;
|
|
683
|
-
|
|
684
1510
|
return lines.map((line) => {
|
|
685
1511
|
const methodMatch = line.match(methodStartPattern);
|
|
686
1512
|
if (methodMatch) {
|
|
@@ -697,14 +1523,14 @@ function augmentTraceCallArgumentSnapshots(source) {
|
|
|
697
1523
|
let nextLine = line;
|
|
698
1524
|
if (currentMethod && !currentMethod.patchedCall && currentMethod.params.length > 0) {
|
|
699
1525
|
const callPattern = new RegExp(
|
|
700
|
-
`^(\\s*)TraceHooks\\.
|
|
1526
|
+
`^(\\s*)TraceHooks\\.emitCallAtLine\\((\\d+),\\s*"${escapeRegExp(currentMethod.name)}",\\s*([^)]*)\\);\\s*$`
|
|
701
1527
|
);
|
|
702
1528
|
const callMatch = line.match(callPattern);
|
|
703
1529
|
if (callMatch) {
|
|
704
1530
|
const serializedArgs = currentMethod.params
|
|
705
1531
|
.map((paramName) => ` + " ${paramName}=" + TraceHooks.serializeResult(${paramName})`)
|
|
706
1532
|
.join('');
|
|
707
|
-
nextLine = `${callMatch[1]}TraceHooks.
|
|
1533
|
+
nextLine = `${callMatch[1]}TraceHooks.emitCallAtLine(${callMatch[2]}, "${currentMethod.name}", ""${serializedArgs});`;
|
|
708
1534
|
currentMethod.patchedCall = true;
|
|
709
1535
|
}
|
|
710
1536
|
}
|
|
@@ -720,6 +1546,403 @@ function augmentTraceCallArgumentSnapshots(source) {
|
|
|
720
1546
|
}).join('\n');
|
|
721
1547
|
}
|
|
722
1548
|
|
|
1549
|
+
function collectJavaLocalDeclarations(line) {
|
|
1550
|
+
const names = [];
|
|
1551
|
+
const trimmedLine = String(line).trim();
|
|
1552
|
+
if (trimmedLine.startsWith('//') || trimmedLine.startsWith('/*') || trimmedLine.startsWith('*')) {
|
|
1553
|
+
return names;
|
|
1554
|
+
}
|
|
1555
|
+
const declarationPattern =
|
|
1556
|
+
/\b(?:final\s+)?((?:boolean|byte|char|short|int|long|float|double|String|Object|[A-Za-z_][A-Za-z0-9_<>.?]*(?:\s*<[^,;=(){}:]+>)?)\s*(?:\[\s*\])*)\s+([A-Za-z_][A-Za-z0-9_]*)\s*(?==)/g;
|
|
1557
|
+
const skippedNames = new Set(['class', 'interface', 'enum', 'record', 'return', 'new']);
|
|
1558
|
+
for (const match of line.matchAll(declarationPattern)) {
|
|
1559
|
+
const typeSource = match[1] ?? '';
|
|
1560
|
+
const name = match[2];
|
|
1561
|
+
if (name && !skippedNames.has(name) && !name.startsWith('__tracecode')) {
|
|
1562
|
+
names.push(name);
|
|
1563
|
+
}
|
|
1564
|
+
}
|
|
1565
|
+
const enhancedForMatch = line.match(
|
|
1566
|
+
/\bfor\s*\(\s*(?:final\s+)?((?:boolean|byte|char|short|int|long|float|double|String|Object|[A-Za-z_][A-Za-z0-9_<>.?]*(?:\s*<[^,;=(){}:]+>)?)\s*(?:\[\s*\])*)\s+([A-Za-z_][A-Za-z0-9_]*)\s*:/
|
|
1567
|
+
);
|
|
1568
|
+
const enhancedForType = enhancedForMatch?.[1] ?? '';
|
|
1569
|
+
const enhancedForName = enhancedForMatch?.[2];
|
|
1570
|
+
if (enhancedForName && !skippedNames.has(enhancedForName) && !enhancedForName.startsWith('__tracecode')) {
|
|
1571
|
+
names.push(enhancedForName);
|
|
1572
|
+
}
|
|
1573
|
+
return names;
|
|
1574
|
+
}
|
|
1575
|
+
|
|
1576
|
+
function visibleJavaLocalNames(scopeStack) {
|
|
1577
|
+
const names = [];
|
|
1578
|
+
const seen = new Set();
|
|
1579
|
+
for (const scope of scopeStack) {
|
|
1580
|
+
for (const name of scope.names) {
|
|
1581
|
+
if (!seen.has(name)) {
|
|
1582
|
+
names.push(name);
|
|
1583
|
+
seen.add(name);
|
|
1584
|
+
}
|
|
1585
|
+
}
|
|
1586
|
+
}
|
|
1587
|
+
return names;
|
|
1588
|
+
}
|
|
1589
|
+
|
|
1590
|
+
function isUnbracedForDeclarationLine(line) {
|
|
1591
|
+
return /^\s*for\s*\(/.test(line) && !(line.includes('{'));
|
|
1592
|
+
}
|
|
1593
|
+
|
|
1594
|
+
function isControlHeaderDeclarationLine(line) {
|
|
1595
|
+
return /^\s*(?:for|if|while|switch|catch)\s*\(/.test(line);
|
|
1596
|
+
}
|
|
1597
|
+
|
|
1598
|
+
function traceEmitAlreadyIncludesVariable(emitExpression, name) {
|
|
1599
|
+
return new RegExp(`\\b${escapeRegExp(name)}=`).test(emitExpression);
|
|
1600
|
+
}
|
|
1601
|
+
|
|
1602
|
+
function appendJavaLocalSnapshotsToEmitLine(line, scopeStack) {
|
|
1603
|
+
const visibleNames = visibleJavaLocalNames(scopeStack);
|
|
1604
|
+
if (visibleNames.length === 0 || !line.includes('TraceHooks.emitLineAtLine(')) {
|
|
1605
|
+
return line;
|
|
1606
|
+
}
|
|
1607
|
+
|
|
1608
|
+
return line.replace(/TraceHooks\.emitLineAtLine\((\d+)(?:,\s*([^;]*?))?\);/g, (match, lineNumber, snapshotExpression) => {
|
|
1609
|
+
const emitExpression = snapshotExpression ?? '';
|
|
1610
|
+
const additions = visibleNames
|
|
1611
|
+
.filter((name) => !traceEmitAlreadyIncludesVariable(emitExpression, name))
|
|
1612
|
+
.map((name) => ` + " ${name}=" + TraceHooks.serializeResult(${name})`)
|
|
1613
|
+
.join('');
|
|
1614
|
+
if (!additions) return match;
|
|
1615
|
+
const prefix = emitExpression.trim().length > 0 ? emitExpression.trim() : '""';
|
|
1616
|
+
return `TraceHooks.emitLineAtLine(${Number.parseInt(lineNumber, 10)}, ${prefix}${additions});`;
|
|
1617
|
+
});
|
|
1618
|
+
}
|
|
1619
|
+
|
|
1620
|
+
function appendJavaLocalSnapshotsAfterMutations(line, scopeStack) {
|
|
1621
|
+
const visibleNames = visibleJavaLocalNames(scopeStack);
|
|
1622
|
+
if (visibleNames.length === 0 || !line.includes('TraceHooks.emitMutatingCallAtLine(')) {
|
|
1623
|
+
return line;
|
|
1624
|
+
}
|
|
1625
|
+
|
|
1626
|
+
return line.replace(
|
|
1627
|
+
/(TraceHooks\.emitMutatingCallAtLine\((\d+),[^;]+;\s*)/g,
|
|
1628
|
+
(match, statement, lineNumber) => {
|
|
1629
|
+
const additions = visibleNames
|
|
1630
|
+
.map((name) => ` + " ${name}=" + TraceHooks.serializeResult(${name})`)
|
|
1631
|
+
.join('');
|
|
1632
|
+
return `${statement} TraceHooks.emitLineAtLine(${lineNumber}, ""${additions});`;
|
|
1633
|
+
}
|
|
1634
|
+
);
|
|
1635
|
+
}
|
|
1636
|
+
|
|
1637
|
+
function guardJavaLineEmit(line) {
|
|
1638
|
+
return line.replace(
|
|
1639
|
+
/^(\s*)TraceHooks\.emitLineAtLine\((.+)\);\s*$/,
|
|
1640
|
+
(_match, indent, argsSource) => `${indent}if (!TraceHooks.traceLimitExceeded()) TraceHooks.emitLineAtLine(${argsSource});`
|
|
1641
|
+
);
|
|
1642
|
+
}
|
|
1643
|
+
|
|
1644
|
+
function appendJavaScalarDeclarationWrites(line, lineNumber) {
|
|
1645
|
+
if (line.includes('TraceHooks.emitScalarWriteAtLine(')) return line;
|
|
1646
|
+
if (/TraceHooks\.read[A-Za-z0-9_]*AtLine\(/.test(line)) return line;
|
|
1647
|
+
if (/^\s*(?:for|if|while|switch|catch)\s*\(/.test(line)) return line;
|
|
1648
|
+
if (!/;\s*$/.test(line)) return line;
|
|
1649
|
+
const declarations = collectJavaLocalDeclarations(line);
|
|
1650
|
+
if (declarations.length === 0) return line;
|
|
1651
|
+
const indent = line.match(/^(\s*)/)?.[1] ?? '';
|
|
1652
|
+
const writes = declarations
|
|
1653
|
+
.map((name) => `${indent}TraceHooks.emitScalarWriteAtLine(${lineNumber}, "${name}", ${name});`)
|
|
1654
|
+
.join('\n');
|
|
1655
|
+
return `${line}\n${writes}`;
|
|
1656
|
+
}
|
|
1657
|
+
|
|
1658
|
+
function appendJavaPendingScalarDeclarationWrites(line, lineNumber, declarations) {
|
|
1659
|
+
if (!Array.isArray(declarations) || declarations.length === 0) return line;
|
|
1660
|
+
if (!/;\s*$/.test(line)) return line;
|
|
1661
|
+
const indent = line.match(/^(\s*)/)?.[1] ?? '';
|
|
1662
|
+
const writes = declarations
|
|
1663
|
+
.map((name) => `${indent}TraceHooks.emitScalarWriteAtLine(${lineNumber}, "${name}", ${name});`)
|
|
1664
|
+
.join('\n');
|
|
1665
|
+
return writes ? `${line}\n${writes}` : line;
|
|
1666
|
+
}
|
|
1667
|
+
|
|
1668
|
+
function augmentJavaLocalSnapshots(source) {
|
|
1669
|
+
const lines = source.split('\n');
|
|
1670
|
+
const output = [];
|
|
1671
|
+
const scopeStack = [];
|
|
1672
|
+
let currentTraceLine = null;
|
|
1673
|
+
let pendingScalarDeclarationWrites = null;
|
|
1674
|
+
let methodDepth = 0;
|
|
1675
|
+
let generatedExportsClassDepth = null;
|
|
1676
|
+
const methodStartPattern =
|
|
1677
|
+
/^(\s*)(?:(?:public|private|protected|static|final|synchronized)\s+)*(?:[A-Za-z_][A-Za-z0-9_<>\[\], ?]*\s+)+([A-Za-z_][A-Za-z0-9_]*)\s*\(([^)]*)\)\s*\{\s*$/;
|
|
1678
|
+
const generatedExportsClassPattern = /^\s*(?:(?:public|private|protected|static|final)\s+)*class\s+Exports[A-Za-z0-9_]*\s*\{/;
|
|
1679
|
+
|
|
1680
|
+
for (const line of lines) {
|
|
1681
|
+
if (generatedExportsClassDepth !== null) {
|
|
1682
|
+
output.push(line);
|
|
1683
|
+
generatedExportsClassDepth += braceDelta(line);
|
|
1684
|
+
if (generatedExportsClassDepth <= 0) generatedExportsClassDepth = null;
|
|
1685
|
+
continue;
|
|
1686
|
+
}
|
|
1687
|
+
if (generatedExportsClassPattern.test(line)) {
|
|
1688
|
+
output.push(line);
|
|
1689
|
+
generatedExportsClassDepth = Math.max(0, braceDelta(line));
|
|
1690
|
+
if (generatedExportsClassDepth <= 0) generatedExportsClassDepth = null;
|
|
1691
|
+
continue;
|
|
1692
|
+
}
|
|
1693
|
+
if (methodDepth <= 0) {
|
|
1694
|
+
const methodMatch = line.match(methodStartPattern);
|
|
1695
|
+
if (methodMatch) {
|
|
1696
|
+
methodDepth = Math.max(0, braceDelta(line));
|
|
1697
|
+
const params = parseJavaParameterNames(methodMatch[3] ?? '');
|
|
1698
|
+
scopeStack.length = 0;
|
|
1699
|
+
scopeStack.push({ names: params });
|
|
1700
|
+
output.push(line);
|
|
1701
|
+
if (methodDepth <= 0) {
|
|
1702
|
+
scopeStack.length = 0;
|
|
1703
|
+
pendingScalarDeclarationWrites = null;
|
|
1704
|
+
}
|
|
1705
|
+
continue;
|
|
1706
|
+
}
|
|
1707
|
+
output.push(line);
|
|
1708
|
+
continue;
|
|
1709
|
+
}
|
|
1710
|
+
|
|
1711
|
+
const leadingClosingCount = line.match(/^\s*}+/)?.[0].replace(/\s/g, '').length ?? 0;
|
|
1712
|
+
for (let index = 0; index < leadingClosingCount; index += 1) {
|
|
1713
|
+
if (scopeStack.length > 0) scopeStack.pop();
|
|
1714
|
+
}
|
|
1715
|
+
|
|
1716
|
+
const transformedLine = guardJavaLineEmit(appendJavaLocalSnapshotsAfterMutations(
|
|
1717
|
+
appendJavaLocalSnapshotsToEmitLine(line, scopeStack),
|
|
1718
|
+
scopeStack
|
|
1719
|
+
));
|
|
1720
|
+
output.push(transformedLine);
|
|
1721
|
+
const emittedTraceLine = parseNativeTraceLine(output[output.length - 1]);
|
|
1722
|
+
if (emittedTraceLine !== null) currentTraceLine = emittedTraceLine;
|
|
1723
|
+
|
|
1724
|
+
const declarations = collectJavaLocalDeclarations(line);
|
|
1725
|
+
if (declarations.length > 0 && currentTraceLine !== null) {
|
|
1726
|
+
const lastIndex = output.length - 1;
|
|
1727
|
+
output[lastIndex] = appendJavaScalarDeclarationWrites(output[lastIndex], currentTraceLine);
|
|
1728
|
+
if (
|
|
1729
|
+
!isControlHeaderDeclarationLine(line) &&
|
|
1730
|
+
line.includes('=') &&
|
|
1731
|
+
!/;\s*$/.test(line)
|
|
1732
|
+
) {
|
|
1733
|
+
pendingScalarDeclarationWrites = {
|
|
1734
|
+
lineNumber: currentTraceLine,
|
|
1735
|
+
declarations: [...declarations],
|
|
1736
|
+
};
|
|
1737
|
+
}
|
|
1738
|
+
} else if (pendingScalarDeclarationWrites && /;\s*$/.test(line)) {
|
|
1739
|
+
const lastIndex = output.length - 1;
|
|
1740
|
+
output[lastIndex] = appendJavaPendingScalarDeclarationWrites(
|
|
1741
|
+
output[lastIndex],
|
|
1742
|
+
pendingScalarDeclarationWrites.lineNumber,
|
|
1743
|
+
pendingScalarDeclarationWrites.declarations
|
|
1744
|
+
);
|
|
1745
|
+
pendingScalarDeclarationWrites = null;
|
|
1746
|
+
}
|
|
1747
|
+
const declarationsBelongToCurrentScope =
|
|
1748
|
+
declarations.length > 0 && !isControlHeaderDeclarationLine(line);
|
|
1749
|
+
if (declarationsBelongToCurrentScope) {
|
|
1750
|
+
const currentScope = scopeStack[scopeStack.length - 1];
|
|
1751
|
+
if (currentScope) {
|
|
1752
|
+
for (const name of declarations) {
|
|
1753
|
+
currentScope.names.push(name);
|
|
1754
|
+
}
|
|
1755
|
+
}
|
|
1756
|
+
}
|
|
1757
|
+
const braceCounts = javaBraceCounts(line);
|
|
1758
|
+
const openingCount = braceCounts.open;
|
|
1759
|
+
const closingCount = Math.max(0, braceCounts.close - leadingClosingCount);
|
|
1760
|
+
for (let index = 0; index < openingCount; index += 1) {
|
|
1761
|
+
scopeStack.push({ names: index === 0 && !declarationsBelongToCurrentScope ? declarations : [] });
|
|
1762
|
+
}
|
|
1763
|
+
if (
|
|
1764
|
+
openingCount === 0 &&
|
|
1765
|
+
declarations.length > 0 &&
|
|
1766
|
+
!declarationsBelongToCurrentScope &&
|
|
1767
|
+
!isUnbracedForDeclarationLine(line)
|
|
1768
|
+
) {
|
|
1769
|
+
const currentScope = scopeStack[scopeStack.length - 1];
|
|
1770
|
+
if (currentScope) {
|
|
1771
|
+
for (const name of declarations) {
|
|
1772
|
+
currentScope.names.push(name);
|
|
1773
|
+
}
|
|
1774
|
+
}
|
|
1775
|
+
}
|
|
1776
|
+
for (let index = 0; index < closingCount; index += 1) {
|
|
1777
|
+
if (scopeStack.length > 0) scopeStack.pop();
|
|
1778
|
+
}
|
|
1779
|
+
methodDepth += braceCounts.delta;
|
|
1780
|
+
if (methodDepth <= 0) {
|
|
1781
|
+
methodDepth = 0;
|
|
1782
|
+
scopeStack.length = 0;
|
|
1783
|
+
pendingScalarDeclarationWrites = null;
|
|
1784
|
+
}
|
|
1785
|
+
}
|
|
1786
|
+
|
|
1787
|
+
return output.join('\n');
|
|
1788
|
+
}
|
|
1789
|
+
|
|
1790
|
+
function collectJavaObjectDeclarations(line) {
|
|
1791
|
+
const names = [];
|
|
1792
|
+
const declarationPattern =
|
|
1793
|
+
/\b([A-Z][A-Za-z0-9_]*)\s+([A-Za-z_][A-Za-z0-9_]*)\s*=\s*new\s+\1\s*\(/g;
|
|
1794
|
+
for (const match of line.matchAll(declarationPattern)) {
|
|
1795
|
+
if (match[2]) names.push(match[2]);
|
|
1796
|
+
}
|
|
1797
|
+
return names;
|
|
1798
|
+
}
|
|
1799
|
+
|
|
1800
|
+
function rewriteJavaObjectFieldReads(expression, objectNames, lineNumber) {
|
|
1801
|
+
let output = expression;
|
|
1802
|
+
for (const name of objectNames) {
|
|
1803
|
+
const fieldPattern = new RegExp(`\\b${escapeRegExp(name)}\\.([A-Za-z_][A-Za-z0-9_]*)\\b`, 'g');
|
|
1804
|
+
output = output.replace(fieldPattern, (match, field, offset, fullSource) => {
|
|
1805
|
+
const marker = fullSource.lastIndexOf('TraceHooks.', offset);
|
|
1806
|
+
const delimiter = Math.max(fullSource.lastIndexOf(';', offset), fullSource.lastIndexOf('\n', offset));
|
|
1807
|
+
if (marker > delimiter) return match;
|
|
1808
|
+
const nextChar = fullSource[offset + match.length] ?? '';
|
|
1809
|
+
if (nextChar === '(') return match;
|
|
1810
|
+
return `TraceHooks.readObjectFieldAtLine(${lineNumber}, "${name}", "${field}", ${match})`;
|
|
1811
|
+
});
|
|
1812
|
+
}
|
|
1813
|
+
return output;
|
|
1814
|
+
}
|
|
1815
|
+
|
|
1816
|
+
function augmentJavaObjectFieldOperations(source) {
|
|
1817
|
+
const lines = source.split('\n');
|
|
1818
|
+
const methodStack = [];
|
|
1819
|
+
const methodStartPattern =
|
|
1820
|
+
/^(\s*)(?:(?:public|private|protected|static|final|synchronized)\s+)*(?:[A-Za-z_][A-Za-z0-9_<>\[\], ?]*\s+)+([A-Za-z_][A-Za-z0-9_]*)\s*\(([^)]*)\)\s*\{\s*$/;
|
|
1821
|
+
|
|
1822
|
+
return lines.map((line) => {
|
|
1823
|
+
const methodMatch = line.match(methodStartPattern);
|
|
1824
|
+
if (methodMatch) {
|
|
1825
|
+
methodStack.push({
|
|
1826
|
+
depth: 1,
|
|
1827
|
+
currentTraceLine: null,
|
|
1828
|
+
objectNames: new Set(),
|
|
1829
|
+
});
|
|
1830
|
+
return line;
|
|
1831
|
+
}
|
|
1832
|
+
|
|
1833
|
+
const currentMethod = methodStack[methodStack.length - 1];
|
|
1834
|
+
let nextLine = line;
|
|
1835
|
+
if (!currentMethod) return nextLine;
|
|
1836
|
+
|
|
1837
|
+
for (const name of collectJavaObjectDeclarations(line)) {
|
|
1838
|
+
currentMethod.objectNames.add(name);
|
|
1839
|
+
}
|
|
1840
|
+
|
|
1841
|
+
const traceLine = parseNativeTraceLine(line);
|
|
1842
|
+
if (traceLine !== null) currentMethod.currentTraceLine = traceLine;
|
|
1843
|
+
|
|
1844
|
+
const lineNumber = currentMethod.currentTraceLine;
|
|
1845
|
+
if (lineNumber !== null && currentMethod.objectNames.size > 0) {
|
|
1846
|
+
for (const name of currentMethod.objectNames) {
|
|
1847
|
+
const writePattern = new RegExp(`^(\\s*)${escapeRegExp(name)}\\.([A-Za-z_][A-Za-z0-9_]*)\\s*=\\s*(.+);\\s*$`);
|
|
1848
|
+
const writeMatch = nextLine.match(writePattern);
|
|
1849
|
+
if (writeMatch) {
|
|
1850
|
+
const indent = writeMatch[1] ?? '';
|
|
1851
|
+
const field = writeMatch[2];
|
|
1852
|
+
const rhs = writeMatch[3];
|
|
1853
|
+
nextLine = `${indent}{ ${name}.${field} = ${rhs}; TraceHooks.emitFieldWriteAtLine(${lineNumber}, "${name}", "${field}", ${name}.${field}); }`;
|
|
1854
|
+
break;
|
|
1855
|
+
}
|
|
1856
|
+
}
|
|
1857
|
+
|
|
1858
|
+
const returnMatch = nextLine.match(/^(\s*)return\s+(.+);\s*$/);
|
|
1859
|
+
if (returnMatch) {
|
|
1860
|
+
nextLine = `${returnMatch[1]}return ${rewriteJavaObjectFieldReads(returnMatch[2], currentMethod.objectNames, lineNumber)};`;
|
|
1861
|
+
}
|
|
1862
|
+
}
|
|
1863
|
+
|
|
1864
|
+
currentMethod.depth += braceDelta(nextLine);
|
|
1865
|
+
while (methodStack.length > 0 && methodStack[methodStack.length - 1].depth <= 0) {
|
|
1866
|
+
methodStack.pop();
|
|
1867
|
+
}
|
|
1868
|
+
return nextLine;
|
|
1869
|
+
}).join('\n');
|
|
1870
|
+
}
|
|
1871
|
+
|
|
1872
|
+
function augmentJavaThrowEvents(source) {
|
|
1873
|
+
const lines = source.split('\n');
|
|
1874
|
+
const methodStack = [];
|
|
1875
|
+
let thrownIndex = 0;
|
|
1876
|
+
const methodStartPattern =
|
|
1877
|
+
/^(\s*)(?:(?:public|private|protected|static|final|synchronized)\s+)*(?:[A-Za-z_][A-Za-z0-9_<>\[\], ?]*\s+)+([A-Za-z_][A-Za-z0-9_]*)\s*\(([^)]*)\)\s*\{\s*$/;
|
|
1878
|
+
|
|
1879
|
+
return lines.map((line) => {
|
|
1880
|
+
const methodMatch = line.match(methodStartPattern);
|
|
1881
|
+
if (methodMatch) {
|
|
1882
|
+
methodStack.push({ depth: 1, currentTraceLine: null });
|
|
1883
|
+
return line;
|
|
1884
|
+
}
|
|
1885
|
+
|
|
1886
|
+
const currentMethod = methodStack[methodStack.length - 1];
|
|
1887
|
+
let nextLine = line;
|
|
1888
|
+
if (!currentMethod) return nextLine;
|
|
1889
|
+
|
|
1890
|
+
const traceLine = parseNativeTraceLine(line);
|
|
1891
|
+
if (traceLine !== null) currentMethod.currentTraceLine = traceLine;
|
|
1892
|
+
|
|
1893
|
+
const throwMatch = nextLine.match(/^(\s*)throw\s+(.+);\s*$/);
|
|
1894
|
+
if (throwMatch && currentMethod.currentTraceLine !== null) {
|
|
1895
|
+
const indent = throwMatch[1] ?? '';
|
|
1896
|
+
const tempName = `__tracecodeThrown${thrownIndex++}`;
|
|
1897
|
+
const expression = throwMatch[2];
|
|
1898
|
+
nextLine = `${indent}{ var ${tempName} = ${expression}; TraceHooks.emitExceptionAtLine(${currentMethod.currentTraceLine}, String.valueOf(${tempName})); throw ${tempName}; }`;
|
|
1899
|
+
}
|
|
1900
|
+
|
|
1901
|
+
currentMethod.depth += braceDelta(nextLine);
|
|
1902
|
+
while (methodStack.length > 0 && methodStack[methodStack.length - 1].depth <= 0) {
|
|
1903
|
+
methodStack.pop();
|
|
1904
|
+
}
|
|
1905
|
+
return nextLine;
|
|
1906
|
+
}).join('\n');
|
|
1907
|
+
}
|
|
1908
|
+
|
|
1909
|
+
function augmentJavaStdoutEvents(source) {
|
|
1910
|
+
const lines = source.split('\n');
|
|
1911
|
+
const methodStack = [];
|
|
1912
|
+
let stdoutIndex = 0;
|
|
1913
|
+
const methodStartPattern =
|
|
1914
|
+
/^(\s*)(?:(?:public|private|protected|static|final|synchronized)\s+)*(?:[A-Za-z_][A-Za-z0-9_<>\[\], ?]*\s+)+([A-Za-z_][A-Za-z0-9_]*)\s*\(([^)]*)\)\s*\{\s*$/;
|
|
1915
|
+
|
|
1916
|
+
return lines.map((line) => {
|
|
1917
|
+
const methodMatch = line.match(methodStartPattern);
|
|
1918
|
+
if (methodMatch) {
|
|
1919
|
+
methodStack.push({ depth: 1, currentTraceLine: null });
|
|
1920
|
+
return line;
|
|
1921
|
+
}
|
|
1922
|
+
|
|
1923
|
+
const currentMethod = methodStack[methodStack.length - 1];
|
|
1924
|
+
let nextLine = line;
|
|
1925
|
+
if (!currentMethod) return nextLine;
|
|
1926
|
+
|
|
1927
|
+
const traceLine = parseNativeTraceLine(line);
|
|
1928
|
+
if (traceLine !== null) currentMethod.currentTraceLine = traceLine;
|
|
1929
|
+
|
|
1930
|
+
const stdoutMatch = nextLine.match(/^(\s*)System\.out\.println\((.+)\);\s*$/);
|
|
1931
|
+
if (stdoutMatch && currentMethod.currentTraceLine !== null) {
|
|
1932
|
+
const indent = stdoutMatch[1] ?? '';
|
|
1933
|
+
const tempName = `__tracecodeStdout${stdoutIndex++}`;
|
|
1934
|
+
const expression = stdoutMatch[2];
|
|
1935
|
+
nextLine = `${indent}{ var ${tempName} = ${expression}; System.out.println(${tempName}); TraceHooks.emitStdoutAtLine(${currentMethod.currentTraceLine}, String.valueOf(${tempName})); }`;
|
|
1936
|
+
}
|
|
1937
|
+
|
|
1938
|
+
currentMethod.depth += braceDelta(nextLine);
|
|
1939
|
+
while (methodStack.length > 0 && methodStack[methodStack.length - 1].depth <= 0) {
|
|
1940
|
+
methodStack.pop();
|
|
1941
|
+
}
|
|
1942
|
+
return nextLine;
|
|
1943
|
+
}).join('\n');
|
|
1944
|
+
}
|
|
1945
|
+
|
|
723
1946
|
function augmentArrayLengthReads(source) {
|
|
724
1947
|
const lines = source.split('\n');
|
|
725
1948
|
const methodStack = [];
|
|
@@ -747,9 +1970,9 @@ function augmentArrayLengthReads(source) {
|
|
|
747
1970
|
currentMethod.arrayNames.add(name);
|
|
748
1971
|
}
|
|
749
1972
|
|
|
750
|
-
const
|
|
751
|
-
if (
|
|
752
|
-
currentMethod.currentTraceLine =
|
|
1973
|
+
const traceLine = parseNativeTraceLine(line);
|
|
1974
|
+
if (traceLine !== null) {
|
|
1975
|
+
currentMethod.currentTraceLine = traceLine;
|
|
753
1976
|
currentMethod.hasTraceEmit = true;
|
|
754
1977
|
}
|
|
755
1978
|
|
|
@@ -801,7 +2024,7 @@ function augmentTraceReturnValueSnapshots(source) {
|
|
|
801
2024
|
const currentMethod = methodStack[methodStack.length - 1];
|
|
802
2025
|
if (currentMethod && currentMethod.returnType !== 'void') {
|
|
803
2026
|
const returnEmitMatch = line.match(
|
|
804
|
-
/^(\s*)TraceHooks\.
|
|
2027
|
+
/^(\s*)TraceHooks\.emitReturnAtLine\((\d+),\s*"([A-Za-z_][A-Za-z0-9_]*)"\);\s*$/
|
|
805
2028
|
);
|
|
806
2029
|
const nextLine = lines[index + 1] ?? '';
|
|
807
2030
|
const returnMatch = nextLine.match(/^(\s*)return\s+(.+);\s*$/);
|
|
@@ -811,7 +2034,7 @@ function augmentTraceReturnValueSnapshots(source) {
|
|
|
811
2034
|
const returnExpression = returnMatch[2].trim();
|
|
812
2035
|
output.push(`${indent}${currentMethod.returnType} ${tempName} = ${returnExpression};`);
|
|
813
2036
|
output.push(
|
|
814
|
-
`${indent}TraceHooks.
|
|
2037
|
+
`${indent}TraceHooks.emitSerializedReturnAtLine(${returnEmitMatch[2]}, "${currentMethod.name}", TraceHooks.serializeResult(${tempName}));`
|
|
815
2038
|
);
|
|
816
2039
|
output.push(`${returnMatch[1] ?? indent}return ${tempName};`);
|
|
817
2040
|
currentMethod.depth += braceDelta(line) + braceDelta(nextLine);
|
|
@@ -888,24 +2111,54 @@ function isTopLevelMethodStart(line) {
|
|
|
888
2111
|
return /^(?:public\s+|private\s+|protected\s+)?(?:static\s+)?(?:[\w<>\[\], ?]+\s+)+[A-Za-z_][A-Za-z0-9_]*\s*\([^;]*\)\s*\{/.test(trimmed);
|
|
889
2112
|
}
|
|
890
2113
|
|
|
891
|
-
function
|
|
892
|
-
|
|
2114
|
+
function isTopLevelTypeStart(line) {
|
|
2115
|
+
const trimmed = line.trim();
|
|
2116
|
+
return /^(?:public\s+|private\s+|protected\s+)?(?:static\s+)?(?:final\s+|abstract\s+)?(?:class|interface|enum|record)\s+[A-Za-z_][A-Za-z0-9_]*\b/.test(trimmed);
|
|
2117
|
+
}
|
|
2118
|
+
|
|
2119
|
+
function isTopLevelMemberStart(line) {
|
|
2120
|
+
return isTopLevelMethodStart(line) || isTopLevelTypeStart(line);
|
|
2121
|
+
}
|
|
2122
|
+
|
|
2123
|
+
function javaBraceCounts(line) {
|
|
2124
|
+
let open = 0;
|
|
2125
|
+
let close = 0;
|
|
893
2126
|
let quote = null;
|
|
2127
|
+
let escaped = false;
|
|
894
2128
|
for (let index = 0; index < line.length; index += 1) {
|
|
895
2129
|
const ch = line[index];
|
|
896
|
-
const
|
|
2130
|
+
const next = line[index + 1] ?? '';
|
|
2131
|
+
if (escaped) {
|
|
2132
|
+
escaped = false;
|
|
2133
|
+
continue;
|
|
2134
|
+
}
|
|
897
2135
|
if (quote) {
|
|
898
|
-
if (ch ===
|
|
2136
|
+
if (ch === '\\') {
|
|
2137
|
+
escaped = true;
|
|
2138
|
+
continue;
|
|
2139
|
+
}
|
|
2140
|
+
if (ch === quote) quote = null;
|
|
2141
|
+
continue;
|
|
2142
|
+
}
|
|
2143
|
+
if (ch === '/' && next === '/') break;
|
|
2144
|
+
if (ch === '/' && next === '*') {
|
|
2145
|
+
const end = line.indexOf('*/', index + 2);
|
|
2146
|
+
if (end === -1) break;
|
|
2147
|
+
index = end + 1;
|
|
899
2148
|
continue;
|
|
900
2149
|
}
|
|
901
2150
|
if (ch === '"' || ch === "'") {
|
|
902
2151
|
quote = ch;
|
|
903
2152
|
continue;
|
|
904
2153
|
}
|
|
905
|
-
if (ch === '{')
|
|
906
|
-
if (ch === '}')
|
|
2154
|
+
if (ch === '{') open += 1;
|
|
2155
|
+
if (ch === '}') close += 1;
|
|
907
2156
|
}
|
|
908
|
-
return delta;
|
|
2157
|
+
return { open, close, delta: open - close };
|
|
2158
|
+
}
|
|
2159
|
+
|
|
2160
|
+
function braceDelta(line) {
|
|
2161
|
+
return javaBraceCounts(line).delta;
|
|
909
2162
|
}
|
|
910
2163
|
|
|
911
2164
|
function splitScriptMembersAndStatements(lines) {
|
|
@@ -915,7 +2168,7 @@ function splitScriptMembersAndStatements(lines) {
|
|
|
915
2168
|
for (let index = 0; index < lines.length; index += 1) {
|
|
916
2169
|
const entry = lines[index];
|
|
917
2170
|
const line = typeof entry === 'string' ? entry : entry.line;
|
|
918
|
-
if (statementDepth !== 0 || !
|
|
2171
|
+
if (statementDepth !== 0 || !isTopLevelMemberStart(line)) {
|
|
919
2172
|
statementLines.push(entry);
|
|
920
2173
|
statementDepth += braceDelta(line);
|
|
921
2174
|
if (statementDepth < 0) statementDepth = 0;
|
|
@@ -1040,65 +2293,226 @@ function normalizeJavaRequest(payload) {
|
|
|
1040
2293
|
};
|
|
1041
2294
|
}
|
|
1042
2295
|
|
|
2296
|
+
if (payload.executionStyle === 'solution-method') {
|
|
2297
|
+
return {
|
|
2298
|
+
...payload,
|
|
2299
|
+
sourceText: payload.code,
|
|
2300
|
+
code: wrapSingleStatementLoopBodies(payload.code),
|
|
2301
|
+
};
|
|
2302
|
+
}
|
|
2303
|
+
|
|
2304
|
+
if (payload.executionStyle === 'ops-class') {
|
|
2305
|
+
return {
|
|
2306
|
+
...payload,
|
|
2307
|
+
sourceText: payload.code,
|
|
2308
|
+
code: wrapSingleStatementLoopBodies(payload.code),
|
|
2309
|
+
};
|
|
2310
|
+
}
|
|
2311
|
+
|
|
1043
2312
|
if (payload.executionStyle !== 'function') {
|
|
1044
2313
|
return payload;
|
|
1045
2314
|
}
|
|
1046
2315
|
|
|
1047
2316
|
return {
|
|
1048
2317
|
...payload,
|
|
2318
|
+
sourceText: payload.code,
|
|
1049
2319
|
code: normalizeFunctionSource(payload.code),
|
|
1050
2320
|
executionStyle: 'solution-method',
|
|
1051
2321
|
};
|
|
1052
2322
|
}
|
|
1053
2323
|
|
|
1054
|
-
function
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
2324
|
+
function stableJson(value) {
|
|
2325
|
+
if (Array.isArray(value)) return `[${value.map(stableJson).join(',')}]`;
|
|
2326
|
+
if (value && typeof value === 'object') {
|
|
2327
|
+
return `{${Object.keys(value).sort().map((key) => `${JSON.stringify(key)}:${stableJson(value[key])}`).join(',')}}`;
|
|
2328
|
+
}
|
|
2329
|
+
return JSON.stringify(value);
|
|
2330
|
+
}
|
|
2331
|
+
|
|
2332
|
+
function stableHash(value) {
|
|
2333
|
+
const source = typeof value === 'string' ? value : stableJson(value);
|
|
2334
|
+
let hashA = 0x811c9dc5;
|
|
2335
|
+
let hashB = 0x9e3779b9;
|
|
2336
|
+
for (let index = 0; index < source.length; index += 1) {
|
|
2337
|
+
const code = source.charCodeAt(index);
|
|
2338
|
+
hashA ^= code;
|
|
2339
|
+
hashA = Math.imul(hashA, 0x01000193) >>> 0;
|
|
2340
|
+
hashB ^= code + index;
|
|
2341
|
+
hashB = Math.imul(hashB, 0x85ebca6b) >>> 0;
|
|
2342
|
+
}
|
|
2343
|
+
return `${hashA.toString(36)}${hashB.toString(36)}`;
|
|
2344
|
+
}
|
|
2345
|
+
|
|
2346
|
+
function dynamicInputEntriesForPayload(payload, compileId) {
|
|
2347
|
+
if (payload.executionStyle === 'ops-class') return [];
|
|
2348
|
+
const parameters = extractMethodParameters(payload.code, payload.functionName);
|
|
2349
|
+
const invocationKeys = parameters.length > 0 ? parameters.map((parameter) => parameter.name) : Object.keys(payload.inputs ?? {});
|
|
2350
|
+
const entries = [];
|
|
2351
|
+
for (let index = 0; index < invocationKeys.length; index += 1) {
|
|
2352
|
+
const key = invocationKeys[index];
|
|
2353
|
+
const parameter = parameters[index];
|
|
2354
|
+
if (!parameter) continue;
|
|
2355
|
+
const value = inputValueForParameter(payload.inputs ?? {}, key, index);
|
|
2356
|
+
if (!isDynamicJavaInputType(parameter.type, value)) continue;
|
|
2357
|
+
const safeName = String(key).replace(/[^A-Za-z0-9_$-]/g, '_');
|
|
2358
|
+
entries.push({
|
|
2359
|
+
key,
|
|
2360
|
+
index,
|
|
2361
|
+
type: parameter.type,
|
|
2362
|
+
value,
|
|
2363
|
+
path: `${DYNAMIC_INPUT_PREFIX}-${compileId}-${index}-${safeName}.json`,
|
|
1074
2364
|
});
|
|
1075
|
-
|
|
1076
|
-
return `public class Exports {
|
|
1077
|
-
${helperMethods}
|
|
1078
|
-
|
|
1079
|
-
public static String run() {
|
|
1080
|
-
${lines.join('\n')}
|
|
1081
|
-
return TraceHooks.serializeResult(out);
|
|
1082
2365
|
}
|
|
2366
|
+
return entries;
|
|
1083
2367
|
}
|
|
1084
|
-
|
|
1085
|
-
|
|
2368
|
+
|
|
2369
|
+
function buildJavaCompileSeed(payload, compileMode = 'trace') {
|
|
2370
|
+
if (payload.executionStyle === 'ops-class') {
|
|
2371
|
+
return {
|
|
2372
|
+
compileMode,
|
|
2373
|
+
code: payload.code,
|
|
2374
|
+
functionName: payload.functionName,
|
|
2375
|
+
executionStyle: payload.executionStyle,
|
|
2376
|
+
inputs: payload.inputs ?? {},
|
|
2377
|
+
};
|
|
2378
|
+
}
|
|
2379
|
+
|
|
2380
|
+
const parameters = extractMethodParameters(payload.code, payload.functionName);
|
|
2381
|
+
const invocationKeys = parameters.length > 0 ? parameters.map((parameter) => parameter.name) : Object.keys(payload.inputs ?? {});
|
|
2382
|
+
const inputs = {};
|
|
2383
|
+
for (let index = 0; index < invocationKeys.length; index += 1) {
|
|
2384
|
+
const key = invocationKeys[index];
|
|
2385
|
+
const parameter = parameters[index];
|
|
2386
|
+
const value = inputValueForParameter(payload.inputs ?? {}, key, index);
|
|
2387
|
+
inputs[key] = parameter && isDynamicJavaInputType(parameter.type, value)
|
|
2388
|
+
? { mode: 'dynamic-json-file', type: normalizedJavaInputType(parameter.type) }
|
|
2389
|
+
: { mode: 'literal', value };
|
|
2390
|
+
}
|
|
2391
|
+
|
|
2392
|
+
return {
|
|
2393
|
+
compileMode,
|
|
2394
|
+
code: payload.code,
|
|
2395
|
+
functionName: payload.functionName,
|
|
2396
|
+
executionStyle: payload.executionStyle,
|
|
2397
|
+
scriptMode: payload.scriptMode === true,
|
|
2398
|
+
inputs,
|
|
2399
|
+
};
|
|
2400
|
+
}
|
|
2401
|
+
|
|
2402
|
+
function buildJavaCompileId(payload, compileMode = 'trace') {
|
|
2403
|
+
return stableHash(buildJavaCompileSeed(payload, compileMode));
|
|
2404
|
+
}
|
|
2405
|
+
|
|
2406
|
+
function buildJavaBatchCompileId(payload, inputBatch) {
|
|
2407
|
+
return stableHash({
|
|
2408
|
+
compileMode: 'execute-batch',
|
|
2409
|
+
cases: inputBatch.map((inputs) => buildJavaCompileSeed({ ...payload, inputs }, 'execute-batch-case')),
|
|
2410
|
+
});
|
|
2411
|
+
}
|
|
2412
|
+
|
|
2413
|
+
async function writeDynamicInputFiles(dynamicInputs) {
|
|
2414
|
+
for (const input of dynamicInputs) {
|
|
2415
|
+
await self.cheerpOSAddStringFile(input.path, JSON.stringify(input.value));
|
|
2416
|
+
}
|
|
2417
|
+
}
|
|
2418
|
+
|
|
2419
|
+
function dynamicInputByKey(dynamicInputs) {
|
|
2420
|
+
const out = new Map();
|
|
2421
|
+
for (const input of dynamicInputs) out.set(input.key, input);
|
|
2422
|
+
return out;
|
|
2423
|
+
}
|
|
2424
|
+
|
|
2425
|
+
function buildExportsSource(source, functionName, executionStyle, input, options = {}) {
|
|
2426
|
+
const features = {
|
|
2427
|
+
...detectFeatures(source, input, options),
|
|
2428
|
+
skipInputMaterializers: options.scriptMode === true,
|
|
2429
|
+
};
|
|
2430
|
+
const helperMethods = buildHelperMethods(features);
|
|
2431
|
+
const nodePreludeSource = buildNodePreludeSource(source, options);
|
|
2432
|
+
const dynamicInputsByKey = dynamicInputByKey(options.dynamicInputs ?? []);
|
|
2433
|
+
|
|
2434
|
+
if (executionStyle === 'ops-class') {
|
|
2435
|
+
const operations = Array.isArray(input.operations) ? input.operations : [];
|
|
2436
|
+
const argumentsList = Array.isArray(input.arguments) ? input.arguments : [];
|
|
2437
|
+
const lines = [' java.util.List<Object> out = new java.util.ArrayList<>();'];
|
|
2438
|
+
const firstOperation = operations.length > 0 ? String(operations[0]) : null;
|
|
2439
|
+
const hasConstructorOperation =
|
|
2440
|
+
firstOperation === functionName ||
|
|
2441
|
+
firstOperation === '__init__' ||
|
|
2442
|
+
firstOperation === 'init' ||
|
|
2443
|
+
(firstOperation !== null && extractMethodReturnType(source, firstOperation) === null);
|
|
2444
|
+
const constructorParameters = extractMethodParametersForArguments(source, functionName, argumentsList[0]);
|
|
2445
|
+
const constructorArgs = hasConstructorOperation
|
|
2446
|
+
? inputArgumentsForParameters(argumentsList[0], constructorParameters)
|
|
2447
|
+
: [];
|
|
2448
|
+
const constructorInvocationArgs = constructorArgs
|
|
2449
|
+
.map((arg, argIndex) => buildJavaExpression(arg, constructorParameters[argIndex]?.type))
|
|
2450
|
+
.join(', ');
|
|
2451
|
+
lines.push(` ${functionName} instance = new ${functionName}(${constructorInvocationArgs});`);
|
|
2452
|
+
if (hasConstructorOperation) {
|
|
2453
|
+
lines.push(' out.add(null);');
|
|
2454
|
+
}
|
|
2455
|
+
|
|
2456
|
+
operations.forEach((operation, index) => {
|
|
2457
|
+
if (hasConstructorOperation && index === 0) {
|
|
2458
|
+
return;
|
|
2459
|
+
}
|
|
2460
|
+
const operationName = String(operation);
|
|
2461
|
+
const parameters = extractMethodParametersForArguments(source, operationName, argumentsList[index]);
|
|
2462
|
+
const args = inputArgumentsForParameters(argumentsList[index], parameters);
|
|
2463
|
+
const invocationArgs = args.map((arg, argIndex) => buildJavaExpression(arg, parameters[argIndex]?.type)).join(', ');
|
|
2464
|
+
const returnType = extractMethodReturnType(source, operationName);
|
|
2465
|
+
if (returnType === 'void') {
|
|
2466
|
+
lines.push(` instance.${operationName}(${invocationArgs});`);
|
|
2467
|
+
lines.push(' out.add(null);');
|
|
2468
|
+
} else {
|
|
2469
|
+
lines.push(` out.add(instance.${operationName}(${invocationArgs}));`);
|
|
2470
|
+
}
|
|
2471
|
+
});
|
|
2472
|
+
|
|
2473
|
+
return `${nodePreludeSource}public class Exports {
|
|
2474
|
+
${helperMethods}
|
|
2475
|
+
|
|
2476
|
+
public static String run() {
|
|
2477
|
+
${lines.join('\n')}
|
|
2478
|
+
return TraceHooks.serializeOutputResult(out);
|
|
2479
|
+
}
|
|
2480
|
+
}
|
|
2481
|
+
`;
|
|
2482
|
+
}
|
|
1086
2483
|
|
|
1087
2484
|
const parameters = extractMethodParameters(source, functionName);
|
|
1088
|
-
const
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
2485
|
+
const returnType = extractMethodReturnType(source, functionName);
|
|
2486
|
+
const invocationKeys = parameters.length > 0 ? parameters.map((parameter) => parameter.name) : Object.keys(input);
|
|
2487
|
+
const usedLocalNames = new Set(['solution', ...invocationKeys]);
|
|
2488
|
+
const resultLocalName = uniqueJavaIdentifier('__tracecode_result', usedLocalNames);
|
|
2489
|
+
const materializedArgs = [];
|
|
2490
|
+
for (let index = 0; index < invocationKeys.length; index += 1) {
|
|
2491
|
+
const key = invocationKeys[index];
|
|
2492
|
+
const parameter = parameters[index];
|
|
2493
|
+
const type = parameter ? parameter.type : 'Object';
|
|
2494
|
+
const value = inputValueForParameter(input, key, index);
|
|
2495
|
+
const dynamicInput = dynamicInputsByKey.get(key);
|
|
2496
|
+
const expression = dynamicInput
|
|
2497
|
+
? dynamicJavaInputExpression(type, dynamicInput.path)
|
|
2498
|
+
: buildJavaExpression(value, type);
|
|
2499
|
+
if (dynamicInput && !expression) {
|
|
2500
|
+
throw new Error(`Unsupported dynamic Java input type: ${type}`);
|
|
2501
|
+
}
|
|
2502
|
+
materializedArgs.push(` ${type} ${key} = ${expression};`);
|
|
2503
|
+
}
|
|
2504
|
+
const invocationArgs = invocationKeys.join(', ');
|
|
2505
|
+
const invocationLine = returnType === 'void'
|
|
2506
|
+
? ` solution.${functionName}(${invocationArgs});\n return TraceHooks.serializeOutputResult(null);`
|
|
2507
|
+
: ` ${returnType || 'Object'} ${resultLocalName} = solution.${functionName}(${invocationArgs});\n return TraceHooks.serializeOutputResult(${resultLocalName});`;
|
|
1094
2508
|
|
|
1095
|
-
return
|
|
2509
|
+
return `${nodePreludeSource}public class Exports {
|
|
1096
2510
|
${helperMethods}
|
|
1097
2511
|
|
|
1098
2512
|
public static String run() {
|
|
1099
2513
|
Solution solution = new Solution();
|
|
1100
|
-
|
|
1101
|
-
|
|
2514
|
+
${materializedArgs.join('\n')}
|
|
2515
|
+
${invocationLine}
|
|
1102
2516
|
}
|
|
1103
2517
|
}
|
|
1104
2518
|
`;
|
|
@@ -1112,6 +2526,20 @@ function buildExportsClassName(messageId) {
|
|
|
1112
2526
|
return `Exports${String(messageId).replace(/[^A-Za-z0-9]/g, '')}`;
|
|
1113
2527
|
}
|
|
1114
2528
|
|
|
2529
|
+
function normalizeJavaSerializedOutput(value) {
|
|
2530
|
+
if (Array.isArray(value)) {
|
|
2531
|
+
return value.map((item) => normalizeJavaSerializedOutput(item));
|
|
2532
|
+
}
|
|
2533
|
+
if (!value || typeof value !== 'object') return value;
|
|
2534
|
+
const output = {};
|
|
2535
|
+
for (const [key, child] of Object.entries(value)) {
|
|
2536
|
+
if (key === '__class__') continue;
|
|
2537
|
+
if (value.__type__ === 'NestedInteger' && key === 'value' && child == null) continue;
|
|
2538
|
+
output[key] = normalizeJavaSerializedOutput(child);
|
|
2539
|
+
}
|
|
2540
|
+
return output;
|
|
2541
|
+
}
|
|
2542
|
+
|
|
1115
2543
|
async function ensureReady() {
|
|
1116
2544
|
if (!workerReadyPromise) {
|
|
1117
2545
|
workerReadyPromise = (async () => {
|
|
@@ -1131,7 +2559,6 @@ async function ensureReady() {
|
|
|
1131
2559
|
})();
|
|
1132
2560
|
}
|
|
1133
2561
|
await workerReadyPromise;
|
|
1134
|
-
resetIdleTimer();
|
|
1135
2562
|
}
|
|
1136
2563
|
|
|
1137
2564
|
async function getHelperLibrary() {
|
|
@@ -1145,7 +2572,7 @@ async function getCompileLibraryClass() {
|
|
|
1145
2572
|
if (!compileLibraryClassPromise) {
|
|
1146
2573
|
compileLibraryClassPromise = (async () => {
|
|
1147
2574
|
const library = await getHelperLibrary();
|
|
1148
|
-
return library.
|
|
2575
|
+
return library.tracecode.browser.BrowserCompileAndTraceLibrary;
|
|
1149
2576
|
})();
|
|
1150
2577
|
}
|
|
1151
2578
|
return compileLibraryClassPromise;
|
|
@@ -1161,45 +2588,87 @@ async function getRewriteLibraryClass() {
|
|
|
1161
2588
|
return rewriteLibraryClassPromise;
|
|
1162
2589
|
}
|
|
1163
2590
|
|
|
1164
|
-
async function
|
|
1165
|
-
if (!
|
|
1166
|
-
|
|
2591
|
+
async function warmRunHost() {
|
|
2592
|
+
if (!runWarmupPromise) {
|
|
2593
|
+
runWarmupPromise = (async () => {
|
|
2594
|
+
const totalStart = performance.now();
|
|
1167
2595
|
const libraryClass = await getCompileLibraryClass();
|
|
1168
|
-
const
|
|
1169
|
-
const
|
|
1170
|
-
const
|
|
2596
|
+
const runSourcePath = '/str/ExportsTracecodeRunWarmup.java';
|
|
2597
|
+
const runClassesDir = '/files/java-worker/__warm_run__/classes';
|
|
2598
|
+
const runWarmupSource = `
|
|
1171
2599
|
package harness.user.warmup;
|
|
1172
2600
|
|
|
1173
|
-
|
|
2601
|
+
import tracecode.user.TraceHooks;
|
|
2602
|
+
|
|
2603
|
+
class Solution {
|
|
2604
|
+
int add(int a, int b) {
|
|
2605
|
+
return a + b;
|
|
2606
|
+
}
|
|
2607
|
+
}
|
|
2608
|
+
|
|
2609
|
+
public class ExportsTracecodeRunWarmup {
|
|
1174
2610
|
public static String run() {
|
|
1175
|
-
|
|
2611
|
+
Solution solution = new Solution();
|
|
2612
|
+
int a = 1;
|
|
2613
|
+
int b = 2;
|
|
2614
|
+
int result = solution.add(a, b);
|
|
2615
|
+
return TraceHooks.serializeOutputResult(result);
|
|
1176
2616
|
}
|
|
1177
2617
|
}
|
|
1178
2618
|
`;
|
|
1179
|
-
await self.cheerpOSAddStringFile(
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
2619
|
+
await self.cheerpOSAddStringFile(runSourcePath, runWarmupSource);
|
|
2620
|
+
const hostCallStart = performance.now();
|
|
2621
|
+
const reportText = await libraryClass.compileAndRun(
|
|
2622
|
+
runSourcePath,
|
|
2623
|
+
runClassesDir,
|
|
2624
|
+
'harness.user.warmup.ExportsTracecodeRunWarmup',
|
|
1184
2625
|
HELPER_JAR_PATH,
|
|
1185
|
-
|
|
2626
|
+
DEFAULT_EXECUTE_COMPILER_DEBUG_PROFILE
|
|
1186
2627
|
);
|
|
2628
|
+
const hostCallEnd = performance.now();
|
|
2629
|
+
const report = JSON.parse(reportText);
|
|
2630
|
+
const totalEnd = performance.now();
|
|
2631
|
+
if (report.success !== true) {
|
|
2632
|
+
throw new Error(report.runtimeError || report.compilerStderr || report.compilerStdout || 'Java warmup failed');
|
|
2633
|
+
}
|
|
2634
|
+
return {
|
|
2635
|
+
success: true,
|
|
2636
|
+
loadTimeMs: Math.round(totalEnd - totalStart),
|
|
2637
|
+
timings: {
|
|
2638
|
+
totalMs: totalEnd - totalStart,
|
|
2639
|
+
hostCallMs: hostCallEnd - hostCallStart,
|
|
2640
|
+
compileMs: report.compileTimeMs ?? 0,
|
|
2641
|
+
classLoadMs: report.classLoadTimeMs ?? 0,
|
|
2642
|
+
runMs: report.runTimeMs ?? 0,
|
|
2643
|
+
compileCacheHit: report.compileCacheHit ?? false,
|
|
2644
|
+
},
|
|
2645
|
+
};
|
|
1187
2646
|
})();
|
|
1188
2647
|
}
|
|
1189
|
-
|
|
2648
|
+
try {
|
|
2649
|
+
return await runWarmupPromise;
|
|
2650
|
+
} catch (error) {
|
|
2651
|
+
runWarmupPromise = null;
|
|
2652
|
+
throw error;
|
|
2653
|
+
}
|
|
1190
2654
|
}
|
|
1191
2655
|
|
|
1192
|
-
async function rewriteSource(payload,
|
|
2656
|
+
async function rewriteSource(payload, compileId, dynamicInputs) {
|
|
1193
2657
|
const rewriteLibraryClass = await getRewriteLibraryClass();
|
|
1194
|
-
const exportsClassName = buildExportsClassName(
|
|
1195
|
-
const packageName = buildPackageName(
|
|
2658
|
+
const exportsClassName = buildExportsClassName(compileId);
|
|
2659
|
+
const packageName = buildPackageName(compileId);
|
|
1196
2660
|
const exportsSource = buildExportsSource(
|
|
1197
2661
|
payload.code,
|
|
1198
2662
|
payload.functionName,
|
|
1199
2663
|
payload.executionStyle,
|
|
1200
|
-
payload.inputs ?? {}
|
|
2664
|
+
payload.inputs ?? {},
|
|
2665
|
+
{
|
|
2666
|
+
dynamicInputs,
|
|
2667
|
+
hasDynamicInputs: dynamicInputs.length > 0,
|
|
2668
|
+
scriptMode: payload.scriptMode === true,
|
|
2669
|
+
}
|
|
1201
2670
|
);
|
|
1202
|
-
|
|
2671
|
+
const rewrittenSource = await rewriteLibraryClass.rewriteSource(
|
|
1203
2672
|
payload.code,
|
|
1204
2673
|
payload.executionStyle,
|
|
1205
2674
|
payload.functionName,
|
|
@@ -1207,13 +2676,106 @@ async function rewriteSource(payload, requestId) {
|
|
|
1207
2676
|
exportsClassName,
|
|
1208
2677
|
packageName
|
|
1209
2678
|
);
|
|
2679
|
+
return addJavaDefaultImportsToPackagedSource(rewrittenSource);
|
|
1210
2680
|
}
|
|
1211
2681
|
|
|
1212
2682
|
function normalizePublicClassDeclarations(source) {
|
|
1213
|
-
return String(source).replace(
|
|
2683
|
+
return String(source).replace(/^([ \t]*)public\s+class\s+/gm, '$1class ');
|
|
2684
|
+
}
|
|
2685
|
+
|
|
2686
|
+
function buildPlainRunnableSource(payload, compileId, dynamicInputs) {
|
|
2687
|
+
const exportsClassName = buildExportsClassName(compileId);
|
|
2688
|
+
const packageName = buildPackageName(compileId);
|
|
2689
|
+
const exportsSource = buildExportsSource(
|
|
2690
|
+
payload.code,
|
|
2691
|
+
payload.functionName,
|
|
2692
|
+
payload.executionStyle,
|
|
2693
|
+
payload.inputs ?? {},
|
|
2694
|
+
{
|
|
2695
|
+
dynamicInputs,
|
|
2696
|
+
hasDynamicInputs: dynamicInputs.length > 0,
|
|
2697
|
+
scriptMode: payload.scriptMode === true,
|
|
2698
|
+
}
|
|
2699
|
+
).replaceAll(/\bpublic class Exports\b/g, `public class ${exportsClassName}`);
|
|
2700
|
+
|
|
2701
|
+
return [
|
|
2702
|
+
`package ${packageName};`,
|
|
2703
|
+
'',
|
|
2704
|
+
'import tracecode.user.TraceHooks;',
|
|
2705
|
+
javaDefaultImportsBlock(),
|
|
2706
|
+
'',
|
|
2707
|
+
normalizePublicClassDeclarations(payload.code).trim(),
|
|
2708
|
+
'',
|
|
2709
|
+
exportsSource.trim(),
|
|
2710
|
+
'',
|
|
2711
|
+
].join('\n');
|
|
2712
|
+
}
|
|
2713
|
+
|
|
2714
|
+
function buildBatchRunnableSource(payload, compileId, inputBatch, dynamicInputBatch) {
|
|
2715
|
+
const exportsClassName = buildExportsClassName(compileId);
|
|
2716
|
+
const packageName = buildPackageName(compileId);
|
|
2717
|
+
const entryClasses = [];
|
|
2718
|
+
const sourceParts = [
|
|
2719
|
+
`package ${packageName};`,
|
|
2720
|
+
'',
|
|
2721
|
+
'import tracecode.user.TraceHooks;',
|
|
2722
|
+
javaDefaultImportsBlock(),
|
|
2723
|
+
'',
|
|
2724
|
+
normalizePublicClassDeclarations(payload.code).trim(),
|
|
2725
|
+
'',
|
|
2726
|
+
];
|
|
2727
|
+
|
|
2728
|
+
for (let index = 0; index < inputBatch.length; index += 1) {
|
|
2729
|
+
const className = index === 0 ? exportsClassName : `${exportsClassName}Case${index}`;
|
|
2730
|
+
const dynamicInputs = dynamicInputBatch[index] ?? [];
|
|
2731
|
+
const exportsSource = buildExportsSource(
|
|
2732
|
+
payload.code,
|
|
2733
|
+
payload.functionName,
|
|
2734
|
+
payload.executionStyle,
|
|
2735
|
+
inputBatch[index] ?? {},
|
|
2736
|
+
{
|
|
2737
|
+
dynamicInputs,
|
|
2738
|
+
hasDynamicInputs: dynamicInputs.length > 0,
|
|
2739
|
+
scriptMode: payload.scriptMode === true,
|
|
2740
|
+
}
|
|
2741
|
+
).replaceAll(
|
|
2742
|
+
/\bpublic class Exports\b/g,
|
|
2743
|
+
`${index === 0 ? 'public class' : 'class'} ${className}`
|
|
2744
|
+
);
|
|
2745
|
+
entryClasses.push(`${packageName}.${className}`);
|
|
2746
|
+
sourceParts.push(exportsSource.trim(), '');
|
|
2747
|
+
}
|
|
2748
|
+
|
|
2749
|
+
return {
|
|
2750
|
+
source: sourceParts.join('\n'),
|
|
2751
|
+
entryClasses,
|
|
2752
|
+
};
|
|
1214
2753
|
}
|
|
1215
2754
|
|
|
1216
|
-
|
|
2755
|
+
function buildCompileProbeSource(payload, requestId, probeClassName, probePackageName) {
|
|
2756
|
+
const exportsSource = buildExportsSource(
|
|
2757
|
+
payload.code,
|
|
2758
|
+
payload.functionName,
|
|
2759
|
+
payload.executionStyle,
|
|
2760
|
+
payload.inputs ?? {},
|
|
2761
|
+
{
|
|
2762
|
+
scriptMode: payload.scriptMode === true,
|
|
2763
|
+
}
|
|
2764
|
+
).replaceAll(/\bpublic class Exports\b/g, `public class ${probeClassName}`);
|
|
2765
|
+
return [
|
|
2766
|
+
`package ${probePackageName};`,
|
|
2767
|
+
'',
|
|
2768
|
+
'import tracecode.user.TraceHooks;',
|
|
2769
|
+
javaDefaultImportsBlock(),
|
|
2770
|
+
'',
|
|
2771
|
+
normalizePublicClassDeclarations(payload.code).trim(),
|
|
2772
|
+
'',
|
|
2773
|
+
exportsSource.trim(),
|
|
2774
|
+
'',
|
|
2775
|
+
].join('\n');
|
|
2776
|
+
}
|
|
2777
|
+
|
|
2778
|
+
async function collectCompileProbeDiagnostics(payload, requestId, options) {
|
|
1217
2779
|
const probeClassName = buildExportsClassName(`${requestId}RewriteProbe`);
|
|
1218
2780
|
const probePackageName = buildPackageName(`${requestId}RewriteProbe`);
|
|
1219
2781
|
const sourcePath = `/str/${probeClassName}.java`;
|
|
@@ -1232,7 +2794,10 @@ async function collectCompileProbeDiagnostics(source, requestId, options) {
|
|
|
1232
2794
|
}
|
|
1233
2795
|
|
|
1234
2796
|
try {
|
|
1235
|
-
await self.cheerpOSAddStringFile(
|
|
2797
|
+
await self.cheerpOSAddStringFile(
|
|
2798
|
+
sourcePath,
|
|
2799
|
+
buildCompileProbeSource(payload, requestId, probeClassName, probePackageName)
|
|
2800
|
+
);
|
|
1236
2801
|
} catch (error) {
|
|
1237
2802
|
return {
|
|
1238
2803
|
consoleOutput: [],
|
|
@@ -1294,79 +2859,194 @@ async function collectCompileProbeDiagnostics(source, requestId, options) {
|
|
|
1294
2859
|
function normalizeScriptTraceEvents(events, scriptMode, userCodeLineCount, sourceLineMap) {
|
|
1295
2860
|
if (!scriptMode || !Array.isArray(events)) return events;
|
|
1296
2861
|
return events.map((event) => {
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
2862
|
+
if (String(event).startsWith('trace:')) {
|
|
2863
|
+
try {
|
|
2864
|
+
const parsed = JSON.parse(String(event).slice('trace:'.length));
|
|
2865
|
+
if (parsed.function === SCRIPT_METHOD_NAME) parsed.function = '<module>';
|
|
2866
|
+
if (parsed.kind === 'call' && parsed.function === SCRIPT_METHOD_NAME) parsed.function = '<module>';
|
|
2867
|
+
if (parsed.kind === 'return' && parsed.function === SCRIPT_METHOD_NAME) parsed.function = '<module>';
|
|
2868
|
+
if (
|
|
2869
|
+
typeof parsed.line === 'number' &&
|
|
2870
|
+
sourceLineMap &&
|
|
2871
|
+
Object.prototype.hasOwnProperty.call(sourceLineMap, String(parsed.line))
|
|
2872
|
+
) {
|
|
2873
|
+
const mappedLine = Number(sourceLineMap[String(parsed.line)]);
|
|
2874
|
+
if (Number.isFinite(mappedLine) && mappedLine > 0) parsed.line = mappedLine;
|
|
2875
|
+
}
|
|
2876
|
+
if (
|
|
2877
|
+
parsed.kind === 'return' &&
|
|
2878
|
+
parsed.function === '<module>' &&
|
|
2879
|
+
Number.isFinite(userCodeLineCount) &&
|
|
2880
|
+
userCodeLineCount > 0 &&
|
|
2881
|
+
parsed.line > userCodeLineCount
|
|
2882
|
+
) {
|
|
2883
|
+
parsed.line = userCodeLineCount;
|
|
2884
|
+
}
|
|
2885
|
+
return `trace:${JSON.stringify(parsed)}`;
|
|
2886
|
+
} catch {
|
|
2887
|
+
return event;
|
|
1306
2888
|
}
|
|
1307
2889
|
}
|
|
1308
|
-
|
|
1309
|
-
const match = normalizedEvent.match(/^line=(\d+)\s+return\s+<module>$/);
|
|
1310
|
-
if (!match || !Number.isFinite(userCodeLineCount) || userCodeLineCount <= 0) {
|
|
1311
|
-
return normalizedEvent;
|
|
1312
|
-
}
|
|
1313
|
-
const line = Number.parseInt(match[1], 10);
|
|
1314
|
-
if (line <= userCodeLineCount) return normalizedEvent;
|
|
1315
|
-
return `line=${userCodeLineCount} return <module>`;
|
|
2890
|
+
return event;
|
|
1316
2891
|
});
|
|
1317
2892
|
}
|
|
1318
2893
|
|
|
1319
2894
|
function parseTraceLineNumber(event) {
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
2895
|
+
if (String(event).startsWith('trace:')) {
|
|
2896
|
+
try {
|
|
2897
|
+
const parsed = JSON.parse(String(event).slice('trace:'.length));
|
|
2898
|
+
const line = Number(parsed.line);
|
|
2899
|
+
return Number.isFinite(line) && line > 0 ? line : null;
|
|
2900
|
+
} catch {
|
|
2901
|
+
return null;
|
|
2902
|
+
}
|
|
2903
|
+
}
|
|
2904
|
+
return null;
|
|
1324
2905
|
}
|
|
1325
2906
|
|
|
1326
2907
|
function isBareTraceLineEvent(event) {
|
|
1327
|
-
|
|
2908
|
+
if (String(event).startsWith('trace:')) {
|
|
2909
|
+
try {
|
|
2910
|
+
const parsed = JSON.parse(String(event).slice('trace:'.length));
|
|
2911
|
+
return parsed.kind === 'line';
|
|
2912
|
+
} catch {
|
|
2913
|
+
return false;
|
|
2914
|
+
}
|
|
2915
|
+
}
|
|
2916
|
+
return false;
|
|
2917
|
+
}
|
|
2918
|
+
|
|
2919
|
+
function buildBareTraceLineEvent(line, templateEvent) {
|
|
2920
|
+
if (String(templateEvent).startsWith('trace:')) {
|
|
2921
|
+
return `trace:${JSON.stringify({ kind: 'line', line })}`;
|
|
2922
|
+
}
|
|
2923
|
+
return `trace:${JSON.stringify({ kind: 'line', line })}`;
|
|
1328
2924
|
}
|
|
1329
2925
|
|
|
1330
|
-
function
|
|
2926
|
+
function cloneNativeSnapshotEventAtLine(event, line) {
|
|
2927
|
+
if (!String(event).startsWith('trace:')) return null;
|
|
2928
|
+
try {
|
|
2929
|
+
const parsed = JSON.parse(String(event).slice('trace:'.length));
|
|
2930
|
+
if (parsed.kind !== 'snapshot') return null;
|
|
2931
|
+
return `trace:${JSON.stringify({ ...parsed, line })}`;
|
|
2932
|
+
} catch {
|
|
2933
|
+
return null;
|
|
2934
|
+
}
|
|
2935
|
+
}
|
|
2936
|
+
|
|
2937
|
+
function parseNativeSnapshotVariable(event) {
|
|
2938
|
+
if (!String(event).startsWith('trace:')) return null;
|
|
2939
|
+
try {
|
|
2940
|
+
const parsed = JSON.parse(String(event).slice('trace:'.length));
|
|
2941
|
+
if (parsed.kind !== 'snapshot') return null;
|
|
2942
|
+
const variable = parsed.target && typeof parsed.target.variable === 'string'
|
|
2943
|
+
? parsed.target.variable
|
|
2944
|
+
: null;
|
|
2945
|
+
return variable;
|
|
2946
|
+
} catch {
|
|
2947
|
+
return null;
|
|
2948
|
+
}
|
|
2949
|
+
}
|
|
2950
|
+
|
|
2951
|
+
function collectJavaLineDeclarationsForHeaderExpansion(line) {
|
|
2952
|
+
const names = [];
|
|
2953
|
+
const declarationPattern =
|
|
2954
|
+
/\b(?:final\s+)?((?:boolean|byte|char|short|int|long|float|double|String|Object|[A-Za-z_][A-Za-z0-9_<>.?]*(?:\s*<[^,;=(){}:]+>)?)\s*(?:\[\s*\])*)\s+([A-Za-z_][A-Za-z0-9_]*)\s*(?==)/g;
|
|
2955
|
+
const skippedNames = new Set(['class', 'interface', 'enum', 'record', 'return', 'new']);
|
|
2956
|
+
for (const match of line.matchAll(declarationPattern)) {
|
|
2957
|
+
const typeSource = match[1] ?? '';
|
|
2958
|
+
const name = match[2];
|
|
2959
|
+
if (!name || skippedNames.has(name) || name.startsWith('__tracecode')) continue;
|
|
2960
|
+
if (typeSource.includes('[')) continue;
|
|
2961
|
+
names.push(name);
|
|
2962
|
+
}
|
|
2963
|
+
return names;
|
|
2964
|
+
}
|
|
2965
|
+
|
|
2966
|
+
function collectJavaControlHeaderDeclarations(line) {
|
|
2967
|
+
const forMatch = /\bfor\s*\(\s*(?:final\s+)?(?:[A-Za-z_][A-Za-z0-9_<>.?]*(?:\s*<[^;=(){}:]+>)?|\w+(?:\s*\[\s*\])*)\s+([A-Za-z_][A-Za-z0-9_]*)\s*(?:=|:)/.exec(line);
|
|
2968
|
+
return forMatch?.[1] ? [forMatch[1]] : [];
|
|
2969
|
+
}
|
|
2970
|
+
|
|
2971
|
+
function buildControlHeaderInfo(sourceText) {
|
|
1331
2972
|
if (typeof sourceText !== 'string' || sourceText.length === 0) return null;
|
|
1332
2973
|
const lines = sourceText.split(/\r?\n/);
|
|
1333
|
-
const
|
|
2974
|
+
const loopBodyLineToHeader = new Map();
|
|
2975
|
+
const headerLineToExcludedVariables = new Map();
|
|
1334
2976
|
|
|
1335
2977
|
for (let index = 0; index < lines.length; index += 1) {
|
|
1336
2978
|
const line = lines[index];
|
|
1337
|
-
|
|
2979
|
+
const isLoopHeader = /\b(?:for|while)\s*\(/.test(line);
|
|
2980
|
+
const isControlHeader = /\b(?:for|while|if|else\s+if)\s*\(/.test(line);
|
|
2981
|
+
if (!isControlHeader || !line.includes('{')) continue;
|
|
1338
2982
|
|
|
1339
2983
|
for (let bodyIndex = index + 1; bodyIndex < lines.length; bodyIndex += 1) {
|
|
1340
2984
|
const trimmed = lines[bodyIndex].trim();
|
|
1341
2985
|
if (trimmed.length === 0) continue;
|
|
1342
2986
|
if (trimmed.startsWith('}')) break;
|
|
1343
|
-
|
|
2987
|
+
const headerInfo = {
|
|
2988
|
+
line: index + 1,
|
|
2989
|
+
excludedVariables: new Set(collectJavaLineDeclarationsForHeaderExpansion(lines[bodyIndex])),
|
|
2990
|
+
headerVariables: new Set(collectJavaControlHeaderDeclarations(line)),
|
|
2991
|
+
};
|
|
2992
|
+
if (isLoopHeader) loopBodyLineToHeader.set(bodyIndex + 1, headerInfo);
|
|
2993
|
+
headerLineToExcludedVariables.set(index + 1, headerInfo.excludedVariables);
|
|
1344
2994
|
break;
|
|
1345
2995
|
}
|
|
1346
2996
|
}
|
|
1347
2997
|
|
|
1348
|
-
|
|
2998
|
+
if (loopBodyLineToHeader.size === 0 && headerLineToExcludedVariables.size === 0) return null;
|
|
2999
|
+
return { loopBodyLineToHeader, headerLineToExcludedVariables };
|
|
1349
3000
|
}
|
|
1350
3001
|
|
|
1351
3002
|
function expandLoopHeaderTraceEvents(events, sourceText) {
|
|
1352
3003
|
if (!Array.isArray(events) || events.length === 0) return events;
|
|
1353
|
-
const
|
|
1354
|
-
if (!
|
|
3004
|
+
const controlHeaderInfo = buildControlHeaderInfo(sourceText);
|
|
3005
|
+
if (!controlHeaderInfo) return events;
|
|
3006
|
+
const { loopBodyLineToHeader, headerLineToExcludedVariables } = controlHeaderInfo;
|
|
1355
3007
|
|
|
1356
3008
|
const expanded = [];
|
|
1357
|
-
|
|
3009
|
+
const latestSnapshotByVariable = new Map();
|
|
3010
|
+
for (let index = 0; index < events.length; index += 1) {
|
|
3011
|
+
const event = events[index];
|
|
1358
3012
|
const line = parseTraceLineNumber(event);
|
|
1359
|
-
const
|
|
3013
|
+
const snapshotVariable = parseNativeSnapshotVariable(event);
|
|
3014
|
+
if (
|
|
3015
|
+
line !== null &&
|
|
3016
|
+
snapshotVariable &&
|
|
3017
|
+
headerLineToExcludedVariables.get(line)?.has(snapshotVariable)
|
|
3018
|
+
) {
|
|
3019
|
+
continue;
|
|
3020
|
+
}
|
|
3021
|
+
const headerInfo = line === null ? undefined : loopBodyLineToHeader.get(line);
|
|
3022
|
+
const headerLine = headerInfo?.line;
|
|
1360
3023
|
const previousLine = expanded.length > 0 ? parseTraceLineNumber(expanded[expanded.length - 1]) : null;
|
|
1361
3024
|
if (headerLine !== undefined && isBareTraceLineEvent(event) && previousLine !== headerLine) {
|
|
1362
|
-
expanded.push(
|
|
3025
|
+
expanded.push(buildBareTraceLineEvent(headerLine, event));
|
|
3026
|
+
for (const [variable, snapshotEvent] of latestSnapshotByVariable) {
|
|
3027
|
+
if (headerInfo.excludedVariables.has(variable)) continue;
|
|
3028
|
+
const clonedSnapshot = cloneNativeSnapshotEventAtLine(snapshotEvent, headerLine);
|
|
3029
|
+
if (clonedSnapshot) expanded.push(clonedSnapshot);
|
|
3030
|
+
}
|
|
3031
|
+
}
|
|
3032
|
+
if (headerLine !== undefined && isBareTraceLineEvent(event)) {
|
|
3033
|
+
for (let lookahead = index + 1; lookahead < events.length; lookahead += 1) {
|
|
3034
|
+
if (parseTraceLineNumber(events[lookahead]) !== line) break;
|
|
3035
|
+
const variable = parseNativeSnapshotVariable(events[lookahead]);
|
|
3036
|
+
if (!variable || !headerInfo.headerVariables.has(variable)) continue;
|
|
3037
|
+
const clonedSnapshot = cloneNativeSnapshotEventAtLine(events[lookahead], headerLine);
|
|
3038
|
+
if (clonedSnapshot) expanded.push(clonedSnapshot);
|
|
3039
|
+
}
|
|
1363
3040
|
}
|
|
1364
3041
|
expanded.push(event);
|
|
3042
|
+
if (snapshotVariable) {
|
|
3043
|
+
latestSnapshotByVariable.set(snapshotVariable, event);
|
|
3044
|
+
}
|
|
1365
3045
|
}
|
|
1366
3046
|
return expanded;
|
|
1367
3047
|
}
|
|
1368
3048
|
|
|
1369
|
-
|
|
3049
|
+
function normalizeJavaExecutionPayload(payload) {
|
|
1370
3050
|
assertSupportedExecutionStyle(payload.executionStyle);
|
|
1371
3051
|
if (typeof payload.code !== 'string') {
|
|
1372
3052
|
throw new Error('`code` must be a string');
|
|
@@ -1376,32 +3056,58 @@ async function runJavaRequest(payload, requestId) {
|
|
|
1376
3056
|
throw new Error('Java execution requires a non-empty functionName or class entry name.');
|
|
1377
3057
|
}
|
|
1378
3058
|
|
|
1379
|
-
const totalStart = performance.now();
|
|
1380
|
-
const rewriteStart = performance.now();
|
|
1381
|
-
let normalizedPayload;
|
|
1382
3059
|
try {
|
|
1383
|
-
|
|
3060
|
+
return normalizeJavaRequest(payload);
|
|
1384
3061
|
} catch (error) {
|
|
1385
3062
|
throw makeWorkerStageError('request normalization', error);
|
|
1386
3063
|
}
|
|
3064
|
+
}
|
|
3065
|
+
|
|
3066
|
+
function javaReportConsoleOutput(report) {
|
|
3067
|
+
return [report.compilerStdout, report.compilerStderr].filter(
|
|
3068
|
+
(entry) => typeof entry === 'string' && entry.trim().length > 0
|
|
3069
|
+
);
|
|
3070
|
+
}
|
|
3071
|
+
|
|
3072
|
+
function parseJavaReportOutput(output) {
|
|
3073
|
+
return output ? normalizeJavaSerializedOutput(JSON.parse(output)) : undefined;
|
|
3074
|
+
}
|
|
3075
|
+
|
|
3076
|
+
async function runJavaTraceRequest(payload, requestId) {
|
|
3077
|
+
const totalStart = performance.now();
|
|
3078
|
+
const rewriteStart = performance.now();
|
|
3079
|
+
const normalizedPayload = normalizeJavaExecutionPayload(payload);
|
|
3080
|
+
|
|
3081
|
+
const compileId = buildJavaCompileId(normalizedPayload, 'trace');
|
|
3082
|
+
const dynamicInputs = dynamicInputEntriesForPayload(normalizedPayload, compileId);
|
|
1387
3083
|
|
|
1388
3084
|
let rewrittenSource;
|
|
1389
3085
|
try {
|
|
1390
|
-
rewrittenSource = await rewriteSource(normalizedPayload,
|
|
3086
|
+
rewrittenSource = await rewriteSource(normalizedPayload, compileId, dynamicInputs);
|
|
1391
3087
|
rewrittenSource = augmentTraceCallArgumentSnapshots(rewrittenSource);
|
|
1392
3088
|
rewrittenSource = augmentArrayLengthReads(rewrittenSource);
|
|
1393
|
-
rewrittenSource = self.TraceCodeJavaSourceAugmentations.augmentJavaCollectionOperations(
|
|
3089
|
+
rewrittenSource = self.TraceCodeJavaSourceAugmentations.augmentJavaCollectionOperations(
|
|
3090
|
+
rewrittenSource,
|
|
3091
|
+
normalizedPayload.sourceText
|
|
3092
|
+
);
|
|
3093
|
+
rewrittenSource = augmentJavaObjectFieldOperations(rewrittenSource);
|
|
3094
|
+
rewrittenSource = augmentJavaStdoutEvents(rewrittenSource);
|
|
3095
|
+
rewrittenSource = augmentJavaThrowEvents(rewrittenSource);
|
|
3096
|
+
rewrittenSource = augmentJavaLocalSnapshots(rewrittenSource);
|
|
1394
3097
|
rewrittenSource = augmentTraceReturnValueSnapshots(rewrittenSource);
|
|
1395
3098
|
} catch (error) {
|
|
1396
3099
|
const rewriteError = formatWorkerErrorMessage(error);
|
|
1397
|
-
const
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
3100
|
+
const skipDiagnosticProbe = rewriteError.includes('unsupported legacy line= TraceHooks hooks');
|
|
3101
|
+
const diagnosticProbe = skipDiagnosticProbe
|
|
3102
|
+
? { consoleOutput: [], error: null, hostCallMs: 0, diagnosticError: null }
|
|
3103
|
+
: await collectCompileProbeDiagnostics(
|
|
3104
|
+
normalizedPayload,
|
|
3105
|
+
requestId,
|
|
3106
|
+
payload.options
|
|
3107
|
+
);
|
|
1402
3108
|
const totalEnd = performance.now();
|
|
1403
3109
|
const surfacedError =
|
|
1404
|
-
diagnosticProbe.error ??
|
|
3110
|
+
(skipDiagnosticProbe ? null : diagnosticProbe.error) ??
|
|
1405
3111
|
(rewriteError === 'Java syntax error.'
|
|
1406
3112
|
? 'Java syntax error. Check Code Assist for parser details.'
|
|
1407
3113
|
: `Java source rewrite failed: ${rewriteError}`);
|
|
@@ -1421,10 +3127,16 @@ async function runJavaRequest(payload, requestId) {
|
|
|
1421
3127
|
}
|
|
1422
3128
|
const rewriteEnd = performance.now();
|
|
1423
3129
|
|
|
1424
|
-
const exportsClassName = buildExportsClassName(
|
|
1425
|
-
const packageName = buildPackageName(
|
|
3130
|
+
const exportsClassName = buildExportsClassName(compileId);
|
|
3131
|
+
const packageName = buildPackageName(compileId);
|
|
1426
3132
|
const sourcePath = `/str/${exportsClassName}.java`;
|
|
1427
|
-
const classesDir = `/files/java-worker/${
|
|
3133
|
+
const classesDir = `/files/java-worker/${compileId}/classes`;
|
|
3134
|
+
|
|
3135
|
+
try {
|
|
3136
|
+
await writeDynamicInputFiles(dynamicInputs);
|
|
3137
|
+
} catch (error) {
|
|
3138
|
+
throw makeWorkerStageError('dynamic input write', error);
|
|
3139
|
+
}
|
|
1428
3140
|
|
|
1429
3141
|
try {
|
|
1430
3142
|
await self.cheerpOSAddStringFile(sourcePath, rewrittenSource);
|
|
@@ -1462,9 +3174,7 @@ async function runJavaRequest(payload, requestId) {
|
|
|
1462
3174
|
throw makeWorkerStageError('trace report parse', error);
|
|
1463
3175
|
}
|
|
1464
3176
|
const totalEnd = performance.now();
|
|
1465
|
-
const consoleOutput =
|
|
1466
|
-
(entry) => typeof entry === 'string' && entry.trim().length > 0
|
|
1467
|
-
);
|
|
3177
|
+
const consoleOutput = javaReportConsoleOutput(report);
|
|
1468
3178
|
|
|
1469
3179
|
if (report.success !== true) {
|
|
1470
3180
|
return {
|
|
@@ -1503,7 +3213,7 @@ async function runJavaRequest(payload, requestId) {
|
|
|
1503
3213
|
|
|
1504
3214
|
return {
|
|
1505
3215
|
success: true,
|
|
1506
|
-
output:
|
|
3216
|
+
output: parseJavaReportOutput(report.output),
|
|
1507
3217
|
events: expandLoopHeaderTraceEvents(
|
|
1508
3218
|
normalizeScriptTraceEvents(
|
|
1509
3219
|
Array.isArray(report.events) ? report.events : [],
|
|
@@ -1535,6 +3245,226 @@ async function runJavaRequest(payload, requestId) {
|
|
|
1535
3245
|
};
|
|
1536
3246
|
}
|
|
1537
3247
|
|
|
3248
|
+
async function runJavaCodeRequest(payload) {
|
|
3249
|
+
const totalStart = performance.now();
|
|
3250
|
+
const normalizedPayload = normalizeJavaExecutionPayload(payload);
|
|
3251
|
+
const compileId = buildJavaCompileId(normalizedPayload, 'execute');
|
|
3252
|
+
const dynamicInputs = dynamicInputEntriesForPayload(normalizedPayload, compileId);
|
|
3253
|
+
const exportsClassName = buildExportsClassName(compileId);
|
|
3254
|
+
const packageName = buildPackageName(compileId);
|
|
3255
|
+
const sourcePath = `/str/${exportsClassName}.java`;
|
|
3256
|
+
const classesDir = `/files/java-worker/${compileId}/classes`;
|
|
3257
|
+
|
|
3258
|
+
let runnableSource;
|
|
3259
|
+
try {
|
|
3260
|
+
runnableSource = buildPlainRunnableSource(normalizedPayload, compileId, dynamicInputs);
|
|
3261
|
+
} catch (error) {
|
|
3262
|
+
throw makeWorkerStageError('source generation', error);
|
|
3263
|
+
}
|
|
3264
|
+
|
|
3265
|
+
try {
|
|
3266
|
+
await writeDynamicInputFiles(dynamicInputs);
|
|
3267
|
+
} catch (error) {
|
|
3268
|
+
throw makeWorkerStageError('dynamic input write', error);
|
|
3269
|
+
}
|
|
3270
|
+
|
|
3271
|
+
try {
|
|
3272
|
+
await self.cheerpOSAddStringFile(sourcePath, runnableSource);
|
|
3273
|
+
} catch (error) {
|
|
3274
|
+
throw makeWorkerStageError('source file write', error);
|
|
3275
|
+
}
|
|
3276
|
+
|
|
3277
|
+
let compileLibraryClass;
|
|
3278
|
+
try {
|
|
3279
|
+
compileLibraryClass = await getCompileLibraryClass();
|
|
3280
|
+
} catch (error) {
|
|
3281
|
+
throw makeWorkerStageError('compiler bridge load', error);
|
|
3282
|
+
}
|
|
3283
|
+
|
|
3284
|
+
const libraryCallStart = performance.now();
|
|
3285
|
+
let reportText;
|
|
3286
|
+
try {
|
|
3287
|
+
reportText = await compileLibraryClass.compileAndRun(
|
|
3288
|
+
sourcePath,
|
|
3289
|
+
classesDir,
|
|
3290
|
+
`${packageName}.${exportsClassName}`,
|
|
3291
|
+
HELPER_JAR_PATH,
|
|
3292
|
+
DEFAULT_EXECUTE_COMPILER_DEBUG_PROFILE
|
|
3293
|
+
);
|
|
3294
|
+
} catch (error) {
|
|
3295
|
+
throw makeWorkerStageError('compile and run', error);
|
|
3296
|
+
}
|
|
3297
|
+
const libraryCallEnd = performance.now();
|
|
3298
|
+
|
|
3299
|
+
let report;
|
|
3300
|
+
try {
|
|
3301
|
+
report = JSON.parse(reportText);
|
|
3302
|
+
} catch (error) {
|
|
3303
|
+
throw makeWorkerStageError('execution report parse', error);
|
|
3304
|
+
}
|
|
3305
|
+
|
|
3306
|
+
const totalEnd = performance.now();
|
|
3307
|
+
const consoleOutput = javaReportConsoleOutput(report);
|
|
3308
|
+
const timings = {
|
|
3309
|
+
hostCallMs: libraryCallEnd - libraryCallStart,
|
|
3310
|
+
totalMs: totalEnd - totalStart,
|
|
3311
|
+
compileMs: report.compileTimeMs ?? 0,
|
|
3312
|
+
classLoadMs: report.classLoadTimeMs ?? 0,
|
|
3313
|
+
runMs: report.runTimeMs ?? 0,
|
|
3314
|
+
compileCacheHit: report.compileCacheHit ?? false,
|
|
3315
|
+
};
|
|
3316
|
+
|
|
3317
|
+
if (report.success !== true) {
|
|
3318
|
+
return {
|
|
3319
|
+
success: false,
|
|
3320
|
+
output: null,
|
|
3321
|
+
executionTimeMs: totalEnd - totalStart,
|
|
3322
|
+
consoleOutput,
|
|
3323
|
+
error:
|
|
3324
|
+
report.runtimeError ||
|
|
3325
|
+
report.compilerStderr ||
|
|
3326
|
+
report.compilerStdout ||
|
|
3327
|
+
'Java execution failed',
|
|
3328
|
+
timings,
|
|
3329
|
+
};
|
|
3330
|
+
}
|
|
3331
|
+
|
|
3332
|
+
return {
|
|
3333
|
+
success: true,
|
|
3334
|
+
output: parseJavaReportOutput(report.output),
|
|
3335
|
+
executionTimeMs: totalEnd - totalStart,
|
|
3336
|
+
consoleOutput,
|
|
3337
|
+
timings,
|
|
3338
|
+
};
|
|
3339
|
+
}
|
|
3340
|
+
|
|
3341
|
+
async function runJavaCodeBatchRequest(payload) {
|
|
3342
|
+
const totalStart = performance.now();
|
|
3343
|
+
const inputBatch = Array.isArray(payload.inputBatch)
|
|
3344
|
+
? payload.inputBatch.map((inputs) => inputs && typeof inputs === 'object' ? inputs : {})
|
|
3345
|
+
: [];
|
|
3346
|
+
if (inputBatch.length === 0) {
|
|
3347
|
+
throw new Error('Java batch execution requires a non-empty inputBatch array.');
|
|
3348
|
+
}
|
|
3349
|
+
|
|
3350
|
+
const normalizedPayload = normalizeJavaExecutionPayload({
|
|
3351
|
+
...payload,
|
|
3352
|
+
inputs: inputBatch[0] ?? {},
|
|
3353
|
+
});
|
|
3354
|
+
const compileId = buildJavaBatchCompileId(normalizedPayload, inputBatch);
|
|
3355
|
+
const dynamicInputBatch = inputBatch.map((inputs, index) =>
|
|
3356
|
+
dynamicInputEntriesForPayload(
|
|
3357
|
+
{ ...normalizedPayload, inputs },
|
|
3358
|
+
`${compileId}-${index}`
|
|
3359
|
+
)
|
|
3360
|
+
);
|
|
3361
|
+
const dynamicInputs = dynamicInputBatch.flat();
|
|
3362
|
+
const exportsClassName = buildExportsClassName(compileId);
|
|
3363
|
+
const sourcePath = `/str/${exportsClassName}.java`;
|
|
3364
|
+
const classesDir = `/files/java-worker/${compileId}/classes`;
|
|
3365
|
+
|
|
3366
|
+
let runnableSource;
|
|
3367
|
+
let entryClasses;
|
|
3368
|
+
try {
|
|
3369
|
+
const batchSource = buildBatchRunnableSource(normalizedPayload, compileId, inputBatch, dynamicInputBatch);
|
|
3370
|
+
runnableSource = batchSource.source;
|
|
3371
|
+
entryClasses = batchSource.entryClasses;
|
|
3372
|
+
} catch (error) {
|
|
3373
|
+
throw makeWorkerStageError('batch source generation', error);
|
|
3374
|
+
}
|
|
3375
|
+
|
|
3376
|
+
try {
|
|
3377
|
+
await writeDynamicInputFiles(dynamicInputs);
|
|
3378
|
+
} catch (error) {
|
|
3379
|
+
throw makeWorkerStageError('dynamic input write', error);
|
|
3380
|
+
}
|
|
3381
|
+
|
|
3382
|
+
try {
|
|
3383
|
+
await self.cheerpOSAddStringFile(sourcePath, runnableSource);
|
|
3384
|
+
} catch (error) {
|
|
3385
|
+
throw makeWorkerStageError('source file write', error);
|
|
3386
|
+
}
|
|
3387
|
+
|
|
3388
|
+
let compileLibraryClass;
|
|
3389
|
+
try {
|
|
3390
|
+
compileLibraryClass = await getCompileLibraryClass();
|
|
3391
|
+
} catch (error) {
|
|
3392
|
+
throw makeWorkerStageError('compiler bridge load', error);
|
|
3393
|
+
}
|
|
3394
|
+
|
|
3395
|
+
const libraryCallStart = performance.now();
|
|
3396
|
+
let reportText;
|
|
3397
|
+
try {
|
|
3398
|
+
reportText = await compileLibraryClass.compileAndRunBatch(
|
|
3399
|
+
sourcePath,
|
|
3400
|
+
classesDir,
|
|
3401
|
+
entryClasses.join('\n'),
|
|
3402
|
+
HELPER_JAR_PATH,
|
|
3403
|
+
DEFAULT_EXECUTE_COMPILER_DEBUG_PROFILE
|
|
3404
|
+
);
|
|
3405
|
+
} catch (error) {
|
|
3406
|
+
throw makeWorkerStageError('compile and run batch', error);
|
|
3407
|
+
}
|
|
3408
|
+
const libraryCallEnd = performance.now();
|
|
3409
|
+
|
|
3410
|
+
let report;
|
|
3411
|
+
try {
|
|
3412
|
+
report = JSON.parse(reportText);
|
|
3413
|
+
} catch (error) {
|
|
3414
|
+
throw makeWorkerStageError('batch execution report parse', error);
|
|
3415
|
+
}
|
|
3416
|
+
|
|
3417
|
+
const totalEnd = performance.now();
|
|
3418
|
+
const consoleOutput = javaReportConsoleOutput(report);
|
|
3419
|
+
const compileMs = report.compileTimeMs ?? 0;
|
|
3420
|
+
const compileCacheHit = report.compileCacheHit ?? false;
|
|
3421
|
+
const rawResults = Array.isArray(report.results) ? report.results : [];
|
|
3422
|
+
const results = rawResults.map((entry) => {
|
|
3423
|
+
const success = entry?.success === true;
|
|
3424
|
+
const classLoadMs = entry?.classLoadTimeMs ?? 0;
|
|
3425
|
+
const runMs = entry?.runTimeMs ?? 0;
|
|
3426
|
+
return {
|
|
3427
|
+
success,
|
|
3428
|
+
output: success ? parseJavaReportOutput(entry.output) : null,
|
|
3429
|
+
consoleOutput,
|
|
3430
|
+
...(success ? {} : { error: entry?.runtimeError || report.runtimeError || 'Java execution failed' }),
|
|
3431
|
+
timings: {
|
|
3432
|
+
compileMs: 0,
|
|
3433
|
+
classLoadMs,
|
|
3434
|
+
runMs,
|
|
3435
|
+
hostCallMs: 0,
|
|
3436
|
+
totalMs: classLoadMs + runMs,
|
|
3437
|
+
compileCacheHit,
|
|
3438
|
+
},
|
|
3439
|
+
};
|
|
3440
|
+
});
|
|
3441
|
+
|
|
3442
|
+
if (results.length > 0) {
|
|
3443
|
+
results[0].timings = {
|
|
3444
|
+
...results[0].timings,
|
|
3445
|
+
compileMs,
|
|
3446
|
+
hostCallMs: libraryCallEnd - libraryCallStart,
|
|
3447
|
+
totalMs: totalEnd - totalStart,
|
|
3448
|
+
};
|
|
3449
|
+
}
|
|
3450
|
+
|
|
3451
|
+
return {
|
|
3452
|
+
success: report.success === true,
|
|
3453
|
+
results,
|
|
3454
|
+
executionTimeMs: totalEnd - totalStart,
|
|
3455
|
+
consoleOutput,
|
|
3456
|
+
...(report.success === true ? {} : { error: report.runtimeError || 'Java batch execution failed' }),
|
|
3457
|
+
timings: {
|
|
3458
|
+
hostCallMs: libraryCallEnd - libraryCallStart,
|
|
3459
|
+
totalMs: totalEnd - totalStart,
|
|
3460
|
+
compileMs,
|
|
3461
|
+
classLoadMs: rawResults.reduce((sum, entry) => sum + (entry?.classLoadTimeMs ?? 0), 0),
|
|
3462
|
+
runMs: rawResults.reduce((sum, entry) => sum + (entry?.runTimeMs ?? 0), 0),
|
|
3463
|
+
compileCacheHit,
|
|
3464
|
+
},
|
|
3465
|
+
};
|
|
3466
|
+
}
|
|
3467
|
+
|
|
1538
3468
|
self.onmessage = (event) => {
|
|
1539
3469
|
const message = event.data;
|
|
1540
3470
|
if (!message || typeof message !== 'object') {
|
|
@@ -1555,22 +3485,63 @@ self.onmessage = (event) => {
|
|
|
1555
3485
|
if (message.type === 'init') {
|
|
1556
3486
|
queue = queue.then(async () => {
|
|
1557
3487
|
try {
|
|
3488
|
+
applyWorkerOptions(message.payload);
|
|
3489
|
+
const startedAt = performance.now();
|
|
1558
3490
|
await ensureReady();
|
|
1559
|
-
|
|
3491
|
+
const totalMs = performance.now() - startedAt;
|
|
1560
3492
|
postMessageResponse({
|
|
1561
3493
|
id: message.id,
|
|
1562
3494
|
type: 'init',
|
|
1563
3495
|
payload: {
|
|
1564
3496
|
success: true,
|
|
1565
|
-
loadTimeMs: Math.round(
|
|
3497
|
+
loadTimeMs: Math.round(totalMs),
|
|
3498
|
+
timings: {
|
|
3499
|
+
totalMs,
|
|
3500
|
+
initMs: initLoadTimeMs ?? 0,
|
|
3501
|
+
warmupMs: 0,
|
|
3502
|
+
},
|
|
1566
3503
|
},
|
|
1567
3504
|
});
|
|
1568
3505
|
} catch (error) {
|
|
3506
|
+
emitRuntimeDiagnostic('error', 'worker-request-failed', 'Java worker init request failed.', {
|
|
3507
|
+
type: message.type,
|
|
3508
|
+
message: formatWorkerErrorMessage(error),
|
|
3509
|
+
});
|
|
3510
|
+
postMessageResponse({
|
|
3511
|
+
id: message.id,
|
|
3512
|
+
type: 'error',
|
|
3513
|
+
payload: { error: formatWorkerErrorMessage(error) },
|
|
3514
|
+
});
|
|
3515
|
+
} finally {
|
|
3516
|
+
resetIdleTimer();
|
|
3517
|
+
}
|
|
3518
|
+
});
|
|
3519
|
+
return;
|
|
3520
|
+
}
|
|
3521
|
+
|
|
3522
|
+
if (message.type === 'warmup') {
|
|
3523
|
+
queue = queue.then(async () => {
|
|
3524
|
+
try {
|
|
3525
|
+
applyWorkerOptions(message.payload);
|
|
3526
|
+
await ensureReady();
|
|
3527
|
+
const result = await warmRunHost();
|
|
3528
|
+
postMessageResponse({
|
|
3529
|
+
id: message.id,
|
|
3530
|
+
type: 'warmup',
|
|
3531
|
+
payload: result,
|
|
3532
|
+
});
|
|
3533
|
+
} catch (error) {
|
|
3534
|
+
emitRuntimeDiagnostic('error', 'worker-request-failed', 'Java worker warmup request failed.', {
|
|
3535
|
+
type: message.type,
|
|
3536
|
+
message: formatWorkerErrorMessage(error),
|
|
3537
|
+
});
|
|
1569
3538
|
postMessageResponse({
|
|
1570
3539
|
id: message.id,
|
|
1571
3540
|
type: 'error',
|
|
1572
3541
|
payload: { error: formatWorkerErrorMessage(error) },
|
|
1573
3542
|
});
|
|
3543
|
+
} finally {
|
|
3544
|
+
resetIdleTimer();
|
|
1574
3545
|
}
|
|
1575
3546
|
});
|
|
1576
3547
|
return;
|
|
@@ -1579,23 +3550,35 @@ self.onmessage = (event) => {
|
|
|
1579
3550
|
if (
|
|
1580
3551
|
message.type === 'execute-with-tracing' ||
|
|
1581
3552
|
message.type === 'execute-code' ||
|
|
3553
|
+
message.type === 'execute-code-batch' ||
|
|
1582
3554
|
message.type === 'execute-code-interview'
|
|
1583
3555
|
) {
|
|
1584
3556
|
queue = queue.then(async () => {
|
|
1585
3557
|
try {
|
|
3558
|
+
applyWorkerOptions(message.payload);
|
|
1586
3559
|
await ensureReady();
|
|
1587
|
-
const result =
|
|
3560
|
+
const result = message.type === 'execute-with-tracing'
|
|
3561
|
+
? await runJavaTraceRequest(message.payload, message.id)
|
|
3562
|
+
: message.type === 'execute-code-batch'
|
|
3563
|
+
? await runJavaCodeBatchRequest(message.payload)
|
|
3564
|
+
: await runJavaCodeRequest(message.payload);
|
|
1588
3565
|
postMessageResponse({
|
|
1589
3566
|
id: message.id,
|
|
1590
3567
|
type: message.type,
|
|
1591
3568
|
payload: result,
|
|
1592
3569
|
});
|
|
1593
3570
|
} catch (error) {
|
|
3571
|
+
emitRuntimeDiagnostic('error', 'worker-request-failed', 'Java worker execution request failed.', {
|
|
3572
|
+
type: message.type,
|
|
3573
|
+
message: formatWorkerErrorMessage(error),
|
|
3574
|
+
});
|
|
1594
3575
|
postMessageResponse({
|
|
1595
3576
|
id: message.id,
|
|
1596
3577
|
type: 'error',
|
|
1597
3578
|
payload: { error: formatWorkerErrorMessage(error) },
|
|
1598
3579
|
});
|
|
3580
|
+
} finally {
|
|
3581
|
+
resetIdleTimer();
|
|
1599
3582
|
}
|
|
1600
3583
|
});
|
|
1601
3584
|
return;
|
|
@@ -1603,5 +3586,6 @@ self.onmessage = (event) => {
|
|
|
1603
3586
|
};
|
|
1604
3587
|
|
|
1605
3588
|
queueMicrotask(() => {
|
|
3589
|
+
emitRuntimeDiagnostic('info', 'worker-ready', 'Java worker is ready.');
|
|
1606
3590
|
postMessageResponse({ type: 'worker-ready' });
|
|
1607
3591
|
});
|