This is an automated email from the ASF dual-hosted git repository.

Cole-Greer pushed a commit to branch multi-label-toy-graph
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git

commit ad751d50d39ed44684fd55eb2b6c532ac73cefd1
Author: Cole Greer <[email protected]>
AuthorDate: Mon Jul 6 12:59:57 2026 -0700

    Fix multi-label rendering gaps in ElementMapStep and ComputerGraph
    
    - ComputerElement.labels() previously inherited Element's default
      implementation (Collections.singleton(label())) instead of delegating
      to the wrapped element, silently losing multi-label data and returning
      a nondeterministic single label under GraphComputer/OLAP execution.
    - ElementMapStep.getVertexStructure() always rendered adjacent vertex
      labels via the deprecated, nondeterministic label() regardless of
      with("multilabel") mode, ignoring the same multilabel option that the
      top-level element already respected. Corrected two scenarios in
      ElementMap.feature whose expected values assumed the old behavior.
    - gremlin-javascript's DotNetTranslateVisitor never unwrapped the
      StringArgumentVarargsContext node introduced for multi-label addV(),
      so generated .NET translations were missing the (string) cast that
      the Java translator already applies; also fixed a labeled-alternative
      method name mismatch that left visitTraversalSourceSpawnMethod_addV
      as dead code (never dispatched by the ANTLR visitor).
    
    Assisted-by: Claude Code:claude-sonnet-5
---
 .../gremlin/process/computer/util/ComputerGraph.java        |  5 +++++
 .../gremlin/process/traversal/step/map/ElementMapStep.java  |  9 ++++++++-
 .../lib/language/translator/DotNetTranslateVisitor.ts       | 13 ++++++++++++-
 .../tinkerpop/gremlin/test/features/map/ElementMap.feature  |  4 ++--
 4 files changed, 27 insertions(+), 4 deletions(-)

diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/util/ComputerGraph.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/util/ComputerGraph.java
index 5634cbbc09..1a302adaea 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/util/ComputerGraph.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/util/ComputerGraph.java
@@ -135,6 +135,11 @@ public final class ComputerGraph implements Graph {
             return this.element.label();
         }
 
+        @Override
+        public Set<String> labels() {
+            return this.element.labels();
+        }
+
         @Override
         public Graph graph() {
             return ComputerGraph.this;
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ElementMapStep.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ElementMapStep.java
index a9566032e5..9eb0e05a21 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ElementMapStep.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ElementMapStep.java
@@ -97,7 +97,14 @@ public class ElementMapStep<K,E> extends 
ScalarMapStep<Element, Map<K, E>> imple
         m.put(T.id, v.id());
 
         // can't add label if doing GraphComputer stuff as there is no access 
to the label of the adjacent vertex
-        if (!onGraphComputer) m.put(T.label, v.label());
+        if (!onGraphComputer) {
+            if (isMultilabelEnabled()) {
+                m.put(T.label, v.labels());
+            } else {
+                final String label = v.label();
+                if (!label.isEmpty()) m.put(T.label, label);
+            }
+        }
 
         return m;
     }
diff --git 
a/gremlin-js/gremlin-javascript/lib/language/translator/DotNetTranslateVisitor.ts
 
b/gremlin-js/gremlin-javascript/lib/language/translator/DotNetTranslateVisitor.ts
index 8955acc5f4..fc22d85a01 100644
--- 
a/gremlin-js/gremlin-javascript/lib/language/translator/DotNetTranslateVisitor.ts
+++ 
b/gremlin-js/gremlin-javascript/lib/language/translator/DotNetTranslateVisitor.ts
@@ -359,6 +359,14 @@ export default class DotNetTranslateVisitor extends 
TranslateVisitor {
         if (ctx?.variable() != null || ctx?.stringLiteral() != null) 
this.sb.push('(string) ');
     }
 
+    private visitStringArgumentVarargsWithCast(ctx: any): void {
+        for (let ix = 0; ix < ctx.getChildCount(); ix++) {
+            const child = ctx.getChild(ix);
+            if (child.constructor?.name === 'StringArgumentContext') 
this.tryAppendCastToString_StringArg(child);
+            this.visit(child);
+        }
+    }
+
     private tryAppendCastToString_StringNullableLit(ctx: any): void {
         if (ctx?.K_NULL != null && ctx.K_NULL() != null) 
this.sb.push('(string) ');
     }
