Skip to content

fix(NODE-4639): allow PromiseProvider to be null #3412

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 15, 2022
Merged
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
4 changes: 2 additions & 2 deletions src/bulk/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1346,13 +1346,13 @@ function handleEarlyError(
err?: AnyError,
callback?: Callback<BulkWriteResult>
): Promise<BulkWriteResult> | void {
const Promise = PromiseProvider.get();
if (typeof callback === 'function') {
callback(err);
return;
}

return Promise.reject(err);
const PromiseConstructor = PromiseProvider.get() ?? Promise;
return PromiseConstructor.reject(err);
}

function shouldForceServerObjectId(bulkOperation: BulkOperationBase): boolean {
Expand Down
4 changes: 3 additions & 1 deletion src/connection_string.ts
Original file line number Diff line number Diff line change
Expand Up @@ -438,7 +438,9 @@ export function parseOptions(

checkTLSOptions(mongoOptions);

if (options.promiseLibrary) PromiseProvider.set(options.promiseLibrary);
if (options.promiseLibrary) {
PromiseProvider.set(options.promiseLibrary);
}

const lbError = validateLoadBalancedOptions(hosts, mongoOptions, isSRV);
if (lbError) {
Expand Down
12 changes: 8 additions & 4 deletions src/mongo_client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -593,8 +593,12 @@ export class MongoClient extends TypedEventEmitter<MongoClientEvents> {
return mongoClient.connect();
}
} catch (error) {
if (callback) return callback(error);
else return PromiseProvider.get().reject(error);
if (callback) {
return callback(error);
} else {
const PromiseConstructor = PromiseProvider.get() ?? Promise;
return PromiseConstructor.reject(error);
}
}
}

Expand Down Expand Up @@ -645,9 +649,9 @@ export class MongoClient extends TypedEventEmitter<MongoClientEvents> {
}

const session = this.startSession(options);
const Promise = PromiseProvider.get();
const PromiseConstructor = PromiseProvider.get() ?? Promise;

return Promise.resolve()
return PromiseConstructor.resolve()
.then(() => withSessionCallback(session))
.then(() => {
// Do not return the result of callback
Expand Down
19 changes: 12 additions & 7 deletions src/promise_provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ import { MongoInvalidArgumentError } from './error';
const kPromise = Symbol('promise');

interface PromiseStore {
[kPromise]?: PromiseConstructor;
[kPromise]: PromiseConstructor | null;
}

const store: PromiseStore = {
[kPromise]: undefined
[kPromise]: null
};

/**
Expand All @@ -31,7 +31,14 @@ export class PromiseProvider {
* Sets the promise library
* @deprecated Setting a custom promise library is deprecated the next major version will use the global Promise constructor only.
*/
static set(lib: PromiseConstructor): void {
static set(lib: PromiseConstructor | null): void {
// eslint-disable-next-line no-restricted-syntax
if (lib === null) {
// Check explicitly against null since `.set()` (no args) should fall through to validate
store[kPromise] = null;
return;
}

if (!PromiseProvider.validate(lib)) {
// validate
return;
Expand All @@ -43,9 +50,7 @@ export class PromiseProvider {
* Get the stored promise library, or resolves passed in
* @deprecated Setting a custom promise library is deprecated the next major version will use the global Promise constructor only.
*/
static get(): PromiseConstructor {
return store[kPromise] as PromiseConstructor;
static get(): PromiseConstructor | null {
return store[kPromise];
}
}

PromiseProvider.set(global.Promise);
4 changes: 2 additions & 2 deletions src/sessions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -609,14 +609,14 @@ function attemptTransaction<TSchema>(
fn: WithTransactionCallback<TSchema>,
options?: TransactionOptions
): Promise<any> {
const Promise = PromiseProvider.get();
session.startTransaction(options);

let promise;
try {
promise = fn(session);
} catch (err) {
promise = Promise.reject(err);
const PromiseConstructor = PromiseProvider.get() ?? Promise;
promise = PromiseConstructor.reject(err);
}

if (!isPromiseLike(promise)) {
Expand Down
4 changes: 2 additions & 2 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -448,10 +448,10 @@ export function maybePromise<T>(
callback: Callback<T> | undefined,
wrapper: (fn: Callback<T>) => void
): Promise<T> | void {
const Promise = PromiseProvider.get();
const PromiseConstructor = PromiseProvider.get() ?? Promise;
let result: Promise<T> | void;
if (typeof callback !== 'function') {
result = new Promise<any>((resolve, reject) => {
result = new PromiseConstructor<any>((resolve, reject) => {
callback = (err, res) => {
if (err) return reject(err);
resolve(res);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ describe('Cursor Async Iterator Tests', function () {

afterEach(() => {
promiseSpy.restore();
PromiseProvider.set(Promise);
PromiseProvider.set(null);
return client.close();
});

Expand Down
15 changes: 15 additions & 0 deletions test/integration/node-specific/custom_promise_library.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,23 @@ class CustomPromise extends Promise {}
CustomPromise.prototype.isCustomMongo = true;

describe('Optional PromiseLibrary', function () {
beforeEach(() => {
PromiseProvider.set(null);
});

afterEach(() => {
PromiseProvider.set(null);
});

it('should initially be set to null', () => {
expect(PromiseProvider.get()).to.be.null;
});

it('should allow passing null to .set() to clear the set promise', () => {
PromiseProvider.set(Promise);
expect(PromiseProvider.get()).to.equal(Promise);
expect(() => PromiseProvider.set(null)).to.not.throw();
expect(PromiseProvider.get()).to.be.null;
});

it('should emit a deprecation warning when a promiseLibrary is set', async () => {
Expand Down
1 change: 0 additions & 1 deletion test/types/community/client.test-d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ const options: MongoClientOptions = {
promoteBuffers: false,
authMechanism: 'SCRAM-SHA-1',
forceServerObjectId: false,
promiseLibrary: Promise,
directConnection: false
};

Expand Down
1 change: 0 additions & 1 deletion test/unit/mongo_client.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,6 @@ describe('MongoOptions', function () {
return 'very unique';
}
},
promiseLibrary: global.Promise,
promoteBuffers: true,
promoteLongs: false,
promoteValues: false,
Expand Down