@@ -14,6 +14,7 @@ import {
14
14
import { UAParser } from "ua-parser-js" ;
15
15
16
16
import type { ParsedUserAgent } from "../types/types.d.ts" ;
17
+ import { RUNTIME_IDS_WITH_PATCH_VERSIONING } from "./constants.js" ;
17
18
18
19
/**
19
20
* Returns the major version from a given version string.
@@ -111,10 +112,11 @@ const parseUA = (userAgent: string, browsers: Browsers): ParsedUserAgent => {
111
112
}
112
113
113
114
data . fullVersion = data . fullVersion || ua . browser . version || "0" ;
114
- data . version = getMajorMinorVersion ( data . fullVersion ) ;
115
115
116
- if ( data . browser . id == "bun" ) {
116
+ if ( RUNTIME_IDS_WITH_PATCH_VERSIONING . has ( data . browser . id ) ) {
117
117
data . version = data . fullVersion ;
118
+ } else {
119
+ data . version = getMajorMinorVersion ( data . fullVersion ) ;
118
120
}
119
121
120
122
if ( ! ( data . browser . id in browsers ) ) {
@@ -155,36 +157,46 @@ const parseUA = (userAgent: string, browsers: Browsers): ParsedUserAgent => {
155
157
// with this, find the pair of versions in |versions| that sandwiches
156
158
// |version|, and use the first of this pair. For example, given |version|
157
159
// "10.1" and |versions| entries "10.0" and "10.2", return "10.0".
158
- for ( let i = 0 ; i < versions . length - 1 ; i ++ ) {
159
- const current = versions [ i ] ;
160
- const next = versions [ i + 1 ] ;
161
- if (
162
- compareVersions ( data . version , current , ">=" ) &&
163
- compareVersions ( data . version , next , "<" )
164
- ) {
160
+ // However, for Bun, we need exact version matches because patch versions can add features.
161
+ if ( RUNTIME_IDS_WITH_PATCH_VERSIONING . has ( data . browser . id ) ) {
162
+ // For Bun, only mark as inBcd if exact version exists
163
+ if ( versions . includes ( data . version ) ) {
165
164
data . inBcd = true ;
166
- data . version = current ;
167
- break ;
165
+ }
166
+ } else {
167
+ for ( let i = 0 ; i < versions . length - 1 ; i ++ ) {
168
+ const current = versions [ i ] ;
169
+ const next = versions [ i + 1 ] ;
170
+ if (
171
+ compareVersions ( data . version , current , ">=" ) &&
172
+ compareVersions ( data . version , next , "<" )
173
+ ) {
174
+ data . inBcd = true ;
175
+ data . version = current ;
176
+ break ;
177
+ }
168
178
}
169
179
}
170
180
171
181
// We reached the last entry in |versions|. With no |next| to compare against
172
182
// we have to check if it looks like a significant release or not. By default
173
183
// that means a new major version, but for Safari and Samsung Internet the
174
184
// major and minor version are significant.
175
- let normalize = getMajorVersion ;
176
- if (
177
- data . browser . id . startsWith ( "safari" ) ||
178
- data . browser . id === "samsunginternet_android"
179
- ) {
180
- normalize = getMajorMinorVersion ;
181
- }
182
- if (
183
- data . inBcd == false &&
184
- normalize ( data . version ) === normalize ( versions [ versions . length - 1 ] )
185
- ) {
186
- data . inBcd = true ;
187
- data . version = versions [ versions . length - 1 ] ;
185
+ if ( ! RUNTIME_IDS_WITH_PATCH_VERSIONING . has ( data . browser . id ) ) {
186
+ let normalize = getMajorVersion ;
187
+ if (
188
+ data . browser . id . startsWith ( "safari" ) ||
189
+ data . browser . id === "samsunginternet_android"
190
+ ) {
191
+ normalize = getMajorMinorVersion ;
192
+ }
193
+ if (
194
+ data . inBcd == false &&
195
+ normalize ( data . version ) === normalize ( versions [ versions . length - 1 ] )
196
+ ) {
197
+ data . inBcd = true ;
198
+ data . version = versions [ versions . length - 1 ] ;
199
+ }
188
200
}
189
201
190
202
return data ;
0 commit comments