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

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

commit cf356c9b66a1ba0d3af605abb97a797e342b46f9
Author: Cole Greer <[email protected]>
AuthorDate: Tue Jun 9 15:36:52 2026 -0700

    Add parameterize GValue feature-test variant to the JavaScript GLV
    
    Wires a PARAMETERIZE=true cucumber variant that wraps each non-g parameter 
in a GValue (matching the Python reference), and fixes the features-*-docker 
npm scripts to target the actual mounted corpus path (/gremlin-test) instead of 
the nonexistent ../gremlin-test, which had made the docker feature run pass 
vacuously.
    
    Also fixes GremlinLang._argAsString to merge a child/anonymous traversal's 
parameters into the parent so GValue bindings nested inside child traversals 
are sent to the server, resolving 'No variable found for <name>' errors. Adds 
unit coverage for the nested-binding merge.
    
    Assisted-by: Kiro:claude-opus-4.8
---
 gremlin-js/gremlin-javascript/lib/process/gremlin-lang.ts |  9 ++++++++-
 gremlin-js/gremlin-javascript/package.json                |  8 +++++---
 .../gremlin-javascript/test/cucumber/feature-steps.js     |  7 +++++++
 .../gremlin-javascript/test/unit/gremlin-lang-test.js     | 15 +++++++++++++++
 4 files changed, 35 insertions(+), 4 deletions(-)

