Skip to content

Commit 74f7f8a

Browse files
authored
feat(NODE-4769)!: remove ISO-8859-1 string support from Binary (#602)
1 parent c0086c9 commit 74f7f8a

5 files changed

+27
-63
lines changed

src/binary.ts

+16-49
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { isUint8Array } from './parser/utils';
1+
import { isAnyArrayBuffer, isUint8Array } from './parser/utils';
22
import type { EJSONOptions } from './extended_json';
33
import { BSONError } from './error';
44
import { BSON_BINARY_SUBTYPE_UUID_NEW } from './constants';
@@ -65,27 +65,19 @@ export class Binary extends BSONValue {
6565

6666
/**
6767
* Create a new Binary instance.
68-
*
69-
* This constructor can accept a string as its first argument. In this case,
70-
* this string will be encoded using ISO-8859-1, **not** using UTF-8.
71-
* This is almost certainly not what you want. Use `new Binary(Buffer.from(string))`
72-
* instead to convert the string to a Buffer using UTF-8 first.
73-
*
7468
* @param buffer - a buffer object containing the binary data.
7569
* @param subType - the option binary type.
7670
*/
77-
constructor(buffer?: string | BinarySequence, subType?: number) {
71+
constructor(buffer?: BinarySequence, subType?: number) {
7872
super();
7973
if (
8074
!(buffer == null) &&
81-
!(typeof buffer === 'string') &&
75+
typeof buffer === 'string' &&
8276
!ArrayBuffer.isView(buffer) &&
83-
!(buffer instanceof ArrayBuffer) &&
77+
!isAnyArrayBuffer(buffer) &&
8478
!Array.isArray(buffer)
8579
) {
86-
throw new BSONError(
87-
'Binary can only be constructed from string, Buffer, TypedArray, or Array<number>'
88-
);
80+
throw new BSONError('Binary can only be constructed from Uint8Array or number[]');
8981
}
9082

9183
this.sub_type = subType ?? Binary.BSON_BINARY_SUBTYPE_DEFAULT;
@@ -95,17 +87,9 @@ export class Binary extends BSONValue {
9587
this.buffer = ByteUtils.allocate(Binary.BUFFER_SIZE);
9688
this.position = 0;
9789
} else {
98-
if (typeof buffer === 'string') {
99-
// string
100-
this.buffer = ByteUtils.fromISO88591(buffer);
101-
} else if (Array.isArray(buffer)) {
102-
// number[]
103-
this.buffer = ByteUtils.fromNumberArray(buffer);
104-
} else {
105-
// Buffer | TypedArray | ArrayBuffer
106-
this.buffer = ByteUtils.toLocalBufferType(buffer);
107-
}
108-
90+
this.buffer = Array.isArray(buffer)
91+
? ByteUtils.fromNumberArray(buffer)
92+
: ByteUtils.toLocalBufferType(buffer);
10993
this.position = this.buffer.byteLength;
11094
}
11195
}
@@ -147,12 +131,12 @@ export class Binary extends BSONValue {
147131
}
148132

149133
/**
150-
* Writes a buffer or string to the binary.
134+
* Writes a buffer to the binary.
151135
*
152136
* @param sequence - a string or buffer to be written to the Binary BSON object.
153137
* @param offset - specify the binary of where to write the content.
154138
*/
155-
write(sequence: string | BinarySequence, offset: number): void {
139+
write(sequence: BinarySequence, offset: number): void {
156140
offset = typeof offset === 'number' ? offset : this.position;
157141

158142
// If the buffer is to small let's extend the buffer
@@ -169,10 +153,7 @@ export class Binary extends BSONValue {
169153
this.position =
170154
offset + sequence.byteLength > this.position ? offset + sequence.length : this.position;
171155
} else if (typeof sequence === 'string') {
172-
const bytes = ByteUtils.fromISO88591(sequence);
173-
this.buffer.set(bytes, offset);
174-
this.position =
175-
offset + sequence.length > this.position ? offset + sequence.length : this.position;
156+
throw new BSONError('input cannot be string');
176157
}
177158
}
178159

@@ -189,26 +170,12 @@ export class Binary extends BSONValue {
189170
return this.buffer.slice(position, position + length);
190171
}
191172

192-
/**
193-
* Returns the value of this binary as a string.
194-
* @param asRaw - Will skip converting to a string
195-
* @remarks
196-
* This is handy when calling this function conditionally for some key value pairs and not others
197-
*/
198-
value(asRaw?: boolean): string | BinarySequence {
199-
asRaw = !!asRaw;
200-
173+
/** returns a view of the binary value as a Uint8Array */
174+
value(): Uint8Array {
201175
// Optimize to serialize for the situation where the data == size of buffer
202-
if (asRaw && this.buffer.length === this.position) {
203-
return this.buffer;
204-
}
205-
206-
// If it's a node.js buffer object
207-
if (asRaw) {
208-
return this.buffer.slice(0, this.position);
209-
}
210-
// TODO(NODE-4361): remove binary string support, value(true) should be the default / only option here.
211-
return ByteUtils.toISO88591(this.buffer.subarray(0, this.position));
176+
return this.buffer.length === this.position
177+
? this.buffer
178+
: this.buffer.subarray(0, this.position);
212179
}
213180

214181
/** the length of the binary sequence */

test/node/bson_node_only_tests.js

+5-7
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ const Buffer = require('buffer').Buffer;
99

1010
describe('BSON - Node only', function () {
1111
it('Should Correctly Serialize and Deserialize a big Binary object', function (done) {
12-
var data = fs.readFileSync(path.resolve(__dirname, './data/test_gs_weird_bug.png'), 'binary');
12+
var data = fs.readFileSync(path.resolve(__dirname, './data/test_gs_weird_bug.png'));
1313
var bin = new Binary();
1414
bin.write(data);
1515
var doc = { doc: bin };
@@ -26,18 +26,17 @@ describe('BSON - Node only', function () {
2626
});
2727

2828
describe('Full BSON - Node only', function () {
29-
it('Should Correctly Serialize and Deserialize a big Binary object', function (done) {
30-
var data = fs.readFileSync(path.resolve(__dirname, './data/test_gs_weird_bug.png'), 'binary');
29+
it('Should Correctly Serialize and Deserialize a big Binary object', function () {
30+
var data = fs.readFileSync(path.resolve(__dirname, './data/test_gs_weird_bug.png'));
3131
var bin = new Binary();
3232
bin.write(data);
3333
var doc = { doc: bin };
3434
var serialized_data = BSON.serialize(doc);
3535
var deserialized_data = BSON.deserialize(serialized_data);
36-
expect(doc.doc.value()).to.equal(deserialized_data.doc.value());
37-
done();
36+
expect(doc.doc.value()).to.deep.equal(deserialized_data.doc.value());
3837
});
3938

40-
it('Should Correctly Deserialize bson file from mongodump', function (done) {
39+
it('Should Correctly Deserialize bson file from mongodump', function () {
4140
var data = fs.readFileSync(path.resolve(__dirname, './data/test.bson'), { encoding: null });
4241
data = Buffer.from(data);
4342
var docs = [];
@@ -46,6 +45,5 @@ describe('Full BSON - Node only', function () {
4645
bsonIndex = BSON.deserializeStream(data, bsonIndex, 1, docs, docs.length, { isArray: true });
4746

4847
expect(docs.length).to.equal(1);
49-
done();
5048
});
5149
});

test/node/bson_types_construction_tests.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ describe('Constructing BSON types', function () {
66
expect(() => new BSON.ObjectId()).to.not.throw();
77
expect(() => new BSON.BSONRegExp('aaa')).to.not.throw();
88
expect(() => new BSON.BSONSymbol('aaa')).to.not.throw();
9-
expect(() => new BSON.Binary('aaa')).to.not.throw();
9+
expect(() => new BSON.Binary(new Uint8Array())).to.not.throw();
1010
expect(() => new BSON.Code(function () {})).to.not.throw();
1111
expect(() => new BSON.Decimal128('123')).to.not.throw();
1212
expect(() => new BSON.Double(2.3)).to.not.throw();

test/node/extended_json.test.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ describe('Extended JSON', function () {
184184

185185
it('should serialize from BSON object to EJSON object', function () {
186186
const doc = {
187-
binary: new Binary(''),
187+
binary: new Binary(new Uint8Array([0, 0, 0]), 0xef),
188188
code: new Code('function() {}'),
189189
dbRef: new DBRef('tests', new Int32(1), 'test'),
190190
decimal128: new Decimal128('128'),
@@ -203,7 +203,7 @@ describe('Extended JSON', function () {
203203

204204
const result = EJSON.serialize(doc, { relaxed: false });
205205
expect(result).to.deep.equal({
206-
binary: { $binary: { base64: '', subType: '00' } },
206+
binary: { $binary: { base64: 'AAAA', subType: 'ef' } },
207207
code: { $code: 'function() {}' },
208208
dbRef: { $ref: 'tests', $id: { $numberInt: '1' }, $db: 'test' },
209209
decimal128: { $numberDecimal: '128' },

test/node/test_full_bson.js

+3-4
Original file line numberDiff line numberDiff line change
@@ -260,17 +260,16 @@ describe('Full BSON', function () {
260260
/**
261261
* @ignore
262262
*/
263-
it('Should Correctly Serialize and Deserialize a Binary object', function (done) {
263+
it('Should Correctly Serialize and Deserialize a Binary object', function () {
264264
var bin = new Binary();
265265
var string = 'binstring';
266266
for (var index = 0; index < string.length; index++) {
267-
bin.put(string.charAt(index));
267+
bin.put(string[index]);
268268
}
269269
var doc = { doc: bin };
270270
var serialized_data = BSON.serialize(doc);
271271
var deserialized_data = BSON.deserialize(serialized_data);
272-
expect(doc.doc.value()).to.equal(deserialized_data.doc.value());
273-
done();
272+
expect(doc.doc.value()).to.deep.equal(deserialized_data.doc.value());
274273
});
275274

276275
it('Should Correctly Serialize and Deserialize a ArrayBuffer object', function () {

0 commit comments

Comments
 (0)