From fba16adb52f2ef37e87ea64bd6163711d0f09b84 Mon Sep 17 00:00:00 2001 From: Neal Beeken Date: Tue, 18 Apr 2023 10:47:24 -0400 Subject: [PATCH] feat(NODE-5199): add alternative runtime detection to client metadata (#3647) Co-authored-by: Durran Jordan --- .evergreen/config.yml | 6 +- .evergreen/generate_evergreen_tasks.js | 4 +- src/cmap/handshake/client_metadata.ts | 46 ++++++++-- .../cmap/handshake/client_metadata.test.ts | 88 +++++++++++++++++++ 4 files changed, 134 insertions(+), 10 deletions(-) diff --git a/.evergreen/config.yml b/.evergreen/config.yml index aa4df00f18..297f3d38b3 100644 --- a/.evergreen/config.yml +++ b/.evergreen/config.yml @@ -2343,7 +2343,7 @@ tasks: commands: - func: install dependencies vars: - NODE_LTS_NAME: erbium + NODE_LTS_NAME: hydrogen - func: check types vars: TS_VERSION: next @@ -2363,7 +2363,7 @@ tasks: commands: - func: install dependencies vars: - NODE_LTS_NAME: erbium + NODE_LTS_NAME: hydrogen - func: check types vars: TS_VERSION: current @@ -2373,7 +2373,7 @@ tasks: commands: - func: install dependencies vars: - NODE_LTS_NAME: erbium + NODE_LTS_NAME: hydrogen - func: check types vars: TS_VERSION: 4.1.6 diff --git a/.evergreen/generate_evergreen_tasks.js b/.evergreen/generate_evergreen_tasks.js index 5d9978b341..598acf87e6 100644 --- a/.evergreen/generate_evergreen_tasks.js +++ b/.evergreen/generate_evergreen_tasks.js @@ -495,7 +495,7 @@ function* makeTypescriptTasks() { { func: 'install dependencies', vars: { - NODE_LTS_NAME: LOWEST_LTS + NODE_LTS_NAME: LATEST_LTS } }, { @@ -514,7 +514,7 @@ function* makeTypescriptTasks() { { func: 'install dependencies', vars: { - NODE_LTS_NAME: LOWEST_LTS + NODE_LTS_NAME: LATEST_LTS } }, { func: 'run typescript next' } diff --git a/src/cmap/handshake/client_metadata.ts b/src/cmap/handshake/client_metadata.ts index 0c00af9a8e..ab66328ca5 100644 --- a/src/cmap/handshake/client_metadata.ts +++ b/src/cmap/handshake/client_metadata.ts @@ -116,12 +116,12 @@ export function makeClientMetadata(options: MakeClientMetadataOptions): ClientMe ); } - const platformInfo = - platform.length > 0 - ? `Node.js ${process.version}, ${os.endianness()}|${platform}` - : `Node.js ${process.version}, ${os.endianness()}`; + let runtimeInfo = getRuntimeInfo(); + if (platform.length > 0) { + runtimeInfo = `${runtimeInfo}|${platform}`; + } - if (!metadataDocument.ifItFitsItSits('platform', platformInfo)) { + if (!metadataDocument.ifItFitsItSits('platform', runtimeInfo)) { throw new MongoInvalidArgumentError( 'Unable to include driverInfo platform, metadata cannot exceed 512 bytes' ); @@ -234,3 +234,39 @@ export function getFAASEnv(): Map | null { return null; } + +/** + * @internal + * This type represents the global Deno object and the minimal type contract we expect it to satisfy. + */ +declare const Deno: { version?: { deno?: string } } | undefined; + +/** + * @internal + * This type represents the global Bun object and the minimal type contract we expect it to satisfy. + */ +declare const Bun: { (): void; version?: string } | undefined; + +/** + * @internal + * Get current JavaScript runtime platform + * + * NOTE: The version information fetching is intentionally written defensively + * to avoid having a released driver version that becomes incompatible + * with a future change to these global objects. + */ +function getRuntimeInfo(): string { + if ('Deno' in globalThis) { + const version = typeof Deno?.version?.deno === 'string' ? Deno?.version?.deno : '0.0.0-unknown'; + + return `Deno v${version}, ${os.endianness()}`; + } + + if ('Bun' in globalThis) { + const version = typeof Bun?.version === 'string' ? Bun?.version : '0.0.0-unknown'; + + return `Bun v${version}, ${os.endianness()}`; + } + + return `Node.js ${process.version}, ${os.endianness()}`; +} diff --git a/test/unit/cmap/handshake/client_metadata.test.ts b/test/unit/cmap/handshake/client_metadata.test.ts index 97b2afe2c5..98eef138e6 100644 --- a/test/unit/cmap/handshake/client_metadata.test.ts +++ b/test/unit/cmap/handshake/client_metadata.test.ts @@ -288,6 +288,94 @@ describe('client metadata module', () => { }); }); }); + + context('when globalThis indicates alternative runtime', () => { + context('deno', () => { + afterEach(() => { + expect(delete globalThis.Deno, 'failed to delete Deno global').to.be.true; + }); + + it('sets platform to Deno', () => { + globalThis.Deno = { version: { deno: '1.2.3' } }; + const metadata = makeClientMetadata({ driverInfo: {} }); + expect(metadata.platform).to.equal('Deno v1.2.3, LE'); + }); + + it('sets platform to Deno with driverInfo.platform', () => { + globalThis.Deno = { version: { deno: '1.2.3' } }; + const metadata = makeClientMetadata({ driverInfo: { platform: 'myPlatform' } }); + expect(metadata.platform).to.equal('Deno v1.2.3, LE|myPlatform'); + }); + + it('ignores version if Deno.version.deno is not a string', () => { + globalThis.Deno = { version: { deno: 1 } }; + const metadata = makeClientMetadata({ driverInfo: {} }); + expect(metadata.platform).to.equal('Deno v0.0.0-unknown, LE'); + }); + + it('ignores version if Deno.version does not have a deno property', () => { + globalThis.Deno = { version: { somethingElse: '1.2.3' } }; + const metadata = makeClientMetadata({ driverInfo: {} }); + expect(metadata.platform).to.equal('Deno v0.0.0-unknown, LE'); + }); + + it('ignores version if Deno.version is null', () => { + globalThis.Deno = { version: null }; + const metadata = makeClientMetadata({ driverInfo: {} }); + expect(metadata.platform).to.equal('Deno v0.0.0-unknown, LE'); + }); + + it('ignores version if Deno is nullish', () => { + globalThis.Deno = null; + const metadata = makeClientMetadata({ driverInfo: {} }); + expect(metadata.platform).to.equal('Deno v0.0.0-unknown, LE'); + }); + }); + + context('bun', () => { + afterEach(() => { + expect(delete globalThis.Bun, 'failed to delete Bun global').to.be.true; + }); + + it('sets platform to Bun', () => { + globalThis.Bun = class { + static version = '1.2.3'; + }; + const metadata = makeClientMetadata({ driverInfo: {} }); + expect(metadata.platform).to.equal('Bun v1.2.3, LE'); + }); + + it('sets platform to Bun with driverInfo.platform', () => { + globalThis.Bun = class { + static version = '1.2.3'; + }; + const metadata = makeClientMetadata({ driverInfo: { platform: 'myPlatform' } }); + expect(metadata.platform).to.equal('Bun v1.2.3, LE|myPlatform'); + }); + + it('ignores version if Bun.version is not a string', () => { + globalThis.Bun = class { + static version = 1; + }; + const metadata = makeClientMetadata({ driverInfo: {} }); + expect(metadata.platform).to.equal('Bun v0.0.0-unknown, LE'); + }); + + it('ignores version if Bun.version is not a string and sets driverInfo.platform', () => { + globalThis.Bun = class { + static version = 1; + }; + const metadata = makeClientMetadata({ driverInfo: { platform: 'myPlatform' } }); + expect(metadata.platform).to.equal('Bun v0.0.0-unknown, LE|myPlatform'); + }); + + it('ignores version if Bun is nullish', () => { + globalThis.Bun = null; + const metadata = makeClientMetadata({ driverInfo: { platform: 'myPlatform' } }); + expect(metadata.platform).to.equal('Bun v0.0.0-unknown, LE|myPlatform'); + }); + }); + }); }); describe('FAAS metadata application to handshake', () => {