Skip to content

Commit d29b3d9

Browse files
authored
fix(NODE-4639): allow PromiseProvider to be null (#3412)
1 parent bdc0d67 commit d29b3d9

10 files changed

+45
-21
lines changed

src/bulk/common.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1346,13 +1346,13 @@ function handleEarlyError(
13461346
err?: AnyError,
13471347
callback?: Callback<BulkWriteResult>
13481348
): Promise<BulkWriteResult> | void {
1349-
const Promise = PromiseProvider.get();
13501349
if (typeof callback === 'function') {
13511350
callback(err);
13521351
return;
13531352
}
13541353

1355-
return Promise.reject(err);
1354+
const PromiseConstructor = PromiseProvider.get() ?? Promise;
1355+
return PromiseConstructor.reject(err);
13561356
}
13571357

13581358
function shouldForceServerObjectId(bulkOperation: BulkOperationBase): boolean {

src/connection_string.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -438,7 +438,9 @@ export function parseOptions(
438438

439439
checkTLSOptions(mongoOptions);
440440

441-
if (options.promiseLibrary) PromiseProvider.set(options.promiseLibrary);
441+
if (options.promiseLibrary) {
442+
PromiseProvider.set(options.promiseLibrary);
443+
}
442444

443445
const lbError = validateLoadBalancedOptions(hosts, mongoOptions, isSRV);
444446
if (lbError) {

src/mongo_client.ts

+8-4
Original file line numberDiff line numberDiff line change
@@ -593,8 +593,12 @@ export class MongoClient extends TypedEventEmitter<MongoClientEvents> {
593593
return mongoClient.connect();
594594
}
595595
} catch (error) {
596-
if (callback) return callback(error);
597-
else return PromiseProvider.get().reject(error);
596+
if (callback) {
597+
return callback(error);
598+
} else {
599+
const PromiseConstructor = PromiseProvider.get() ?? Promise;
600+
return PromiseConstructor.reject(error);
601+
}
598602
}
599603
}
600604

@@ -645,9 +649,9 @@ export class MongoClient extends TypedEventEmitter<MongoClientEvents> {
645649
}
646650

647651
const session = this.startSession(options);
648-
const Promise = PromiseProvider.get();
652+
const PromiseConstructor = PromiseProvider.get() ?? Promise;
649653

650-
return Promise.resolve()
654+
return PromiseConstructor.resolve()
651655
.then(() => withSessionCallback(session))
652656
.then(() => {
653657
// Do not return the result of callback

src/promise_provider.ts

+12-7
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@ import { MongoInvalidArgumentError } from './error';
44
const kPromise = Symbol('promise');
55

66
interface PromiseStore {
7-
[kPromise]?: PromiseConstructor;
7+
[kPromise]: PromiseConstructor | null;
88
}
99

1010
const store: PromiseStore = {
11-
[kPromise]: undefined
11+
[kPromise]: null
1212
};
1313

1414
/**
@@ -31,7 +31,14 @@ export class PromiseProvider {
3131
* Sets the promise library
3232
* @deprecated Setting a custom promise library is deprecated the next major version will use the global Promise constructor only.
3333
*/
34-
static set(lib: PromiseConstructor): void {
34+
static set(lib: PromiseConstructor | null): void {
35+
// eslint-disable-next-line no-restricted-syntax
36+
if (lib === null) {
37+
// Check explicitly against null since `.set()` (no args) should fall through to validate
38+
store[kPromise] = null;
39+
return;
40+
}
41+
3542
if (!PromiseProvider.validate(lib)) {
3643
// validate
3744
return;
@@ -43,9 +50,7 @@ export class PromiseProvider {
4350
* Get the stored promise library, or resolves passed in
4451
* @deprecated Setting a custom promise library is deprecated the next major version will use the global Promise constructor only.
4552
*/
46-
static get(): PromiseConstructor {
47-
return store[kPromise] as PromiseConstructor;
53+
static get(): PromiseConstructor | null {
54+
return store[kPromise];
4855
}
4956
}
50-
51-
PromiseProvider.set(global.Promise);

src/sessions.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -609,14 +609,14 @@ function attemptTransaction<TSchema>(
609609
fn: WithTransactionCallback<TSchema>,
610610
options?: TransactionOptions
611611
): Promise<any> {
612-
const Promise = PromiseProvider.get();
613612
session.startTransaction(options);
614613

615614
let promise;
616615
try {
617616
promise = fn(session);
618617
} catch (err) {
619-
promise = Promise.reject(err);
618+
const PromiseConstructor = PromiseProvider.get() ?? Promise;
619+
promise = PromiseConstructor.reject(err);
620620
}
621621

622622
if (!isPromiseLike(promise)) {

src/utils.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -448,10 +448,10 @@ export function maybePromise<T>(
448448
callback: Callback<T> | undefined,
449449
wrapper: (fn: Callback<T>) => void
450450
): Promise<T> | void {
451-
const Promise = PromiseProvider.get();
451+
const PromiseConstructor = PromiseProvider.get() ?? Promise;
452452
let result: Promise<T> | void;
453453
if (typeof callback !== 'function') {
454-
result = new Promise<any>((resolve, reject) => {
454+
result = new PromiseConstructor<any>((resolve, reject) => {
455455
callback = (err, res) => {
456456
if (err) return reject(err);
457457
resolve(res);

test/integration/node-specific/cursor_async_iterator.test.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ describe('Cursor Async Iterator Tests', function () {
109109

110110
afterEach(() => {
111111
promiseSpy.restore();
112-
PromiseProvider.set(Promise);
112+
PromiseProvider.set(null);
113113
return client.close();
114114
});
115115

test/integration/node-specific/custom_promise_library.test.js

+15
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,23 @@ class CustomPromise extends Promise {}
99
CustomPromise.prototype.isCustomMongo = true;
1010

1111
describe('Optional PromiseLibrary', function () {
12+
beforeEach(() => {
13+
PromiseProvider.set(null);
14+
});
15+
1216
afterEach(() => {
17+
PromiseProvider.set(null);
18+
});
19+
20+
it('should initially be set to null', () => {
21+
expect(PromiseProvider.get()).to.be.null;
22+
});
23+
24+
it('should allow passing null to .set() to clear the set promise', () => {
1325
PromiseProvider.set(Promise);
26+
expect(PromiseProvider.get()).to.equal(Promise);
27+
expect(() => PromiseProvider.set(null)).to.not.throw();
28+
expect(PromiseProvider.get()).to.be.null;
1429
});
1530

1631
it('should emit a deprecation warning when a promiseLibrary is set', async () => {

test/types/community/client.test-d.ts

-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ const options: MongoClientOptions = {
3535
promoteBuffers: false,
3636
authMechanism: 'SCRAM-SHA-1',
3737
forceServerObjectId: false,
38-
promiseLibrary: Promise,
3938
directConnection: false
4039
};
4140

test/unit/mongo_client.test.js

-1
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,6 @@ describe('MongoOptions', function () {
110110
return 'very unique';
111111
}
112112
},
113-
promiseLibrary: global.Promise,
114113
promoteBuffers: true,
115114
promoteLongs: false,
116115
promoteValues: false,

0 commit comments

Comments
 (0)