diff --git a/gremlin-js/gremlin-javascript/lib/process/gremlin-lang.ts 
b/gremlin-js/gremlin-javascript/lib/process/gremlin-lang.ts
index 2c085a2c31..94542b2121 100644
--- a/gremlin-js/gremlin-javascript/lib/process/gremlin-lang.ts
+++ b/gremlin-js/gremlin-javascript/lib/process/gremlin-lang.ts
@@ -145,6 +145,9 @@ export default class GremlinLang {
       return this._argAsString(arg.id);
     }
     if (arg instanceof GremlinLang) {
+      // Merge the child's parameters so GValue bindings nested inside a child
+      // traversal are still sent to the server alongside the rendered query.
+      arg.parameters.forEach((v, k) => this.parameters.set(k, v));
       return arg.getGremlin('__');
     }
     if (typeof arg.getGremlinLang === 'function') {
@@ -152,7 +155,11 @@ export default class GremlinLang {
       if (arg.graph != null) {
         throw new Error('Child traversal must be anonymous - use __ not g');
       }
-      return arg.getGremlinLang().getGremlin('__');
+      const childLang = arg.getGremlinLang();
+      // Merge the child's parameters so GValue bindings nested inside a child
+      // traversal are still sent to the server alongside the rendered query.
+      childLang.parameters.forEach((v: any, k: string) => 
this.parameters.set(k, v));
+      return childLang.getGremlin('__');
     }
     if (arg instanceof Uint8Array) {
       return `Binary("${Buffer.from(arg.buffer, arg.byteOffset, 
arg.byteLength).toString('base64')}")`;
diff --git a/gremlin-js/gremlin-javascript/package.json 
b/gremlin-js/gremlin-javascript/package.json
index 5ec1746c92..6de05ae683 100644
--- a/gremlin-js/gremlin-javascript/package.json
+++ b/gremlin-js/gremlin-javascript/package.json
@@ -91,10 +91,12 @@
     "integration-test": "npm run integration-test-graphbinary",
     "integration-test-graphbinary": "cross-env 
TS_NODE_PROJECT='tsconfig.test.json' 
CLIENT_MIMETYPE='application/vnd.graphbinary-v4.0' mocha test/integration -t 
5000",
     "TODO": "# test other mime types like graphbinary stringd",
-    "features": "npm run features-graphbinary",
+    "features": "npm run features-graphbinary && npm run 
features-graphbinary-params",
     "features-graphbinary": "cross-env NODE_OPTIONS='--loader ts-node/esm' 
TS_NODE_PROJECT='tsconfig.test.json' 
CLIENT_MIMETYPE='application/vnd.graphbinary-v4.0' cucumber-js --tags \"not 
@DataBigDecimal and not @DataBigInt and not @DataUUID and not @DataLong and not 
@StepWrite\" --import test/cucumber 
../../gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/",
-    "features-docker": "npm run features-graphbinary-docker",
-    "features-graphbinary-docker": "cross-env NODE_OPTIONS='--loader 
ts-node/esm' TS_NODE_PROJECT='tsconfig.test.json' 
CLIENT_MIMETYPE='application/vnd.graphbinary-v4.0' cucumber-js --tags \"not 
@DataBigDecimal and not @DataBigInt and not @DataUUID and not @DataLong and not 
@StepWrite\" --import test/cucumber ../gremlin-test/",
+    "features-graphbinary-params": "cross-env NODE_OPTIONS='--loader 
ts-node/esm' TS_NODE_PROJECT='tsconfig.test.json' 
CLIENT_MIMETYPE='application/vnd.graphbinary-v4.0' PARAMETERIZE=true 
cucumber-js --tags \"not @DataBigDecimal and not @DataBigInt and not @DataUUID 
and not @DataLong and not @StepWrite\" --import test/cucumber 
../../gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/",
+    "features-docker": "npm run features-graphbinary-docker && npm run 
features-graphbinary-params-docker",
+    "features-graphbinary-docker": "cross-env NODE_OPTIONS='--loader 
ts-node/esm' TS_NODE_PROJECT='tsconfig.test.json' 
CLIENT_MIMETYPE='application/vnd.graphbinary-v4.0' cucumber-js --tags \"not 
@DataBigDecimal and not @DataBigInt and not @DataUUID and not @DataLong and not 
@StepWrite\" --import test/cucumber /gremlin-test/",
+    "features-graphbinary-params-docker": "cross-env NODE_OPTIONS='--loader 
ts-node/esm' TS_NODE_PROJECT='tsconfig.test.json' 
CLIENT_MIMETYPE='application/vnd.graphbinary-v4.0' PARAMETERIZE=true 
cucumber-js --tags \"not @DataBigDecimal and not @DataBigInt and not @DataUUID 
and not @DataLong and not @StepWrite\" --import test/cucumber /gremlin-test/",
     "lint": "eslint --ext .js .",
     "doc": "typedoc --out doc --readme README.md --entryPointStrategy expand 
--entryPoints 'lib/**/*.ts' --tsconfig tsconfig.json --exclude 
'lib/language/grammar/**'"
   },
diff --git a/gremlin-js/gremlin-javascript/test/cucumber/feature-steps.js 
b/gremlin-js/gremlin-javascript/test/cucumber/feature-steps.js
index 08830a407e..4010dee697 100644
--- a/gremlin-js/gremlin-javascript/test/cucumber/feature-steps.js
+++ b/gremlin-js/gremlin-javascript/test/cucumber/feature-steps.js
@@ -33,8 +33,10 @@ import { Path, Vertex, Edge, Property } from 
'../../lib/structure/graph.js';
 import { statics } from '../../lib/process/graph-traversal.js';
 import { t, P, direction, merge, barrier, cardinality, column, order, TextP, 
IO, pick, pop, scope, operator, withOptions } from 
'../../lib/process/traversal.js';
 import { toLong } from '../../lib/utils.js';
+import { GValue } from '../../lib/process/gvalue.js';
 import anon from '../../lib/process/anonymous-traversal.js';
 const __ = statics;
+const parameterize = process.env.PARAMETERIZE === 'true';
 import { deepMembersById } from './element-comparison.js';
 import { Buffer } from 'buffer';
 import GremlinLang from "../../lib/process/gremlin-lang.js";
@@ -141,6 +143,11 @@ Given('an unsupported test', () => {});
 
 Given('the traversal of', function (traversalText) {
   const p = Object.assign({}, this.parameters);
+  if (parameterize) {
+    for (const k of Object.keys(p)) {
+      p[k] = new GValue(k, p[k]);
+    }
+  }
   p.g = this.g;
   this.traversal = gremlin[this.scenario].shift()(p);
   const sideEffectLang = new GremlinLang();
diff --git a/gremlin-js/gremlin-javascript/test/unit/gremlin-lang-test.js 
b/gremlin-js/gremlin-javascript/test/unit/gremlin-lang-test.js
index abb86a1740..a983b64d03 100644
--- a/gremlin-js/gremlin-javascript/test/unit/gremlin-lang-test.js
+++ b/gremlin-js/gremlin-javascript/test/unit/gremlin-lang-test.js
@@ -711,6 +711,21 @@ describe('GremlinLang', function () {
       assert.deepStrictEqual(gl.getParameters().get('ids'), [1, 2, 3]);
     });
 
+    it('should merge bindings from a GValue nested in a child traversal', 
function () {
+      const traversal = g.V().where(__.is(new GValue('xx1', 1)));
+      const gl = traversal.getGremlinLang();
+      assert.strictEqual(gl.getGremlin(), 'g.V().where(__.is(xx1))');
+      assert.deepStrictEqual(gl.getParameters().get('xx1'), 1);
+    });
+
+    it('should merge bindings from GValues nested across multiple child 
traversals', function () {
+      const traversal = g.union(__.V(new GValue('vid1', 1)), __.V(new 
GValue('vid4', 4))).values('name');
+      const gl = traversal.getGremlinLang();
+      assert.strictEqual(gl.getGremlin(), 
"g.union(__.V(vid1),__.V(vid4)).values('name')");
+      assert.deepStrictEqual(gl.getParameters().get('vid1'), 1);
+      assert.deepStrictEqual(gl.getParameters().get('vid4'), 4);
+    });
+
     it('should reject non-string name', function () {
       assert.throws(() => new GValue(123, 'v'), /Invalid GValue name/);
       assert.throws(() => new GValue(null, 'v'), /Invalid GValue name/);

Reply via email to