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