From 9a21055c686dbe8ae5b9a7d3d5b9f054f83d8db7 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" Date: Tue, 3 Oct 2023 23:21:10 +0000 Subject: [PATCH] =?UTF-8?q?[runtime]=20Sync=20b20f704=20=E2=86=92=20ef6283?= =?UTF-8?q?a=20Diff:=20https://github.com/dotnet/runtime/compare/b20f704cc?= =?UTF-8?q?00f390e5560a137deb8f0e64e863e1d..ef6283ac0a14c78d9e9fef48415450?= =?UTF-8?q?99bd7ad12b?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: https://github.com/dotnet/runtime/commit/b20f704cc00f390e5560a137deb8f0e64e863e1d To: https://github.com/dotnet/runtime/commit/ef6283ac0a14c78d9e9fef4841545099bd7ad12b Commits: - Update dependencies from https://dev.azure.com/dnceng/internal/_git/dotnet-optimization build 20230928.3 (#92816) https://github.com/dotnet/runtime/commit/f1e4e90e2c125c6066d96bb0b8d64163b1def1a7 - Changes from https://github.com/dotnet/runtime/pull/92630 (#92753) https://github.com/dotnet/runtime/commit/8632a7572473caeab7c4eb29d2a1b82fc31a1fc1 - [release/8.0] [browser] Remove duplicated marshaling of return value for JSExport (#92886) https://github.com/dotnet/runtime/commit/172d79a458e9468e74bba60dc061a5c94aa21eca - fix https://github.com/dotnet/runtime/issues/92713 (#92890) https://github.com/dotnet/runtime/commit/8e365ee9e1c1b4da3300b0ecb672ea7c85b1f220 - [release/8.0] Update dependencies from dotnet/roslyn (#92503) https://github.com/dotnet/runtime/commit/ef6283ac0a14c78d9e9fef4841545099bd7ad12b [[ commit created by automation ]] --- README.md | 2 +- prereqs/git-info/AllRepoVersions.props | 4 +- prereqs/git-info/runtime.props | 6 +- src/runtime/eng/Version.Details.xml | 36 +++--- src/runtime/eng/Versions.props | 18 +-- .../JSExportCodeGenerator.cs | 38 +++--- .../X509Certificates/ChainPal.Apple.cs | 16 +-- .../BrowserDebugProxy/EvaluateExpression.cs | 4 +- .../MemberReferenceResolver.cs | 120 ++++++++++++------ .../EvaluateOnCallFrame2Tests.cs | 18 +++ .../EvaluateOnCallFrameTests.cs | 4 +- .../debugger-test/debugger-evaluate-test.cs | 6 +- src/runtime/src/mono/wasm/runtime/startup.ts | 6 +- src/source-manifest.json | 4 +- 14 files changed, 173 insertions(+), 109 deletions(-) diff --git a/README.md b/README.md index e9be3c6e354..73a329b05e1 100644 --- a/README.md +++ b/README.md @@ -196,7 +196,7 @@ To enable full offline source-building of the VMR, we have no other choice than - `src/roslyn-analyzers` *[dotnet/roslyn-analyzers@4a7701f](https://github.com/dotnet/roslyn-analyzers/commit/4a7701fd72094614897b33e4cb1d9640c221d862)* - `src/runtime` -*[dotnet/runtime@b20f704](https://github.com/dotnet/runtime/commit/b20f704cc00f390e5560a137deb8f0e64e863e1d)* +*[dotnet/runtime@ef6283a](https://github.com/dotnet/runtime/commit/ef6283ac0a14c78d9e9fef4841545099bd7ad12b)* - `src/sdk` *[dotnet/sdk@2296937](https://github.com/dotnet/sdk/commit/22969374eed5b2467de56e127f65abfb3627e275)* - `src/source-build-externals` diff --git a/prereqs/git-info/AllRepoVersions.props b/prereqs/git-info/AllRepoVersions.props index 7b261d7dc98..5e2b2ca6914 100644 --- a/prereqs/git-info/AllRepoVersions.props +++ b/prereqs/git-info/AllRepoVersions.props @@ -31,8 +31,8 @@ 3.11.0-beta1.23472.1 0d735148bbb4cb511be547fbc1db63a2c81a821d 4.8.0-3.23501.1 - b20f704cc00f390e5560a137deb8f0e64e863e1d - 8.0.0-rtm.23478.17 + ef6283ac0a14c78d9e9fef4841545099bd7ad12b + 8.0.0-rtm.23502.11 22969374eed5b2467de56e127f65abfb3627e275 8.0.100-rtm.23503.4 ed17956dbc31097b7ba6a66be086f4a70a97d84f diff --git a/prereqs/git-info/runtime.props b/prereqs/git-info/runtime.props index 3f944a972bc..3f91a1ac0cc 100644 --- a/prereqs/git-info/runtime.props +++ b/prereqs/git-info/runtime.props @@ -1,9 +1,9 @@  - b20f704cc00f390e5560a137deb8f0e64e863e1d - 20230928.17 - 8.0.0-rtm.23478.17 + ef6283ac0a14c78d9e9fef4841545099bd7ad12b + 20231002.11 + 8.0.0-rtm.23502.11 rtm false diff --git a/src/runtime/eng/Version.Details.xml b/src/runtime/eng/Version.Details.xml index 9896dec90d5..1f220ede26d 100644 --- a/src/runtime/eng/Version.Details.xml +++ b/src/runtime/eng/Version.Details.xml @@ -334,21 +334,21 @@ https://github.com/dotnet/arcade 1d451c32dda2314c721adbf8829e1c0cd4e681ff - + https://dev.azure.com/dnceng/internal/_git/dotnet-optimization - a268dec2bc8ad282a525897b428cf014d5181f77 + 492f7464d31d9599531fab2a67bc2422046f5133 - + https://dev.azure.com/dnceng/internal/_git/dotnet-optimization - a268dec2bc8ad282a525897b428cf014d5181f77 + 492f7464d31d9599531fab2a67bc2422046f5133 - + https://dev.azure.com/dnceng/internal/_git/dotnet-optimization - a268dec2bc8ad282a525897b428cf014d5181f77 + 492f7464d31d9599531fab2a67bc2422046f5133 - + https://dev.azure.com/dnceng/internal/_git/dotnet-optimization - a268dec2bc8ad282a525897b428cf014d5181f77 + 492f7464d31d9599531fab2a67bc2422046f5133 https://github.com/dotnet/hotreload-utils @@ -358,18 +358,18 @@ https://github.com/dotnet/runtime-assets 99168dcff56809205e7ef8530d1256f3a07fab1f - + https://github.com/dotnet/roslyn - aa7e4da5341196be494ca4bb0c719d7bef3e396a + 0d735148bbb4cb511be547fbc1db63a2c81a821d - + https://github.com/dotnet/roslyn - aa7e4da5341196be494ca4bb0c719d7bef3e396a + 0d735148bbb4cb511be547fbc1db63a2c81a821d - + https://github.com/dotnet/roslyn - aa7e4da5341196be494ca4bb0c719d7bef3e396a + 0d735148bbb4cb511be547fbc1db63a2c81a821d https://github.com/dotnet/roslyn-analyzers @@ -384,13 +384,13 @@ d10b02ae5cc670609d920a672985ed4456bdd6b6 - + https://dev.azure.com/dnceng/internal/_git/dotnet-optimization - a268dec2bc8ad282a525897b428cf014d5181f77 + 492f7464d31d9599531fab2a67bc2422046f5133 - + https://dev.azure.com/dnceng/internal/_git/dotnet-optimization - a268dec2bc8ad282a525897b428cf014d5181f77 + 492f7464d31d9599531fab2a67bc2422046f5133 diff --git a/src/runtime/eng/Versions.props b/src/runtime/eng/Versions.props index 216a4a7406b..1663485ec06 100644 --- a/src/runtime/eng/Versions.props +++ b/src/runtime/eng/Versions.props @@ -44,9 +44,9 @@ Any tools that contribute to the design-time experience should use the MicrosoftCodeAnalysisVersion_LatestVS property above to ensure they do not break the local dev experience. --> - 4.8.0-3.23472.2 - 4.8.0-3.23472.2 - 4.8.0-3.23472.2 + 4.8.0-3.23501.1 + 4.8.0-3.23501.1 + 4.8.0-3.23501.1 - 1.0.0-prerelease.23477.3 - 1.0.0-prerelease.23477.3 - 1.0.0-prerelease.23477.3 - 1.0.0-prerelease.23477.3 - 1.0.0-prerelease.23477.3 - 1.0.0-prerelease.23477.3 + 1.0.0-prerelease.23478.3 + 1.0.0-prerelease.23478.3 + 1.0.0-prerelease.23478.3 + 1.0.0-prerelease.23478.3 + 1.0.0-prerelease.23478.3 + 1.0.0-prerelease.23478.3 16.11.29-beta1.23404.4 2.0.0-beta4.23307.1 diff --git a/src/runtime/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSExportCodeGenerator.cs b/src/runtime/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSExportCodeGenerator.cs index 0a18241ef7c..a00fc9e4024 100644 --- a/src/runtime/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSExportCodeGenerator.cs +++ b/src/runtime/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSExportCodeGenerator.cs @@ -59,7 +59,7 @@ public JSExportCodeGenerator( public BlockSyntax GenerateJSExportBody() { - StatementSyntax invoke = InvokeSyntax(); + List invoke = InvokeSyntax(); GeneratedStatements statements = GeneratedStatements.Create(_marshallers, _context); bool shouldInitializeVariables = !statements.GuaranteedUnmarshal.IsEmpty || !statements.CleanupCallerAllocated.IsEmpty || !statements.CleanupCalleeAllocated.IsEmpty; VariableDeclarations declarations = VariableDeclarations.GenerateDeclarationsForUnmanagedToManaged(_marshallers, _context, shouldInitializeVariables); @@ -79,7 +79,7 @@ public BlockSyntax GenerateJSExportBody() var tryStatements = new List(); tryStatements.AddRange(statements.Unmarshal); - tryStatements.Add(invoke); + tryStatements.AddRange(invoke); if (!(statements.GuaranteedUnmarshal.IsEmpty && statements.CleanupCalleeAllocated.IsEmpty)) { @@ -93,6 +93,18 @@ public BlockSyntax GenerateJSExportBody() tryStatements.AddRange(statements.Marshal); List allStatements = setupStatements; + + // Wrap unmarshall, invocation and return value marshalling in try-catch. + // In case of exception, marshal exception instead of return value. + var tryInvokeAndMarshal = TryStatement(SingletonList(CatchClause() + .WithDeclaration(CatchDeclaration(IdentifierName(Constants.ExceptionGlobal)).WithIdentifier(Identifier("ex"))) + .WithBlock(Block(SingletonList( + ExpressionStatement(InvocationExpression( + MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, + IdentifierName(Constants.ArgumentException), IdentifierName(Constants.ToJSMethod))) + .WithArgumentList(ArgumentList(SingletonSeparatedList(Argument(IdentifierName("ex"))))))))))) + .WithBlock(Block(tryStatements)); + List finallyStatements = new List(); if (!(statements.GuaranteedUnmarshal.IsEmpty && statements.CleanupCalleeAllocated.IsEmpty)) { @@ -100,16 +112,14 @@ public BlockSyntax GenerateJSExportBody() } finallyStatements.AddRange(statements.CleanupCallerAllocated); + if (finallyStatements.Count > 0) { - allStatements.Add( - TryStatement(Block(tryStatements), default, FinallyClause(Block(finallyStatements)))); - } - else - { - allStatements.AddRange(tryStatements); + tryInvokeAndMarshal = TryStatement(Block(tryInvokeAndMarshal), default, FinallyClause(Block(finallyStatements))); } + allStatements.Add(tryInvokeAndMarshal); + return Block(allStatements); } @@ -175,7 +185,7 @@ private void SetupSyntax(List statementsToUpdate) Argument(LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(1))))))))))))); } - private TryStatementSyntax InvokeSyntax() + private List InvokeSyntax() { var statements = new List(); var arguments = new List(); @@ -205,16 +215,8 @@ private TryStatementSyntax InvokeSyntax() IdentifierName(nativeIdentifier), invocation)); statements.Add(statement); - statements.AddRange(_marshallers.ManagedReturnMarshaller.Generator.Generate(_marshallers.ManagedReturnMarshaller.TypeInfo, _context with { CurrentStage = StubCodeContext.Stage.Marshal })); } - return TryStatement(SingletonList(CatchClause() - .WithDeclaration(CatchDeclaration(IdentifierName(Constants.ExceptionGlobal)).WithIdentifier(Identifier("ex"))) - .WithBlock(Block(SingletonList( - ExpressionStatement(InvocationExpression( - MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, - IdentifierName(Constants.ArgumentException), IdentifierName(Constants.ToJSMethod))) - .WithArgumentList(ArgumentList(SingletonSeparatedList(Argument(IdentifierName("ex"))))))))))) - .WithBlock(Block(statements)); + return statements; } diff --git a/src/runtime/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ChainPal.Apple.cs b/src/runtime/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ChainPal.Apple.cs index 7c3ab590319..6df9aacc727 100644 --- a/src/runtime/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ChainPal.Apple.cs +++ b/src/runtime/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ChainPal.Apple.cs @@ -348,16 +348,14 @@ private void BuildAndSetProperties((X509Certificate2, int)[] elementTuples) for (int i = 0; i < elementTuples.Length; i++) { - (X509Certificate2, int) tuple = elementTuples[i]; + (X509Certificate2 cert, int chainStatus) = elementTuples[i]; - elements[i] = BuildElement(tuple.Item1, tuple.Item2); - allStatus |= tuple.Item2; + elements[i] = new X509ChainElement(cert, BuildChainElementStatuses(cert, chainStatus), ""); + allStatus |= chainStatus; } ChainElements = elements; - - X509ChainElement rollupElement = BuildElement(null!, allStatus); - ChainStatus = rollupElement.ChainElementStatus; + ChainStatus = BuildChainElementStatuses(null, allStatus); } private static void FixupRevocationStatus( @@ -457,11 +455,11 @@ private static X509ChainStatusFlags FindUntrustedRootReason(X509Certificate2 cer return X509ChainStatusFlags.UntrustedRoot; } - private X509ChainElement BuildElement(X509Certificate2 cert, int dwStatus) + private X509ChainStatus[] BuildChainElementStatuses(X509Certificate2? cert, int dwStatus) { if (dwStatus == 0) { - return new X509ChainElement(cert, Array.Empty(), ""); + return Array.Empty(); } List statuses = new List(); @@ -499,7 +497,7 @@ private X509ChainElement BuildElement(X509Certificate2 cert, int dwStatus) } } - return new X509ChainElement(cert, statuses.ToArray(), ""); + return statuses.ToArray(); } private readonly struct X509ChainErrorMapping diff --git a/src/runtime/src/mono/wasm/debugger/BrowserDebugProxy/EvaluateExpression.cs b/src/runtime/src/mono/wasm/debugger/BrowserDebugProxy/EvaluateExpression.cs index c384f74e9c7..45d700e122e 100644 --- a/src/runtime/src/mono/wasm/debugger/BrowserDebugProxy/EvaluateExpression.cs +++ b/src/runtime/src/mono/wasm/debugger/BrowserDebugProxy/EvaluateExpression.cs @@ -387,12 +387,14 @@ private static async Task> ResolveElementAccess(ExpressionSyntaxR { var values = new List(); JObject index = null; + List nestedIndexers = new(); IEnumerable elementAccesses = replacer.elementAccess; foreach (ElementAccessExpressionSyntax elementAccess in elementAccesses.Reverse()) { - index = await resolver.Resolve(elementAccess, replacer.memberAccessValues, index, replacer.variableDefinitions, token); + index = await resolver.Resolve(elementAccess, replacer.memberAccessValues, nestedIndexers, replacer.variableDefinitions, token); if (index == null) throw new ReturnAsErrorException($"Failed to resolve element access for {elementAccess}", "ReferenceError"); + nestedIndexers.Add(index); } values.Add(index); return values; diff --git a/src/runtime/src/mono/wasm/debugger/BrowserDebugProxy/MemberReferenceResolver.cs b/src/runtime/src/mono/wasm/debugger/BrowserDebugProxy/MemberReferenceResolver.cs index 650583a9dc7..e1b9583ddbe 100644 --- a/src/runtime/src/mono/wasm/debugger/BrowserDebugProxy/MemberReferenceResolver.cs +++ b/src/runtime/src/mono/wasm/debugger/BrowserDebugProxy/MemberReferenceResolver.cs @@ -366,7 +366,12 @@ async Task ResolveAsInstanceMember(ArraySegment parts, JObject } } - public async Task Resolve(ElementAccessExpressionSyntax elementAccess, Dictionary memberAccessValues, JObject indexObject, List variableDefinitions, CancellationToken token) + public async Task Resolve( + ElementAccessExpressionSyntax elementAccess, + Dictionary memberAccessValues, + List nestedIndexObject, + List variableDefinitions, + CancellationToken token) { try { @@ -376,12 +381,13 @@ public async Task Resolve(ElementAccessExpressionSyntax elementAccess, if (rootObject == null) { - // it might be a jagged array where indexObject should be treated as a new rootObject - rootObject = indexObject; - indexObject = null; + // it might be a jagged array where the previously added nestedIndexObject should be treated as a new rootObject + rootObject = nestedIndexObject.LastOrDefault(); + if (rootObject != null) + nestedIndexObject.RemoveAt(nestedIndexObject.Count - 1); } - ElementIndexInfo elementIdxInfo = await GetElementIndexInfo(); + ElementIndexInfo elementIdxInfo = await GetElementIndexInfo(nestedIndexObject); if (elementIdxInfo is null) return null; @@ -394,6 +400,7 @@ public async Task Resolve(ElementAccessExpressionSyntax elementAccess, if (!DotnetObjectId.TryParse(rootObject?["objectId"]?.Value(), out DotnetObjectId objectId)) throw new InvalidOperationException($"Cannot apply indexing with [] to a primitive object of type '{type}'"); + bool isMultidimensional = elementIdxInfo.DimensionsCount != 1; switch (objectId.Scheme) { case "valuetype": //can be an inlined array @@ -407,7 +414,7 @@ public async Task Resolve(ElementAccessExpressionSyntax elementAccess, } case "array": rootObject["value"] = await context.SdbAgent.GetArrayValues(objectId.Value, token); - if (!elementIdxInfo.IsMultidimensional) + if (!isMultidimensional) { int.TryParse(elementIdxInfo.ElementIdxStr, out elementIdx); return (JObject)rootObject["value"][elementIdx]["value"]; @@ -417,10 +424,8 @@ public async Task Resolve(ElementAccessExpressionSyntax elementAccess, return (JObject)(((JArray)rootObject["value"]).FirstOrDefault(x => x["name"].Value() == elementIdxInfo.ElementIdxStr)["value"]); } case "object": - if (elementIdxInfo.IsMultidimensional) - throw new InvalidOperationException($"Cannot apply indexing with [,] to an object of type '{type}'"); // ToDo: try to use the get_Item for string as well - if (type == "string") + if (!isMultidimensional && type == "string") { var eaExpressionFormatted = elementAccessStrExpression.Replace('.', '_'); // instance_str variableDefinitions.Add(new (eaExpressionFormatted, rootObject, ExpressionEvaluator.ConvertJSToCSharpLocalVariableAssignment(eaExpressionFormatted, rootObject))); @@ -428,7 +433,7 @@ public async Task Resolve(ElementAccessExpressionSyntax elementAccess, var variableDef = await ExpressionEvaluator.GetVariableDefinitions(this, variableDefinitions, invokeToStringInObject: false, token); return await ExpressionEvaluator.EvaluateSimpleExpression(this, eaFormatted, elementAccessStr, variableDef, logger, token); } - if (indexObject is null && elementIdxInfo.IndexingExpression is null) + if (elementIdxInfo.Indexers is null || elementIdxInfo.Indexers.Count == 0) throw new InternalErrorException($"Unable to write index parameter to invoke the method in the runtime."); var typeIds = await context.SdbAgent.GetTypeIdsForObject(objectId.Value, true, token); @@ -441,15 +446,13 @@ public async Task Resolve(ElementAccessExpressionSyntax elementAccess, { MethodInfoWithDebugInformation methodInfo = await context.SdbAgent.GetMethodInfo(methodIds[i], token); ParameterInfo[] paramInfo = methodInfo.GetParametersInfo(); - if (paramInfo.Length == 1) + if (paramInfo.Length == elementIdxInfo.DimensionsCount) { try { - if (indexObject != null && !CheckParametersCompatibility(paramInfo[0].TypeCode, indexObject)) + if (!CheckParametersCompatibility(paramInfo, elementIdxInfo.Indexers)) continue; - ArraySegment buffer = indexObject is null ? - await WriteLiteralExpressionAsIndex(objectId, elementIdxInfo.IndexingExpression, elementIdxInfo.ElementIdxStr) : - await WriteJObjectAsIndex(objectId, indexObject, elementIdxInfo.ElementIdxStr, paramInfo[0].TypeCode); + ArraySegment buffer = await WriteIndexObjectAsIndices(objectId, elementIdxInfo.Indexers, paramInfo); JObject getItemRetObj = await context.SdbAgent.InvokeMethod(buffer, methodIds[i], token); return (JObject)getItemRetObj["value"]; } @@ -470,31 +473,32 @@ await WriteLiteralExpressionAsIndex(objectId, elementIdxInfo.IndexingExpression, throw new ReturnAsErrorException($"Unable to evaluate element access '{elementAccess}': {ex.Message}", ex.GetType().Name); } - async Task GetElementIndexInfo() + async Task GetElementIndexInfo(List nestedIndexers) { - // e.g. x[a[0]], x[a[b[1]]] etc. - if (indexObject is not null) - return new ElementIndexInfo(ElementIdxStr: indexObject["value"].ToString() ); - if (elementAccess.ArgumentList is null) return null; - StringBuilder elementIdxStr = new StringBuilder(); - var multiDimensionalArray = false; + int dimCnt = elementAccess.ArgumentList.Arguments.Count; LiteralExpressionSyntax indexingExpression = null; - for (int i = 0; i < elementAccess.ArgumentList.Arguments.Count; i++) + StringBuilder elementIdxStr = new StringBuilder(); + List indexers = new(); + // nesting should be resolved in reverse order + int nestedIndexersCnt = nestedIndexers.Count - 1; + for (int i = 0; i < dimCnt; i++) { + JObject indexObject; var arg = elementAccess.ArgumentList.Arguments[i]; if (i != 0) { elementIdxStr.Append(", "); - multiDimensionalArray = true; } // e.g. x[1] if (arg.Expression is LiteralExpressionSyntax) { indexingExpression = arg.Expression as LiteralExpressionSyntax; - elementIdxStr.Append(indexingExpression.ToString()); + string expression = indexingExpression.ToString(); + elementIdxStr.Append(expression); + indexers.Add(indexingExpression); } // e.g. x[a] or x[a.b] @@ -508,6 +512,18 @@ async Task GetElementIndexInfo() // x[a] indexObject ??= await Resolve(argParm.Identifier.Text, token); elementIdxStr.Append(indexObject["value"].ToString()); + indexers.Add(indexObject); + } + // nested indexing, e.g. x[a[0]], x[a[b[1]]], x[a[0], b[1]] + else if (arg.Expression is ElementAccessExpressionSyntax) + { + if (nestedIndexers == null || nestedIndexersCnt < 0) + throw new InvalidOperationException($"Cannot resolve nested indexing"); + JObject nestedIndexObject = nestedIndexers[nestedIndexersCnt]; + nestedIndexers.RemoveAt(nestedIndexersCnt); + elementIdxStr.Append(nestedIndexObject["value"].ToString()); + indexers.Add(nestedIndexObject); + nestedIndexersCnt--; } // indexing with expressions, e.g. x[a + 1] else @@ -519,36 +535,57 @@ async Task GetElementIndexInfo() if (idxType != "number") throw new InvalidOperationException($"Cannot index with an object of type '{idxType}'"); elementIdxStr.Append(indexObject["value"].ToString()); + indexers.Add(indexObject); } } return new ElementIndexInfo( + DimensionsCount: dimCnt, ElementIdxStr: elementIdxStr.ToString(), - IsMultidimensional: multiDimensionalArray, - IndexingExpression: indexingExpression); + Indexers: indexers); } - async Task> WriteJObjectAsIndex(DotnetObjectId rootObjId, JObject indexObject, string elementIdxStr, ElementType? expectedType) + async Task> WriteIndexObjectAsIndices(DotnetObjectId rootObjId, List indexObjects, ParameterInfo[] paramInfo) { using var writer = new MonoBinaryWriter(); writer.WriteObj(rootObjId, context.SdbAgent); - writer.Write(1); // number of method args - if (!await writer.WriteJsonValue(indexObject, context.SdbAgent, expectedType, token)) - throw new InternalErrorException($"Parsing index of type {indexObject["type"].Value()} to write it into the buffer failed."); + writer.Write(indexObjects.Count); // number of method args + foreach ((ParameterInfo pi, object indexObject) in paramInfo.Zip(indexObjects)) + { + if (indexObject is JObject indexJObject) + { + // indexed by an identifier name syntax + if (!await writer.WriteJsonValue(indexJObject, context.SdbAgent, pi.TypeCode, token)) + throw new InternalErrorException($"Parsing index of type {indexJObject["type"].Value()} to write it into the buffer failed."); + } + else if (indexObject is LiteralExpressionSyntax expression) + { + // indexed by a literal expression syntax + if (!await writer.WriteConst(expression, context.SdbAgent, token)) + throw new InternalErrorException($"Parsing literal expression index = {expression} to write it into the buffer failed."); + } + else + { + throw new InternalErrorException($"Unexpected index type."); + } + } return writer.GetParameterBuffer(); } + } - async Task> WriteLiteralExpressionAsIndex(DotnetObjectId rootObjId, LiteralExpressionSyntax indexingExpression, string elementIdxStr) + private static bool CheckParametersCompatibility(ParameterInfo[] paramInfos, List indexObjects) + { + if (paramInfos.Length != indexObjects.Count) + return false; + foreach ((ParameterInfo paramInfo, object indexObj) in paramInfos.Zip(indexObjects)) { - using var writer = new MonoBinaryWriter(); - writer.WriteObj(rootObjId, context.SdbAgent); - writer.Write(1); // number of method args - if (!await writer.WriteConst(indexingExpression, context.SdbAgent, token)) - throw new InternalErrorException($"Parsing index of type {indexObject["type"].Value()} to write it into the buffer failed."); - return writer.GetParameterBuffer(); + // shouldn't we check LiteralExpressionSyntax for compatibility as well? + if (indexObj is JObject indexJObj && !CheckParameterCompatibility(paramInfo.TypeCode, indexJObj)) + return false; } + return true; } - private static bool CheckParametersCompatibility(ElementType? paramTypeCode, JObject value) + private static bool CheckParameterCompatibility(ElementType? paramTypeCode, JObject value) { if (!paramTypeCode.HasValue) return true; @@ -871,7 +908,8 @@ public JObject TryGetEvaluationResult(string id) private sealed record ElementIndexInfo( string ElementIdxStr, - bool IsMultidimensional = false, - LiteralExpressionSyntax IndexingExpression = null); + // keeps JObjects and LiteralExpressionSyntaxes: + List Indexers, + int DimensionsCount = 1); } } diff --git a/src/runtime/src/mono/wasm/debugger/DebuggerTestSuite/EvaluateOnCallFrame2Tests.cs b/src/runtime/src/mono/wasm/debugger/DebuggerTestSuite/EvaluateOnCallFrame2Tests.cs index 051da33469c..b1a79b28cee 100644 --- a/src/runtime/src/mono/wasm/debugger/DebuggerTestSuite/EvaluateOnCallFrame2Tests.cs +++ b/src/runtime/src/mono/wasm/debugger/DebuggerTestSuite/EvaluateOnCallFrame2Tests.cs @@ -731,5 +731,23 @@ await CheckEvaluateFail(id, ("dt+1", "Cannot evaluate '(dt+1\n)': (2,9): error CS0019: Operator '+' cannot be applied to operands of type 'object' and 'int'") ); }); + + [Fact] + public async Task EvaluateObjectIndexingMultidimensional() => await CheckInspectLocalsAtBreakpointSite( + "DebuggerTests.EvaluateLocalsWithIndexingTests", "EvaluateLocals", 12, "DebuggerTests.EvaluateLocalsWithIndexingTests.EvaluateLocals", + "window.setTimeout(function() { invoke_static_method ('[debugger-test] DebuggerTests.EvaluateLocalsWithIndexingTests:EvaluateLocals'); })", + wait_for_event_fn: async (pause_location) => + { + var id = pause_location["callFrames"][0]["callFrameId"].Value(); + await EvaluateOnCallFrameAndCheck(id, + ("f[j, aDouble]", TNumber("3.34")), //only IdentifierNameSyntaxes + ("f[1, aDouble]", TNumber("3.34")), //IdentifierNameSyntax with LiteralExpressionSyntax + ("f[aChar, \"&\", longString]", TString("9-&-longString")), + ("f[f.numArray[j], aDouble]", TNumber("4.34")), //ElementAccessExpressionSyntax + ("f[f.numArray[j], f.numArray[0]]", TNumber("3")), //multiple ElementAccessExpressionSyntaxes + ("f[f.numArray[f.numList[0]], f.numArray[i]]", TNumber("3")), + ("f[f.numArray[f.numList[0]], f.numArray[f.numArray[i]]]", TNumber("4")) + ); + }); } } diff --git a/src/runtime/src/mono/wasm/debugger/DebuggerTestSuite/EvaluateOnCallFrameTests.cs b/src/runtime/src/mono/wasm/debugger/DebuggerTestSuite/EvaluateOnCallFrameTests.cs index 2ff9bd26a28..2d0fb878227 100644 --- a/src/runtime/src/mono/wasm/debugger/DebuggerTestSuite/EvaluateOnCallFrameTests.cs +++ b/src/runtime/src/mono/wasm/debugger/DebuggerTestSuite/EvaluateOnCallFrameTests.cs @@ -585,7 +585,7 @@ public async Task EvaluateIndexingNegative() => await CheckInspectLocalsAtBreakp Assert.Equal("Unable to evaluate element access 'f.idx0[2]': Cannot apply indexing with [] to a primitive object of type 'number'", res.Error["result"]?["description"]?.Value()); var exceptionDetailsStack = res.Error["exceptionDetails"]?["stackTrace"]?["callFrames"]?[0]; Assert.Equal("DebuggerTests.EvaluateLocalsWithIndexingTests.EvaluateLocals", exceptionDetailsStack?["functionName"]?.Value()); - Assert.Equal(556, exceptionDetailsStack?["lineNumber"]?.Value()); + Assert.Equal(558, exceptionDetailsStack?["lineNumber"]?.Value()); Assert.Equal(12, exceptionDetailsStack?["columnNumber"]?.Value()); (_, res) = await EvaluateOnCallFrame(id, "f[1]", expect_ok: false ); Assert.Equal( "Unable to evaluate element access 'f[1]': Cannot apply indexing with [] to an object of type 'DebuggerTests.EvaluateLocalsWithIndexingTests.TestEvaluate'", res.Error["result"]?["description"]?.Value()); @@ -722,7 +722,7 @@ public async Task EvaluateIndexingByExpressionNegative() => await CheckInspectLo Assert.Equal("Unable to evaluate element access 'f.numList[\"a\" + 1]': Cannot index with an object of type 'string'", res.Error["result"]?["description"]?.Value()); var exceptionDetailsStack = res.Error["exceptionDetails"]?["stackTrace"]?["callFrames"]?[0]; Assert.Equal("DebuggerTests.EvaluateLocalsWithIndexingTests.EvaluateLocals", exceptionDetailsStack?["functionName"]?.Value()); - Assert.Equal(556, exceptionDetailsStack?["lineNumber"]?.Value()); + Assert.Equal(558, exceptionDetailsStack?["lineNumber"]?.Value()); Assert.Equal(12, exceptionDetailsStack?["columnNumber"]?.Value()); }); diff --git a/src/runtime/src/mono/wasm/debugger/tests/debugger-test/debugger-evaluate-test.cs b/src/runtime/src/mono/wasm/debugger/tests/debugger-test/debugger-evaluate-test.cs index 480dc30115c..e46177ecc92 100644 --- a/src/runtime/src/mono/wasm/debugger/tests/debugger-test/debugger-evaluate-test.cs +++ b/src/runtime/src/mono/wasm/debugger/tests/debugger-test/debugger-evaluate-test.cs @@ -522,7 +522,6 @@ public class TestEvaluate public int idx0; public int idx1; - // ToDo: add 2d indexing - https://github.com/dotnet/runtime/issues/76062 public string this[char key] => "res_" + key; public string this[bool key] => key.ToString(); public bool this[string key] => key.Length > 3; @@ -530,11 +529,14 @@ public class TestEvaluate public int this[float key] => (int)key; public int this[decimal key] => (int)key; + public double this[int key1, double key2] => key1 + key2; + public string this[char key1, string key2, string key3] => $"{key1}-{key2}-{key3}"; + public void run() { numList = new List { 1, 2 }; textList = new List { "1", "2" }; - numArray = new int[] { 1, 2 }; + numArray = new int[] { 1, 2, 0 }; textArray = new string[] { "1", "2" }; numArrayOfArrays = new int[][] { numArray, numArray }; numListOfLists = new List> { numList, numList }; diff --git a/src/runtime/src/mono/wasm/runtime/startup.ts b/src/runtime/src/mono/wasm/runtime/startup.ts index d8eab74d8b2..c385844dfd3 100644 --- a/src/runtime/src/mono/wasm/runtime/startup.ts +++ b/src/runtime/src/mono/wasm/runtime/startup.ts @@ -5,7 +5,7 @@ import MonoWasmThreads from "consts:monoWasmThreads"; import WasmEnableLegacyJsInterop from "consts:wasmEnableLegacyJsInterop"; import { DotnetModuleInternal, CharPtrNull } from "./types/internal"; -import { linkerDisableLegacyJsInterop, ENVIRONMENT_IS_PTHREAD, exportedRuntimeAPI, INTERNAL, loaderHelpers, Module, runtimeHelpers, createPromiseController, mono_assert, linkerWasmEnableSIMD, linkerWasmEnableEH } from "./globals"; +import { linkerDisableLegacyJsInterop, ENVIRONMENT_IS_PTHREAD, exportedRuntimeAPI, INTERNAL, loaderHelpers, Module, runtimeHelpers, createPromiseController, mono_assert, linkerWasmEnableSIMD, linkerWasmEnableEH, ENVIRONMENT_IS_NODE, ENVIRONMENT_IS_WORKER } from "./globals"; import cwraps, { init_c_exports } from "./cwraps"; import { mono_wasm_raise_debug_event, mono_wasm_runtime_ready } from "./debug"; import { toBase64StringImpl } from "./base64"; @@ -273,6 +273,10 @@ async function onRuntimeInitializedAsync(userOnRuntimeInitialized: () => void) { bindings_init(); runtimeHelpers.runtimeReady = true; + if (ENVIRONMENT_IS_NODE && !ENVIRONMENT_IS_WORKER) { + Module.runtimeKeepalivePush(); + } + if (MonoWasmThreads) { runtimeHelpers.javaScriptExports.install_synchronization_context(); runtimeHelpers.jsSynchronizationContextInstalled = true; diff --git a/src/source-manifest.json b/src/source-manifest.json index a299293f857..1b19f578ab0 100644 --- a/src/source-manifest.json +++ b/src/source-manifest.json @@ -91,10 +91,10 @@ "commitSha": "4a7701fd72094614897b33e4cb1d9640c221d862" }, { - "packageVersion": "8.0.0-rtm.23478.17", + "packageVersion": "8.0.0-rtm.23502.11", "path": "runtime", "remoteUri": "https://github.com/dotnet/runtime", - "commitSha": "b20f704cc00f390e5560a137deb8f0e64e863e1d" + "commitSha": "ef6283ac0a14c78d9e9fef4841545099bd7ad12b" }, { "packageVersion": "8.0.100-rtm.23503.4",