@@ -421,11 +429,12 @@ export default class DotNetTranslateVisitor extends 
TranslateVisitor {
         this.sb.push(')');
     }
 
-    visitTraversalSourceSpawnMethod_addV(ctx: any): void {
+    visitTraversalSourceSpawnMethod_addV_String(ctx: any): void {
         this.sb.push(capitalize(ctx.getChild(0).getText()));
         for (let ix = 1; ix < ctx.getChildCount(); ix++) {
             const child = ctx.getChild(ix);
             if (child.constructor?.name === 'StringArgumentContext') 
this.tryAppendCastToString_StringArg(child);
+            else if (child.constructor?.name === 
'StringArgumentVarargsContext') { 
this.visitStringArgumentVarargsWithCast(child); continue; }
             this.visit(child);
         }
     }
@@ -610,6 +619,7 @@ export default class DotNetTranslateVisitor extends 
TranslateVisitor {
         for (let ix = 1; ix < ctx.getChildCount(); ix++) {
             const child = ctx.getChild(ix);
             if (child.constructor?.name === 'StringArgumentContext') 
this.tryAppendCastToString_StringArg(child);
+            else if (child.constructor?.name === 
'StringArgumentVarargsContext') { 
this.visitStringArgumentVarargsWithCast(child); continue; }
             this.visit(child);
         }
     }
@@ -619,6 +629,7 @@ export default class DotNetTranslateVisitor extends 
TranslateVisitor {
         for (let ix = 1; ix < ctx.getChildCount(); ix++) {
             const child = ctx.getChild(ix);
             if (child.constructor?.name === 'StringArgumentContext') 
this.tryAppendCastToString_StringArg(child);
+            else if (child.constructor?.name === 
'StringArgumentVarargsContext') { 
this.visitStringArgumentVarargsWithCast(child); continue; }
             this.visit(child);
         }
     }
diff --git 
a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/ElementMap.feature
 
b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/ElementMap.feature
index e5a746bf80..4cc80f1529 100644
--- 
a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/ElementMap.feature
+++ 
b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/ElementMap.feature
@@ -250,7 +250,7 @@ Feature: Step - elementMap()
     When iterated to list
     Then the result should be unordered
       | result |
-      | m[{"t[id]": "e[marko-knows->josh].id", "t[label]": "s[knows]", 
"weight": "d[0.5].d", "D[OUT]": "m[{\\"t[id]\\": \\"v[marko].id\\", 
\\"t[label]\\": \\"person\\"}]", "D[IN]": "m[{\\"t[id]\\": \\"v[josh].id\\", 
\\"t[label]\\": \\"person\\"}]"}] |
+      | m[{"t[id]": "e[marko-knows->josh].id", "t[label]": "s[knows]", 
"weight": "d[0.5].d", "D[OUT]": "m[{\\"t[id]\\": \\"v[marko].id\\", 
\\"t[label]\\": \\"s[person]\\"}]", "D[IN]": "m[{\\"t[id]\\": \\"v[josh].id\\", 
\\"t[label]\\": \\"s[person]\\"}]"}] |
 
   @GraphComputerVerificationReferenceOnly @MultiLabel @MultiLabelDefault
   Scenario: g_E_elementMap_multi_label_default
@@ -266,7 +266,7 @@ Feature: Step - elementMap()
     When iterated to list
     Then the result should be unordered
       | result |
-      | m[{"t[id]": "e[marko-knows->josh].id", "t[label]": "s[knows]", 
"weight": "d[0.5].d", "D[OUT]": "m[{\\"t[id]\\": \\"v[marko].id\\", 
\\"t[label]\\": \\"person\\"}]", "D[IN]": "m[{\\"t[id]\\": \\"v[josh].id\\", 
\\"t[label]\\": \\"person\\"}]"}] |
+      | m[{"t[id]": "e[marko-knows->josh].id", "t[label]": "s[knows]", 
"weight": "d[0.5].d", "D[OUT]": "m[{\\"t[id]\\": \\"v[marko].id\\", 
\\"t[label]\\": \\"s[person]\\"}]", "D[IN]": "m[{\\"t[id]\\": \\"v[josh].id\\", 
\\"t[label]\\": \\"s[person]\\"}]"}] |
 
   @GraphComputerVerificationReferenceOnly @MultiLabel @SingleLabelDefault
   Scenario: g_E_elementMap_single_label_default

Reply via email to