Skip to content

Replace Bytecode with GremlinLang in JavaScript GLV#3307

Open
kirill-stepanishin wants to merge 1 commit intoapache:masterfrom
kirill-stepanishin:bytecode-to-gremlinlang-js
Open

Replace Bytecode with GremlinLang in JavaScript GLV#3307
kirill-stepanishin wants to merge 1 commit intoapache:masterfrom
kirill-stepanishin:bytecode-to-gremlinlang-js

Conversation

@kirill-stepanishin
Copy link
Contributor

As part of the TP4 migration, the server no longer accepts Bytecode and only processes Gremlin queries in script form.. This PR replaces Bytecode + Translator with a new GremlinLang class.

Changes

  • New GremlinLang class that incrementally builds Gremlin query strings as steps are added
  • GraphTraversalSource / GraphTraversal now accumulate into GremlinLang instead of Bytecode
  • Client.submit() only accepts strings now; all queries sent as gremlin-lang language. OptionsStrategy extracted into RequestOptions (timeout, batchSize, bulkResults, etc.)
  • Deleted Bytecode, Translator, BytecodeSerializer, and their tests
  • Removed Bytecode serializers from both GraphSON and GraphBinary layers

Intentionally out of scope for this PR

  • UUID — no UUID("...") wrapper; UUIDs fall through to String(arg)
  • Numeric type suffixes (1B, 2S, 4L, 5.0F, 6.0D, etc.)

@codecov-commenter
Copy link

codecov-commenter commented Feb 13, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 75.80%. Comparing base (cfd6889) to head (f452656).
⚠️ Report is 774 commits behind head on master.

Additional details and impacted files
@@             Coverage Diff              @@
##             master    #3307      +/-   ##
============================================
- Coverage     77.87%   75.80%   -2.07%     
+ Complexity    13578    13271     -307     
============================================
  Files          1015     1020       +5     
  Lines         59308    59864     +556     
  Branches       6835     7034     +199     
============================================
- Hits          46184    45379     -805     
- Misses        10817    11815     +998     
- Partials       2307     2670     +363     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Contributor

@Cole-Greer Cole-Greer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall I think this looks really good. Most of my comments are just for context and not anything which needs action in this PR, the rest are all for minor clarifications and tweaks.

'materializeProperties',
'bulkResults',
];
for (const strategy of strategies) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I expect all of the strategy handling here will need to be adjusted in the future. I think this is good enough for now and we can revisit this as we get more pieces of the driver functioning and get more tests running.

return this.withStrategies(new OptionsStrategy({ [key]: val }));
}
optionsStrategy[1].configuration[key] = val;
glStrategies[glStrategies.length - 1].configuration[key] = val;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've got some questions around how OptionsStrategy needs to work as all the pieces of this driver come together. What you have here looks about right for now. It will become easier to reason about if any adjustments are needed here once more of the driver is complete.

if (arg === null || arg === undefined) return 'null';
if (typeof arg === 'boolean') return arg ? 'true' : 'false';
if (arg instanceof Long) {
return String(arg.value);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should probably append an L suffix on longs.

return String(arg.value);
}
if (arg instanceof Date) {
const iso = arg.toISOString().replace('.000Z', 'Z');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was this added to be more consistent with Java, Python, and Go? I think it's ok to save a step here and keep .000Z as both are equivalent. Not sure if anyone has other opinions on this.

return String(arg);
}
if (typeof arg === 'string') {
const escaped = JSON.stringify(arg).slice(1, -1).replace(/'/g, "\\'");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not understanding what the JSON.stringify() and slice() are doing here. Could we just do a replace() directly on arg itself?

// #91
[g.withStrategies(new SubgraphStrategy({vertices: __.has('region','US-TX'), vertexProperties: __.hasNot('runways')})).V().count(), "g.withStrategies(new SubgraphStrategy(vertices:__.has('region','US-TX'),vertexProperties:__.hasNot('runways'))).V().count()"],
// #92
[g.withStrategies(new ReadOnlyStrategy(), new SubgraphStrategy({vertices: __.has('region','US-TX'), edges: __.hasLabel('route')})).V().count(), "g.withStrategies(ReadOnlyStrategy,new SubgraphStrategy(vertices:__.has('region','US-TX'),edges:__.hasLabel('route'))).V().count()"],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm noticing the new keyword is only used in the GremlinLang if the strategy has arguments (ReadOnlyStrategy does not use new in this case, but SubgraphStrategy does). That appears to be consistent with Java but it is odd. I think that's fine for now but might be worth a revisit later.


describe('JS-specific tests', function () {
it('should handle Long values', function () {
assert.strictEqual(g.V(new Long('9007199254740993')).getGremlinLang().getGremlin(), 'g.V(9007199254740993)');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should result in 'g.V(9007199254740993L)'

assert.strictEqual(bytecode.stepInstructions[2][2].elementName, 'desc');
});

it('should add steps with Direction aliases from_ and to properly mapped to OUT and IN', function () {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think these test cases are still valuable, although they should just assert the final GremlinLang string matches the expected result instead of all of these assertions for the bytecode. The first 2 and final cases all appear to be adequately covered by gremlin-lang-test already, but this case is not. Could you restore the test here or add this case to gremlin-lang-test?

assert.strictEqual(vStartBytecode.stepInstructions[0][2], 2); // ID should be extracted from Vertex

// Test V() step in the middle of a traversal
const vMid = g.inject('foo').V(1, new Vertex(2, 'person'));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar to my above comment, I don't see an equivalent mid-traversal V() case in gremlin-lang-test

assert.strictEqual(fromToBytecode.stepInstructions[2][0], 'to');
assert.strictEqual(fromToBytecode.stepInstructions[2][1], 2); // ID should be extracted from Vertex
});
it('should extract ID from Vertex objects for mergeE()', function () {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar to above, I don't see an equivalent for this in gremlin-lang-test.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants