2020-09-24 19:33:09 +08:00
/ *
MIT License http : //www.opensource.org/licenses/mit-license.php
Author Sergey Melyukov @ smelukov
* /
2020-09-24 19:42:27 +08:00
"use strict" ;
2020-09-24 19:33:09 +08:00
2020-09-24 20:46:28 +08:00
const path = require ( "path" ) ;
2025-07-03 17:06:45 +08:00
const browserslist = require ( "browserslist" ) ;
2020-09-24 19:33:09 +08:00
2020-09-28 16:04:58 +08:00
/** @typedef {import("./target").ApiTargetProperties} ApiTargetProperties */
2020-09-28 15:57:29 +08:00
/** @typedef {import("./target").EcmaTargetProperties} EcmaTargetProperties */
2020-09-28 16:04:58 +08:00
/** @typedef {import("./target").PlatformTargetProperties} PlatformTargetProperties */
2020-09-28 15:57:29 +08:00
2020-09-25 04:10:33 +08:00
// [[C:]/path/to/config][:env]
2020-09-25 04:44:41 +08:00
const inputRx = /^(?:((?:[A-Z]:)?[/\\].*?))?(?::(.+?))?$/i ;
2020-09-24 19:33:09 +08:00
/ * *
2023-05-24 05:25:06 +08:00
* @ param { string | null | undefined } input input string
2020-09-28 16:52:52 +08:00
* @ param { string } context the context directory
2025-10-02 01:12:27 +08:00
* @ returns { string [ ] | undefined } selected browsers
2020-09-24 19:33:09 +08:00
* /
2025-10-02 01:12:27 +08:00
const load = ( input , context ) => {
// browserslist:path-to-config
// browserslist:path-to-config:env
if ( input && path . isAbsolute ( input ) ) {
2020-09-24 20:41:54 +08:00
const [ , configPath , env ] = inputRx . exec ( input ) || [ ] ;
2025-10-02 01:12:27 +08:00
const config = browserslist . loadConfig ( {
config : configPath ,
env
} ) ;
2020-09-24 20:41:54 +08:00
2025-10-02 01:12:27 +08:00
return browserslist ( config , { env } ) ;
2020-09-24 20:41:54 +08:00
}
2020-09-24 19:33:09 +08:00
2025-10-02 01:12:27 +08:00
const env = input || undefined ;
const config = browserslist . loadConfig ( {
path : context ,
env
} ) ;
// browserslist
// browserslist:env
if ( config ) {
try {
return browserslist ( config , { env , throwOnMissing : true } ) ;
} catch ( _err ) {
// Nothing, no `env` was found in browserslist, maybe input is `queries`
}
}
2020-09-28 16:52:52 +08:00
2025-10-02 01:12:27 +08:00
// browserslist:query
if ( env ) {
return browserslist ( env ) ;
}
2020-09-28 16:52:52 +08:00
} ;
2020-09-24 19:33:09 +08:00
/ * *
* @ param { string [ ] } browsers supported browsers list
2020-09-28 16:04:58 +08:00
* @ returns { EcmaTargetProperties & PlatformTargetProperties & ApiTargetProperties } target properties
2020-09-24 19:33:09 +08:00
* /
2025-07-17 00:13:14 +08:00
const resolve = ( browsers ) => {
2020-09-28 15:57:29 +08:00
/ * *
* Checks all against a version number
2020-09-28 17:09:07 +08:00
* @ param { Record < string , number | [ number , number ] > } versions first supported version
2020-09-28 15:57:29 +08:00
* @ returns { boolean } true if supports
* /
2025-07-17 00:13:14 +08:00
const rawChecker = ( versions ) =>
browsers . every ( ( v ) => {
2020-10-31 21:54:47 +08:00
const [ name , parsedVersion ] = v . split ( " " ) ;
if ( ! name ) return false ;
const requiredVersion = versions [ name ] ;
if ( ! requiredVersion ) return false ;
2020-10-31 22:03:54 +08:00
const [ parsedMajor , parserMinor ] =
// safari TP supports all features for normal safari
parsedVersion === "TP"
? [ Infinity , Infinity ]
2024-01-31 20:45:32 +08:00
: parsedVersion . includes ( "-" )
? parsedVersion . split ( "-" ) [ 0 ] . split ( "." )
: parsedVersion . split ( "." ) ;
2020-10-31 21:54:47 +08:00
if ( typeof requiredVersion === "number" ) {
2024-07-31 11:11:11 +08:00
return Number ( parsedMajor ) >= requiredVersion ;
2020-10-31 21:54:47 +08:00
}
2024-07-31 11:11:11 +08:00
return requiredVersion [ 0 ] === Number ( parsedMajor )
? Number ( parserMinor ) >= requiredVersion [ 1 ]
: Number ( parsedMajor ) > requiredVersion [ 0 ] ;
2020-09-28 15:57:29 +08:00
} ) ;
2025-07-17 00:13:14 +08:00
const anyNode = browsers . some ( ( b ) => b . startsWith ( "node " ) ) ;
const anyBrowser = browsers . some ( ( b ) => / ^ ( ? ! node ) / . test ( b ) ) ;
2020-09-28 16:04:58 +08:00
const browserProperty = ! anyBrowser ? false : anyNode ? null : true ;
const nodeProperty = ! anyNode ? false : anyBrowser ? null : true ;
2020-11-03 00:08:06 +08:00
// Internet Explorer Mobile, Blackberry browser and Opera Mini are very old browsers, they do not support new features
2020-10-31 21:54:47 +08:00
const es6DynamicImport = rawChecker ( {
2024-07-31 09:37:24 +08:00
/* eslint-disable camelcase */
2020-10-31 21:54:47 +08:00
chrome : 63 ,
2020-10-31 22:17:47 +08:00
and _chr : 63 ,
2020-10-31 21:54:47 +08:00
edge : 79 ,
firefox : 67 ,
2020-10-31 22:17:47 +08:00
and _ff : 67 ,
2020-11-03 00:08:06 +08:00
// ie: Not supported
2020-10-31 21:54:47 +08:00
opera : 50 ,
2020-11-02 23:21:37 +08:00
op _mob : 46 ,
2020-10-31 21:54:47 +08:00
safari : [ 11 , 1 ] ,
2020-10-31 22:17:47 +08:00
ios _saf : [ 11 , 3 ] ,
2020-11-03 00:08:06 +08:00
samsung : [ 8 , 2 ] ,
2020-11-02 23:21:37 +08:00
android : 63 ,
2020-11-03 00:08:06 +08:00
and _qq : [ 10 , 4 ] ,
2024-01-31 21:15:13 +08:00
baidu : [ 13 , 18 ] ,
and _uc : [ 15 , 5 ] ,
2023-06-17 12:18:08 +08:00
kaios : [ 3 , 0 ] ,
2022-02-21 22:22:42 +08:00
node : [ 12 , 17 ]
2024-07-31 09:37:24 +08:00
/* eslint-enable camelcase */
2020-10-31 21:54:47 +08:00
} ) ;
2020-09-28 15:57:29 +08:00
return {
2024-07-31 09:37:24 +08:00
/* eslint-disable camelcase */
2020-10-31 21:54:47 +08:00
const : rawChecker ( {
2020-11-03 00:08:06 +08:00
chrome : 49 ,
and _chr : 49 ,
2020-10-31 21:54:47 +08:00
edge : 12 ,
// Prior to Firefox 13, <code>const</code> is implemented, but re-assignment is not failing.
// Prior to Firefox 46, a <code>TypeError</code> was thrown on redeclaration instead of a <code>SyntaxError</code>.
firefox : 36 ,
2020-10-31 22:17:47 +08:00
and _ff : 36 ,
2020-11-02 23:21:37 +08:00
// Not supported in for-in and for-of loops
// ie: Not supported
2020-11-03 00:08:06 +08:00
opera : 36 ,
op _mob : 36 ,
safari : [ 10 , 0 ] ,
ios _saf : [ 10 , 0 ] ,
2020-11-02 23:21:37 +08:00
// Before 5.0 supported correctly in strict mode, otherwise supported without block scope
samsung : [ 5 , 0 ] ,
android : 37 ,
2020-11-03 00:08:06 +08:00
and _qq : [ 10 , 4 ] ,
// Supported correctly in strict mode, otherwise supported without block scope
2024-01-31 21:15:13 +08:00
baidu : [ 13 , 18 ] ,
2020-11-03 00:08:06 +08:00
and _uc : [ 12 , 12 ] ,
kaios : [ 2 , 5 ] ,
2020-11-02 23:21:37 +08:00
node : [ 6 , 0 ]
2020-10-31 21:54:47 +08:00
} ) ,
arrowFunction : rawChecker ( {
chrome : 45 ,
2020-10-31 22:17:47 +08:00
and _chr : 45 ,
2020-10-31 21:54:47 +08:00
edge : 12 ,
// The initial implementation of arrow functions in Firefox made them automatically strict. This has been changed as of Firefox 24. The use of <code>'use strict';</code> is now required.
// Prior to Firefox 39, a line terminator (<code>\\n</code>) was incorrectly allowed after arrow function arguments. This has been fixed to conform to the ES2015 specification and code like <code>() \\n => {}</code> will now throw a <code>SyntaxError</code> in this and later versions.
firefox : 39 ,
2020-10-31 22:17:47 +08:00
and _ff : 39 ,
2020-10-31 21:54:47 +08:00
// ie: Not supported,
opera : 32 ,
2020-11-02 23:21:37 +08:00
op _mob : 32 ,
2020-10-31 21:54:47 +08:00
safari : 10 ,
2020-10-31 22:17:47 +08:00
ios _saf : 10 ,
samsung : [ 5 , 0 ] ,
2020-11-02 23:21:37 +08:00
android : 45 ,
2020-11-03 00:08:06 +08:00
and _qq : [ 10 , 4 ] ,
baidu : [ 7 , 12 ] ,
and _uc : [ 12 , 12 ] ,
kaios : [ 2 , 5 ] ,
2020-11-02 23:21:37 +08:00
node : [ 6 , 0 ]
2020-10-31 21:54:47 +08:00
} ) ,
2020-10-31 01:24:42 +08:00
forOf : rawChecker ( {
chrome : 38 ,
2020-10-31 22:17:47 +08:00
and _chr : 38 ,
2020-10-31 01:24:42 +08:00
edge : 12 ,
// Prior to Firefox 51, using the for...of loop construct with the const keyword threw a SyntaxError ("missing = in const declaration").
firefox : 51 ,
2020-10-31 22:17:47 +08:00
and _ff : 51 ,
2020-10-31 01:24:42 +08:00
// ie: Not supported,
opera : 25 ,
2020-11-02 23:21:37 +08:00
op _mob : 25 ,
2020-10-31 01:24:42 +08:00
safari : 7 ,
2020-10-31 22:17:47 +08:00
ios _saf : 7 ,
samsung : [ 3 , 0 ] ,
2020-11-02 23:21:37 +08:00
android : 38 ,
2020-11-03 00:08:06 +08:00
// and_qq: Unknown support
// baidu: Unknown support
// and_uc: Unknown support
2023-06-17 12:18:08 +08:00
kaios : [ 3 , 0 ] ,
2020-11-02 23:21:37 +08:00
node : [ 0 , 12 ]
2020-10-31 01:24:42 +08:00
} ) ,
destructuring : rawChecker ( {
chrome : 49 ,
2020-10-31 22:17:47 +08:00
and _chr : 49 ,
2020-10-31 01:24:42 +08:00
edge : 14 ,
firefox : 41 ,
2020-10-31 22:17:47 +08:00
and _ff : 41 ,
2020-10-31 01:24:42 +08:00
// ie: Not supported,
opera : 36 ,
2020-11-02 23:21:37 +08:00
op _mob : 36 ,
2020-10-31 01:24:42 +08:00
safari : 8 ,
2020-10-31 22:17:47 +08:00
ios _saf : 8 ,
samsung : [ 5 , 0 ] ,
2020-11-02 23:21:37 +08:00
android : 49 ,
2020-11-03 00:08:06 +08:00
// and_qq: Unknown support
// baidu: Unknown support
// and_uc: Unknown support
2023-06-17 12:18:08 +08:00
kaios : [ 2 , 5 ] ,
2020-11-02 23:21:37 +08:00
node : [ 6 , 0 ]
2020-10-31 01:24:42 +08:00
} ) ,
2020-10-31 21:54:47 +08:00
bigIntLiteral : rawChecker ( {
chrome : 67 ,
2020-10-31 22:17:47 +08:00
and _chr : 67 ,
2020-10-31 21:54:47 +08:00
edge : 79 ,
firefox : 68 ,
2020-10-31 22:17:47 +08:00
and _ff : 68 ,
2020-10-31 21:54:47 +08:00
// ie: Not supported,
opera : 54 ,
2020-11-02 23:21:37 +08:00
op _mob : 48 ,
2020-10-31 21:54:47 +08:00
safari : 14 ,
2020-10-31 22:17:47 +08:00
ios _saf : 14 ,
2020-11-03 00:08:06 +08:00
samsung : [ 9 , 2 ] ,
2020-11-02 23:21:37 +08:00
android : 67 ,
2024-01-31 21:15:13 +08:00
and _qq : [ 13 , 1 ] ,
baidu : [ 13 , 18 ] ,
and _uc : [ 15 , 5 ] ,
2023-06-17 12:18:08 +08:00
kaios : [ 3 , 0 ] ,
2020-11-02 23:21:37 +08:00
node : [ 10 , 4 ]
2020-10-31 21:54:47 +08:00
} ) ,
// Support syntax `import` and `export` and no limitations and bugs on Node.js
// Not include `export * as namespace`
module : rawChecker ( {
chrome : 61 ,
2020-10-31 22:17:47 +08:00
and _chr : 61 ,
2020-10-31 21:54:47 +08:00
edge : 16 ,
firefox : 60 ,
2020-10-31 22:17:47 +08:00
and _ff : 60 ,
2020-10-31 21:54:47 +08:00
// ie: Not supported,
opera : 48 ,
2020-11-02 23:21:37 +08:00
op _mob : 45 ,
2020-10-31 21:54:47 +08:00
safari : [ 10 , 1 ] ,
2020-10-31 22:17:47 +08:00
ios _saf : [ 10 , 3 ] ,
2020-11-02 23:21:37 +08:00
samsung : [ 8 , 0 ] ,
2020-11-03 00:08:06 +08:00
android : 61 ,
and _qq : [ 10 , 4 ] ,
2024-01-31 21:15:13 +08:00
baidu : [ 13 , 18 ] ,
and _uc : [ 15 , 5 ] ,
2023-06-17 12:18:08 +08:00
kaios : [ 3 , 0 ] ,
2022-02-21 22:22:42 +08:00
node : [ 12 , 17 ]
2020-10-31 21:54:47 +08:00
} ) ,
dynamicImport : es6DynamicImport ,
dynamicImportInWorker : es6DynamicImport && ! anyNode ,
2020-09-28 15:57:29 +08:00
// browserslist does not have info about globalThis
// so this is based on mdn-browser-compat-data
globalThis : rawChecker ( {
chrome : 71 ,
2020-10-31 22:17:47 +08:00
and _chr : 71 ,
2020-09-28 15:57:29 +08:00
edge : 79 ,
firefox : 65 ,
2020-10-31 22:17:47 +08:00
and _ff : 65 ,
2020-09-28 15:57:29 +08:00
// ie: Not supported,
opera : 58 ,
2020-11-02 23:21:37 +08:00
op _mob : 50 ,
2020-09-28 15:57:29 +08:00
safari : [ 12 , 1 ] ,
2020-10-31 22:17:47 +08:00
ios _saf : [ 12 , 2 ] ,
2020-11-03 00:08:06 +08:00
samsung : [ 10 , 1 ] ,
2020-11-02 23:21:37 +08:00
android : 71 ,
2020-11-03 00:08:06 +08:00
// and_qq: Unknown support
// baidu: Unknown support
// and_uc: Unknown support
2023-06-17 12:18:08 +08:00
kaios : [ 3 , 0 ] ,
2022-02-21 22:22:42 +08:00
node : 12
2020-09-28 16:04:58 +08:00
} ) ,
2021-11-22 01:51:36 +08:00
optionalChaining : rawChecker ( {
chrome : 80 ,
and _chr : 80 ,
edge : 80 ,
firefox : 74 ,
and _ff : 79 ,
// ie: Not supported,
opera : 67 ,
op _mob : 64 ,
safari : [ 13 , 1 ] ,
ios _saf : [ 13 , 4 ] ,
samsung : 13 ,
android : 80 ,
// and_qq: Not supported
// baidu: Not supported
// and_uc: Not supported
2023-06-17 12:18:08 +08:00
kaios : [ 3 , 0 ] ,
2021-11-22 01:51:36 +08:00
node : 14
} ) ,
templateLiteral : rawChecker ( {
chrome : 41 ,
and _chr : 41 ,
edge : 13 ,
firefox : 34 ,
and _ff : 34 ,
// ie: Not supported,
opera : 29 ,
op _mob : 64 ,
safari : [ 9 , 1 ] ,
ios _saf : 9 ,
samsung : 4 ,
android : 41 ,
and _qq : [ 10 , 4 ] ,
baidu : [ 7 , 12 ] ,
and _uc : [ 12 , 12 ] ,
kaios : [ 2 , 5 ] ,
node : 4
} ) ,
2024-01-14 18:11:12 +08:00
asyncFunction : rawChecker ( {
chrome : 55 ,
and _chr : 55 ,
edge : 15 ,
firefox : 52 ,
and _ff : 52 ,
// ie: Not supported,
opera : 42 ,
op _mob : 42 ,
2024-01-31 20:45:32 +08:00
safari : 11 ,
ios _saf : 11 ,
samsung : [ 6 , 2 ] ,
2024-01-14 18:11:12 +08:00
android : 55 ,
2024-01-31 20:45:32 +08:00
and _qq : [ 13 , 1 ] ,
baidu : [ 13 , 18 ] ,
and _uc : [ 15 , 5 ] ,
kaios : 3 ,
2024-01-14 18:11:12 +08:00
node : [ 7 , 6 ]
} ) ,
2024-07-31 09:37:24 +08:00
/* eslint-enable camelcase */
2020-09-28 16:04:58 +08:00
browser : browserProperty ,
electron : false ,
node : nodeProperty ,
nwjs : false ,
web : browserProperty ,
webworker : false ,
document : browserProperty ,
fetchWasm : browserProperty ,
global : nodeProperty ,
importScripts : false ,
importScriptsInWorker : true ,
nodeBuiltins : nodeProperty ,
2024-04-12 00:16:15 +08:00
nodePrefixForCoreModules :
nodeProperty &&
2025-07-17 00:13:14 +08:00
! browsers . some ( ( b ) => b . startsWith ( "node 15" ) ) &&
2024-04-12 00:16:15 +08:00
rawChecker ( {
node : [ 14 , 18 ]
} ) ,
2020-09-28 16:04:58 +08:00
require : nodeProperty
2020-09-24 19:33:09 +08:00
} ;
} ;
module . exports = {
2025-07-03 17:06:45 +08:00
load ,
resolve
2020-09-24 19:33:09 +08:00
} ;