Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 18 additions & 8 deletions handwritten/spanner/src/partial-result-stream.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,22 @@
toJSON(options?: JSONOptions): Json;
}

/**
* Row implementation extending Array to provide a shared, non-enumerable
* toJSON method without per-row closures or Object.setPrototypeOf overhead.
*/
class RowImpl extends Array<Field> implements Row {
toJSON(options?: JSONOptions): Json {
return codec.convertFieldsToJson(this, options);
}
}
Object.defineProperty(RowImpl.prototype, 'constructor', {
value: Array,
writable: true,
configurable: true,
enumerable: false,
});
Comment thread
olavloite marked this conversation as resolved.

/**
* @callback PartialResultStream~rowCallback
* @param {Row|object} row The row data.
Expand Down Expand Up @@ -249,7 +265,7 @@
this._options.columnsMetadata,
name,
)
? (this._options.columnsMetadata as any)[name]

Check warning on line 268 in handwritten/spanner/src/partial-result-stream.ts

View workflow job for this annotation

GitHub Actions / lint

Unexpected any. Specify a different type
: undefined;
if (codec.decode !== originalDecode) {
return val =>
Expand Down Expand Up @@ -458,7 +474,7 @@
*/
private _createRow(values: Value[]): Row {
const len = values.length;
const fields = new Array(len);
const fields = new RowImpl(len);
Comment thread
olavloite marked this conversation as resolved.
const decoders = this._decoders;
const classFields = this._fields;

Expand All @@ -469,13 +485,7 @@
};
}

Object.defineProperty(fields, 'toJSON', {
value: (options?: JSONOptions): Json => {
return codec.convertFieldsToJson(fields, options);
},
});

return fields as Row;
return fields;
Comment thread
olavloite marked this conversation as resolved.
}
/**
* Attempts to merge chunked values together.
Expand Down
39 changes: 39 additions & 0 deletions handwritten/spanner/test/partial-result-stream.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
import {grpc} from 'google-gax';
import {Row} from '../src/partial-result-stream';

function toRawValue(value: any): any {

Check warning on line 33 in handwritten/spanner/test/partial-result-stream.ts

View workflow job for this annotation

GitHub Actions / lint

Unexpected any. Specify a different type

Check warning on line 33 in handwritten/spanner/test/partial-result-stream.ts

View workflow job for this annotation

GitHub Actions / lint

Unexpected any. Specify a different type
if (value === null || value === undefined) {
return null;
}
Expand All @@ -44,7 +44,7 @@
return value.toISOString();
}
if (value instanceof codec.Struct) {
return Array.from(value).map((field: any) => toRawValue(field.value));

Check warning on line 47 in handwritten/spanner/test/partial-result-stream.ts

View workflow job for this annotation

GitHub Actions / lint

Unexpected any. Specify a different type
}
if (value instanceof codec.Int) {
return value.value;
Expand Down Expand Up @@ -200,6 +200,45 @@
stream.write(RESULT);
});

it('should create rows with shared prototype and non-enumerable toJSON', done => {
const rows: prs.Row[] = [];
stream.on('error', done).on('data', row => {
rows.push(row);
if (rows.length === 2) {
try {
const [row1, row2] = rows;
assert.strictEqual(Array.isArray(row1), true);
assert.strictEqual(row1 instanceof Array, true);
assert.strictEqual(row1.constructor, Array);
assert.strictEqual(Array.isArray(row2), true);
assert.strictEqual(row2 instanceof Array, true);
assert.strictEqual(row2.constructor, Array);

// toJSON must be non-enumerable
assert.strictEqual(Object.keys(row1).includes('toJSON'), false);
assert.strictEqual(
Object.prototype.propertyIsEnumerable.call(row1, 'toJSON'),
false,
);

// toJSON must be shared on the prototype, not created as a per-row closure
Comment thread
olavloite marked this conversation as resolved.
assert.strictEqual(row1.toJSON, row2.toJSON);

// toJSON should correctly serialize the row
const json1 = row1.toJSON();
const expectedJson = codec.convertFieldsToJson(row1);
assert.deepStrictEqual(json1, expectedJson);
done();
} catch (error) {
done(error);
}
}
});

stream.write(RESULT);
stream.write({values: [convertToIValue(VALUE)]});
});

it('should emit rows as JSON', done => {
const jsonOptions = {};
const stream = new PartialResultStream({json: true, jsonOptions});
Expand Down Expand Up @@ -411,8 +450,8 @@
],
};

const jsonRows: any[] = [];

Check warning on line 453 in handwritten/spanner/test/partial-result-stream.ts

View workflow job for this annotation

GitHub Actions / lint

Unexpected any. Specify a different type
const standardRows: any[] = [];

Check warning on line 454 in handwritten/spanner/test/partial-result-stream.ts

View workflow job for this annotation

GitHub Actions / lint

Unexpected any. Specify a different type

let jsonDone = false;
let standardDone = false;
Expand Down Expand Up @@ -469,7 +508,7 @@
describe('Multiple metadata chunks', () => {
it('should respect the first metadata chunk and ignore subsequent ones', done => {
const stream = new PartialResultStream({json: true});
const rows: any[] = [];

Check warning on line 511 in handwritten/spanner/test/partial-result-stream.ts

View workflow job for this annotation

GitHub Actions / lint

Unexpected any. Specify a different type

stream
.on('error', done)
Expand Down Expand Up @@ -539,7 +578,7 @@
// Pause the stream initially to force buffering
stream.pause();

const rows: any[] = [];

Check warning on line 581 in handwritten/spanner/test/partial-result-stream.ts

View workflow job for this annotation

GitHub Actions / lint

Unexpected any. Specify a different type
stream.on('data', row => rows.push(row));
stream.on('end', () => {
try {
Expand Down Expand Up @@ -1024,7 +1063,7 @@

const receivedRows: Row[] = [];
partialResultStream(requestFnStub)
.on('data', (row: any) => receivedRows.push(row))

Check warning on line 1066 in handwritten/spanner/test/partial-result-stream.ts

View workflow job for this annotation

GitHub Actions / lint

Unexpected any. Specify a different type
.on('error', done)
.on('end', () => {
try {
Expand Down
Loading