Redefine browser requirements for modern (latest) builds#16506
Redefine browser requirements for modern (latest) builds#16506
Conversation
|
Should have mentioned that the regex includes all the browsers in the CanIUse.com database, not just the ones listed above. Here's the full test: var isModern = /Edge?\/(1{2}\d|1[2-9]\d|[2-9]\d{2}|\d{4,})(\.\d+|)(\.\d+|)|Firefox\/(10[2-9]|1[1-9]\d|[2-9]\d{2}|\d{4,})\.\d+(\.\d+|)|Chrom(ium|e)\/(109|1[1-9]\d|[2-9]\d{2}|\d{4,})\.\d+(\.\d+|)|Maci.+ Version\/(15\.([6-9]|\d{2,})|(1[6-9]|[2-9]\d|\d{3,})\.\d+)([,.]\d+|)( Mobile\/\w+|) Safari\/|Chrome.+OPR\/(9[4-9]|\d{3,})\.\d+\.\d+|(CPU[ +]OS|iPhone[ +]OS|CPU[ +]iPhone|CPU IPhone OS|CPU iPad OS)[ +]+(15[._]([6-9]|\d{2,})|(1[6-9]|[2-9]\d|\d{3,})[._]\d+)([._]\d+|)|Android:?[ /-](1{2}[2-9]|1[2-9]\d|[2-9]\d{2}|\d{4,})(\.\d+|)(\.\d+|)|Mobile Safari.+OPR\/(7[3-9]|[89]\d|\d{3,})\.\d+\.\d+|Android.+Firefox\/(1{2}\d|1[2-9]\d|[2-9]\d{2}|\d{4,})\.\d+(\.\d+|)|Android.+Chrom(ium|e)\/(1{2}[2-9]|1[2-9]\d|[2-9]\d{2}|\d{4,})\.\d+(\.\d+|)|Android.+(UC? ?Browser|UCWEB|U3)[ /]?(13\.([4-9]|\d{2,})|(1[4-9]|[2-9]\d|\d{3,})\.\d+)\.\d+|SamsungBrowser\/(19|[2-9]\d|\d{3,})\.\d+|Android.+MQ{2}Browser\/(13(\.([1-9]|\d{2,})|)|(1[4-9]|[2-9]\d|\d{3,})(\.\d+|))(\.\d+|)|K[Aa][Ii]OS\/(3\.\d+|([4-9]|\d{2,})\.\d+)(\.\d+|)/.test(navigator.userAgent); |
ca3a3eb to
9e55e39
Compare
|
I feel like these restraints are a bit too much, we are now pushing people to the much bigger and slower ES5 build, while their device/browser is perfectly capable of running on our latest build? Are we fixing certain browsers with this, that now don't work with latest and are moved to ES5? If so what are we fixing and could we target that more precise? If it would really gain us something in terms of performance I would get it, but it seems that isn't the case (at least for now?) |
|
I'm marking this as a draft because I want to investigate how it treats android mobile versions. The regex is only grabbing the latest version but the docs say it should be treated like desktop. Answering your questions in the meantime...
In terms of size, the 2 builds are actually not that far apart anymore after #16466. Compared to the current release of major browsers, the latest build is actually targeting browsers much closer to the legacy requirements from #16384, and that gap will keep getting smaller without redefining somehow. So this is really just trying to drive a bigger wedge between the 2 builds and eek out as much extra performance and reduced size as possible. Based on the global usage data, this might affect about 5% of users, but that's an estimate for sure. That said, I'm certainly not claiming this is the best position for the wedge so that's worth discussing. I'm not sure how to make it more "accurate" though in the absence of including user agents in the HA analytics data.
Yes. Though it's not turned on right now, we should be allowing Babel to inject core-js polyfills into the latest build in order to fix or support various features, some of which are used frequently. If we did under the current dynamic import test, here's the plugins and polyfills that would be used:
|
|
FYI, to deal with the android issue, some fixes to
The latter can be worked around temporarily, but the first is a hold up. |
9e55e39 to
16df767
Compare
75008dd to
d48a9e3
Compare
|
I submitted fixes to the var isModern = /Edge?\/(10[4-9]|1[1-9]\d|[2-9]\d{2}|\d{4,})(\.\d+|)(\.\d+|)|Firefox\/(10[2-9]|1[1-9]\d|[2-9]\d{2}|\d{4,})\.\d+(\.\d+|)|Chrom(ium|e)\/(10[4-9]|1[1-9]\d|[2-9]\d{2}|\d{4,})\.\d+(\.\d+|)|Maci.+ Version\/(15\.([6-9]|\d{2,})|(1[6-9]|[2-9]\d|\d{3,})\.\d+)([,.]\d+|)( Mobile\/\w+|) Safari\/|Chrome.+OPR\/(89|9\d|\d{3,})\.\d+\.\d+|(CPU[ +]OS|iPhone[ +]OS|CPU[ +]iPhone|CPU IPhone OS|CPU iPad OS)[ +]+(15[._]([6-9]|\d{2,})|(1[6-9]|[2-9]\d|\d{3,})[._]\d+)([._]\d+|)|Android:?[ /-](10[4-9]|1[1-9]\d|[2-9]\d{2}|\d{4,})(\.\d+|)(\.\d+|)|Mobile Safari.+OPR\/(7[3-9]|[89]\d|\d{3,})\.\d+\.\d+|Android.+Firefox\/(10[3-9]|1[1-9]\d|[2-9]\d{2}|\d{4,})\.\d+(\.\d+|)|Android.+Chrom(ium|e)\/(10[4-9]|1[1-9]\d|[2-9]\d{2}|\d{4,})\.\d+(\.\d+|)|SamsungBrowser\/(1[89]|[2-9]\d|\d{3,})\.\d+/.test(navigator.userAgent);In fixing the |
|
In terms of adding more browsers, I think we could safely include anything released in the last year as opposed to just the last 2 versions. The popularity of older iOS versions and inclusion of Firefox ESR keep the transpiling and polyfilling to about a year in the past anyway. Going beyond 1 year I think would be excessive. The other parameter to play with is the usage percentage, but that will start bringing back pretty old stuff depending on the value. For example, > 0.2% goes back to IOS 12 and Chrome 79, adding extra transpiling and polyfilling of course. Thoughts? |
b9cf48b to
296de5e
Compare
|
Okay I think this is probably ready to go now:
I updated the OP to reflect all changes. |
bce0e3c to
b9e5561
Compare
|
@bramkragten are you generally okay with this approach (minus the exact query to use perhaps)? If so, I can throw together updated documentation for home-assistant/home-assistant.io#27509. |
|
I don't really like that we will now test on useragent instead of actual features, the useragent can be overriden by a client (Like our apps: iOS & Android) and in general I think it is saver to check for actually features For the exact query to use I think we should try to make something that will gain us enough to justify dropping certain users to a slower version, or make sure we (almost) don't actually drop anything. |
WalkthroughWalkthroughThe recent changes focus on enhancing performance and compatibility across modern and legacy browsers. Key updates include refining browser targeting in Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant Browser
participant Server
User->>Browser: Request page
Browser->>Server: Load HTML template
Server->>Browser: Serve HTML template
Browser->>Browser: Check user agent
alt Modern Browser
Browser->>Server: Load ES6 modules
else Legacy Browser
Browser->>Server: Load ES5 modules
end
Browser->>User: Render page
sequenceDiagram
participant User
participant Browser
participant Server
User->>Browser: Request onboarding
Browser->>Browser: Check window.latestJS
alt latestJS is true
Browser->>Server: Fetch onboarding steps
else latestJS is false
Browser->>Server: Load fallback scripts
end
Browser->>User: Render onboarding page
Recent review detailsConfiguration used: CodeRabbit UI Files ignored due to path filters (1)
Files selected for processing (14)
Files skipped from review as they are similar to previous changes (13)
Additional comments not posted (2)
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (invoked as PR comments)
Additionally, you can add CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Actionable comments posted: 0
Outside diff range comments (1)
build-scripts/bundle.cjs (1)
Line range hint
1-1: Update import statement to use thenode:protocol.To align with Node.js best practices, prepend
node:to the import statement for built-in modules.- const path = require("path"); + const path = require("node:path");
|
This should be good now but merge #21177 first. I can follow this up with some minor clean up:
|
|
Adding feature detection was fairly simple so that can be crossed off now. |
117b58a to
1b663ea
Compare
There was a problem hiding this comment.
Actionable comments posted: 2
Outside diff range comments (6)
build-scripts/bundle.cjs (6)
Line range hint
1-1: Use thenode:protocol for Node.js built-in modules.Using the
node:protocol is more explicit and signals that the imported module belongs to Node.js.- const path = require("path"); + const path = require("node:path");
Line range hint
222-222: Use template literals instead of string concatenation.Template literals are preferred over string concatenation for better readability and maintainability.
- return `https://raw.githubusercontent.com/home-assistant/frontend/${ref}/`;
Line range hint
243-243: Use template literals instead of string concatenation.Template literals are preferred over string concatenation for better readability and maintainability.
- __BUILD__: JSON.stringify(latestBuild ? "latest" : "es5"),
Line range hint
273-273: Use template literals instead of string concatenation.Template literals are preferred over string concatenation for better readability and maintainability.
- name: "frontend" + nameSuffix(latestBuild), + name: `frontend${nameSuffix(latestBuild)}`,
Line range hint
287-287: Use template literals instead of string concatenation.Template literals are preferred over string concatenation for better readability and maintainability.
- name: "demo" + nameSuffix(latestBuild), + name: `demo${nameSuffix(latestBuild)}`,
Line range hint
307-307: Use template literals instead of string concatenation.Template literals are preferred over string concatenation for better readability and maintainability.
- name: "cast" + nameSuffix(latestBuild), + name: `cast${nameSuffix(latestBuild)}`,
1b663ea to
87280e2
Compare
There was a problem hiding this comment.
Actionable comments posted: 0
Outside diff range, codebase verification and nitpick comments (3)
hassio/src/entrypoint.js.template (2)
Line range hint
7-16: Review the use ofnew Functionfor dynamic imports.Using
new Functionto handle imports can lead to security risks, such as code injection, if not properly sanitized. It's crucial to ensure that theentryvalues are controlled and not susceptible to external manipulation.Consider replacing
new Functionwith a more secure method of dynamic importing if possible, or ensure that the inputs (entry) are rigorously validated.
Line range hint
7-16: Ensure comprehensive error handling for dynamic imports.The current implementation uses a
try-catchblock to fall back to ES5 loading if the ES6 import fails. This is a good practice as it ensures that the application can still function if modern modules fail to load. However, it might be beneficial to log these errors for debugging and monitoring purposes.try { <% for (const entry of latestEntryJS) { %> new Function("import('<%= entry %>')")(); <% } %> } catch (err) { + console.error("Failed to load modern entries:", err); <% for (const entry of es5EntryJS) { %> loadES5("<%= entry %>"); <% } %> }Also applies to: 17-19
cast/src/html/index.html.template (1)
18-18: Google Analytics Script ReviewThe Google Analytics script is correctly implemented to track page views. However, consider the implications of user privacy and ensure compliance with GDPR if applicable.
Co-authored-by: Quentame <polletquentin74@me.com>
87280e2 to
f1214e4
Compare
|
GitHub should have an achievement award for number of conflicts fixed on a single PR... |
Breaking change
Browser requirements for serving modern (latest) builds of the frontend have been updated to include only those released in the last year or those still having high global utilization above 0.5%. As before, legacy builds will be served whenever modern requirements are not met.
Proposed change
This change implements a new and more practical way to decipher between "modern" and "legacy" browsers by:
browserslistquery to be more practical and evolve to always grab the most recent/utilized browser versions. This does for the modern builds what Redefine browser requirements for legacy (ES5) builds #16384 did for legacy.import()syntax test is kept for simplicity of these changes and as a backup for now, but I think it can be safely eliminated in order to consolidate and simplify the loading code in a future PR.This does turn off most of Babel's transforms, but only reduces the bundle by about 1%. Of course that doesn't account for the fact that the current dynamic import test technically includes some pretty old browsers that should have a bunch of polyfills, so not really a fair comparison. Also, a not-so-modest reduction might be obtained by not having to transpile class fields, but Lit's decorators are still on the stage 2 spec.
Lastly, I did try to consolidate more code in the templates. The exception was the app index because of its special treatment, but I can fix that in a follow up.
New requirements as of today would be at least (updated to reflect changes from discussion below):
* = only latest version due to limitations of CanIUse database
Modern Build Babel Plugins
@babel/preset-env:
DEBUGoptionUsing targets:
{
"android": "115",
"chrome": "109",
"edge": "115",
"firefox": "115",
"ios": "15.6",
"opera": "101",
"opera_mobile": "80",
"safari": "16.6",
"samsung": "22"
}
Using modules transform: auto
Using plugins:
transform-unicode-sets-regex { chrome < 112, firefox < 116, ios < 17, safari < 17, samsung }
bugfix/transform-firefox-class-in-computed-class-key { firefox }
proposal-class-static-block { ios < 16.4 }
syntax-private-property-in-object
syntax-class-properties
syntax-numeric-separator
syntax-nullish-coalescing-operator
syntax-optional-chaining
syntax-json-strings
syntax-optional-catch-binding
syntax-async-generators
syntax-object-rest-spread
syntax-export-namespace-from
bugfix/transform-safari-id-destructuring-collision-in-function-expression { ios < 16.3 }
syntax-dynamic-import
syntax-top-level-await
syntax-import-meta
syntax-import-attributes
Modern Build Core-JS Polyfills
The following 56 polyfills may be injected by Babel:
es.array.push { android < 122, chrome < 122, edge < 122, ios < 16.0, opera < 108, opera_mobile < 81, samsung < 26.0 }
es.array.to-reversed { chrome < 110, ios < 16.0 }
es.array.to-sorted { chrome < 110, ios < 16.0 }
es.array.to-spliced { chrome < 110, ios < 16.0 }
es.array.unshift { ios < 16.0 }
es.array.with { chrome < 110, ios < 16.0 }
es.array-buffer.detached { chrome < 114, firefox < 122, ios < 17.4, safari < 17.4, samsung < 23.0 }
es.array-buffer.transfer { chrome < 114, firefox < 122, ios < 17.4, safari < 17.4, samsung < 23.0 }
es.array-buffer.transfer-to-fixed-length { chrome < 114, firefox < 122, ios < 17.4, safari < 17.4, samsung < 23.0 }
es.map.group-by { android < 117, chrome < 117, edge < 117, firefox < 119, ios, opera < 103, safari, samsung < 24.0 }
es.object.group-by { android < 117, chrome < 117, edge < 117, firefox < 119, ios, opera < 103, safari, samsung < 24.0 }
es.promise.with-resolvers { android < 119, chrome < 119, edge < 119, firefox < 121, ios < 17.4, opera < 105, safari < 17.4, samsung < 25.0 }
es.regexp.flags { chrome < 111 }
es.set.difference.v2 { android < 123, chrome < 123, edge < 123, firefox < 127, ios, opera < 109, opera_mobile < 82, safari, samsung }
es.set.intersection.v2 { android < 123, chrome < 123, edge < 123, firefox < 127, ios, opera < 109, opera_mobile < 82, safari, samsung }
es.set.is-disjoint-from.v2 { android < 123, chrome < 123, edge < 123, firefox < 127, ios, opera < 109, opera_mobile < 82, safari, samsung }
es.set.is-subset-of.v2 { android < 123, chrome < 123, edge < 123, firefox < 127, ios, opera < 109, opera_mobile < 82, safari, samsung }
es.set.is-superset-of.v2 { android < 123, chrome < 123, edge < 123, firefox < 127, ios, opera < 109, opera_mobile < 82, safari, samsung }
es.set.symmetric-difference.v2 { android < 123, chrome < 123, edge < 123, firefox < 127, ios, opera < 109, opera_mobile < 82, safari, samsung }
es.set.union.v2 { android < 123, chrome < 123, edge < 123, firefox < 127, ios, opera < 109, opera_mobile < 82, safari, samsung }
es.string.is-well-formed { chrome < 111, firefox < 119, ios < 16.4 }
es.string.to-well-formed { chrome < 111, firefox < 119, ios < 16.4 }
es.typed-array.to-reversed { chrome < 110, ios < 16.0 }
es.typed-array.to-sorted { chrome < 110, ios < 16.0 }
es.typed-array.with { chrome < 110, ios < 16.4 }
esnext.suppressed-error.constructor { android, chrome, edge, firefox, ios, opera, opera_mobile, safari, samsung }
esnext.array.from-async { android < 121, chrome < 121, edge < 121, ios, opera < 107, opera_mobile < 81, safari, samsung < 25.0 }
esnext.array.group { android, chrome, edge, firefox, ios, opera, opera_mobile, safari, samsung }
esnext.array.group-to-map { android, chrome, edge, firefox, ios, opera, opera_mobile, safari, samsung }
esnext.iterator.constructor { android < 122, chrome < 122, edge < 122, firefox, ios, opera < 108, opera_mobile < 81, safari, samsung < 26.0 }
esnext.iterator.drop { android < 122, chrome < 122, edge < 122, firefox, ios, opera < 108, opera_mobile < 81, safari, samsung < 26.0 }
esnext.iterator.every { android < 122, chrome < 122, edge < 122, firefox, ios, opera < 108, opera_mobile < 81, safari, samsung < 26.0 }
esnext.iterator.filter { android < 122, chrome < 122, edge < 122, firefox, ios, opera < 108, opera_mobile < 81, safari, samsung < 26.0 }
esnext.iterator.find { android < 122, chrome < 122, edge < 122, firefox, ios, opera < 108, opera_mobile < 81, safari, samsung < 26.0 }
esnext.iterator.flat-map { android < 122, chrome < 122, edge < 122, firefox, ios, opera < 108, opera_mobile < 81, safari, samsung < 26.0 }
esnext.iterator.for-each { android < 122, chrome < 122, edge < 122, firefox, ios, opera < 108, opera_mobile < 81, safari, samsung < 26.0 }
esnext.iterator.from { android < 122, chrome < 122, edge < 122, firefox, ios, opera < 108, opera_mobile < 81, safari, samsung < 26.0 }
esnext.iterator.map { android < 122, chrome < 122, edge < 122, firefox, ios, opera < 108, opera_mobile < 81, safari, samsung < 26.0 }
esnext.iterator.reduce { android < 122, chrome < 122, edge < 122, firefox, ios, opera < 108, opera_mobile < 81, safari, samsung < 26.0 }
esnext.iterator.some { android < 122, chrome < 122, edge < 122, firefox, ios, opera < 108, opera_mobile < 81, safari, samsung < 26.0 }
esnext.iterator.take { android < 122, chrome < 122, edge < 122, firefox, ios, opera < 108, opera_mobile < 81, safari, samsung < 26.0 }
esnext.iterator.to-array { android < 122, chrome < 122, edge < 122, firefox, ios, opera < 108, opera_mobile < 81, safari, samsung < 26.0 }
esnext.json.is-raw-json { chrome < 114, firefox, ios, safari, samsung < 23.0 }
esnext.json.parse { chrome < 114, firefox, ios, safari, samsung < 23.0 }
esnext.json.raw-json { chrome < 114, firefox, ios, safari, samsung < 23.0 }
esnext.symbol.async-dispose { android, chrome, edge, firefox, ios, opera, opera_mobile, safari, samsung }
esnext.symbol.dispose { android < 125, chrome < 125, edge < 125, firefox, ios, opera < 111, opera_mobile, safari, samsung }
esnext.symbol.metadata { android, chrome, edge, firefox, ios, opera, opera_mobile, safari, samsung }
web.dom-exception.stack { android, chrome, edge, ios, opera, opera_mobile, safari, samsung }
web.immediate { android, chrome, edge, firefox, ios, opera, opera_mobile, safari, samsung }
web.structured-clone { android, chrome, edge, firefox, ios, opera, opera_mobile, safari, samsung }
web.url.can-parse { android < 120, chrome < 120, edge < 120, ios < 17.0, opera < 106, safari < 17.0, samsung < 25.0 }
web.url.parse { android < 126, chrome < 126, edge < 126, firefox < 126, ios, opera < 112, opera_mobile, safari, samsung }
web.url-search-params.delete { android < 118, chrome < 118, edge < 118, ios < 17.0, opera < 104, safari < 17.0, samsung < 25.0 }
web.url-search-params.has { android < 118, chrome < 118, edge < 118, ios < 17.0, opera < 104, safari < 17.0, samsung < 25.0 }
web.url-search-params.size { chrome < 113, ios < 17.0, safari < 17.0, samsung < 23.0 }
Legacy Build Babel Plugins
@babel/preset-env:
DEBUGoptionUsing targets:
{
"android": "60",
"chrome": "60",
"edge": "16",
"firefox": "52",
"ie": "11",
"ios": "10.3",
"opera": "47",
"opera_mobile": "80",
"safari": "11",
"samsung": "4"
}
Using modules transform: auto
Using plugins:
transform-unicode-sets-regex { android, chrome < 112, edge < 112, firefox < 116, ie, ios < 17, opera < 98, safari < 17, samsung }
proposal-class-static-block { android, chrome < 94, edge < 94, firefox < 93, ie, ios < 16.4, opera < 80, safari < 16.4, samsung < 17 }
proposal-private-property-in-object { android, chrome < 91, edge < 91, firefox < 90, ie, ios < 15, opera < 77, safari < 15, samsung < 16 }
proposal-class-properties { android, chrome < 74, edge < 79, firefox < 90, ie, ios < 14.5, opera < 62, safari < 14.1, samsung < 11 }
proposal-private-methods { android, chrome < 84, edge < 84, firefox < 90, ie, ios < 15, opera < 70, safari < 15, samsung < 14 }
proposal-numeric-separator { android, chrome < 75, edge < 79, firefox < 70, ie, ios < 13, opera < 62, safari < 13, samsung < 11 }
proposal-logical-assignment-operators { android, chrome < 85, edge < 85, firefox < 79, ie, ios < 14, opera < 71, safari < 14, samsung < 14 }
proposal-nullish-coalescing-operator { android, chrome < 80, edge < 80, firefox < 72, ie, ios < 13.4, opera < 67, safari < 13.1, samsung < 13 }
proposal-optional-chaining { android, chrome < 80, edge < 80, firefox < 74, ie, ios < 13.4, opera < 67, safari < 13.1, samsung < 13 }
proposal-json-strings { android, chrome < 66, edge < 79, firefox < 62, ie, ios < 12, opera < 53, safari < 12, samsung < 9 }
proposal-optional-catch-binding { android, chrome < 66, edge < 79, firefox < 58, ie, ios < 11.3, opera < 53, safari < 11.1, samsung < 9 }
transform-parameters { firefox < 53, ie, samsung < 5 }
proposal-async-generator-functions { android, chrome < 63, edge < 79, firefox < 57, ie, ios < 12, opera < 50, safari < 12, samsung < 8 }
proposal-object-rest-spread { edge < 79, firefox < 55, ie, ios < 11.3, safari < 11.1, samsung < 8 }
transform-dotall-regex { android, chrome < 62, edge < 79, firefox < 78, ie, ios < 11.3, opera < 49, safari < 11.1, samsung < 8 }
proposal-unicode-property-regex { android, chrome < 64, edge < 79, firefox < 78, ie, ios < 11.3, opera < 51, safari < 11.1, samsung < 9 }
transform-named-capturing-groups-regex { android, chrome < 64, edge < 79, firefox < 78, ie, ios < 11.3, opera < 51, safari < 11.1, samsung < 9 }
transform-async-to-generator { ie, samsung < 6 }
transform-exponentiation-operator { ie, samsung < 6 }
transform-template-literals { ie }
transform-literals { firefox < 53, ie }
transform-function-name { firefox < 53, ie, samsung < 5 }
transform-arrow-functions { ie, samsung < 5 }
transform-classes { ie, samsung < 5 }
transform-object-super { ie, samsung < 5 }
transform-shorthand-properties { ie }
transform-duplicate-keys { ie }
transform-computed-properties { ie }
transform-for-of { firefox < 53, ie, samsung < 5 }
transform-sticky-regex { ie, samsung < 5 }
transform-unicode-escapes { firefox < 53, ie }
transform-unicode-regex { ie, ios < 12, safari < 12, samsung < 5 }
transform-spread { ie, samsung < 5 }
transform-destructuring { firefox < 53, ie, samsung < 5 }
transform-block-scoping { firefox < 53, ie, samsung < 5 }
transform-typeof-symbol { ie }
transform-new-target { ie, samsung < 5 }
transform-regenerator { firefox < 53, ie, samsung < 5 }
proposal-export-namespace-from { android < 72, chrome < 72, edge < 79, firefox < 80, ie, ios < 14.5, opera < 60, safari < 14.1, samsung < 11.0 }
syntax-dynamic-import
syntax-top-level-await
syntax-import-meta
syntax-import-attributes
Legacy Build Core-JS Polyfills
The following 273 polyfills may be injected by Babel:
es.symbol { ie, samsung < 5.0 }
es.symbol.description { android < 70, chrome < 70, edge < 79, firefox < 63, ie, ios < 12.2, opera < 57, safari < 12.1, samsung < 10.0 }
es.symbol.async-iterator { android < 63, chrome < 63, edge < 79, firefox < 55, ie, ios < 12.0, opera < 50, safari < 12.0, samsung < 8.0 }
es.symbol.has-instance { ie, samsung < 5.0 }
es.symbol.is-concat-spreadable { ie, samsung < 5.0 }
es.symbol.iterator { ie }
es.symbol.match { edge < 79, ie, samsung < 5.0 }
es.symbol.match-all { android < 73, chrome < 73, edge < 79, firefox < 67, ie, ios < 13.0, opera < 60, safari < 13, samsung < 11.0 }
es.symbol.replace { edge < 79, ie, samsung < 5.0 }
es.symbol.search { edge < 79, ie, samsung < 5.0 }
es.symbol.species { ie, samsung < 5.0 }
es.symbol.split { edge < 79, ie, samsung < 5.0 }
es.symbol.to-primitive { ie, samsung < 5.0 }
es.symbol.to-string-tag { ie, samsung < 5.0 }
es.symbol.unscopables { ie }
es.error.cause { android < 94, chrome < 94, edge < 94, firefox < 91, ie, ios < 15.0, opera < 80, safari < 15.0, samsung < 17.0 }
es.aggregate-error { android < 85, chrome < 85, edge < 85, firefox < 79, ie, ios < 14.0, opera < 71, safari < 14.0, samsung < 14.0 }
es.aggregate-error.cause { android < 94, chrome < 94, edge < 94, firefox < 91, ie, ios < 15.0, opera < 80, safari < 15.0, samsung < 17.0 }
es.array.at { android < 92, chrome < 92, edge < 92, firefox < 90, ie, ios < 15.4, opera < 78, safari < 15.4, samsung < 16.0 }
es.array.concat { ie, samsung < 5.0 }
es.array.copy-within { ie, samsung < 5.0 }
es.array.fill { ie, samsung < 5.0 }
es.array.filter { ie, samsung < 5.0 }
es.array.find { ie, samsung < 5.0 }
es.array.find-index { ie, samsung < 5.0 }
es.array.find-last { android < 97, chrome < 97, edge < 97, firefox < 104, ie, ios < 15.4, opera < 83, safari < 15.4, samsung < 18.0 }
es.array.find-last-index { android < 97, chrome < 97, edge < 97, firefox < 104, ie, ios < 15.4, opera < 83, safari < 15.4, samsung < 18.0 }
es.array.flat { android < 69, chrome < 69, edge < 79, firefox < 62, ie, ios < 12.0, opera < 56, safari < 12.0, samsung < 10.0 }
es.array.flat-map { android < 69, chrome < 69, edge < 79, firefox < 62, ie, ios < 12.0, opera < 56, safari < 12.0, samsung < 10.0 }
es.array.from { firefox < 53, ie, samsung < 5.0 }
es.array.includes { firefox < 102, ie, samsung < 6.0 }
es.array.index-of { samsung < 5.0 }
es.array.iterator { android < 66, chrome < 66, firefox < 60, ie, opera < 53, samsung < 9.0 }
es.array.join { ie }
es.array.last-index-of { samsung < 5.0 }
es.array.map { ie, samsung < 5.0 }
es.array.of { ie, samsung < 5.0 }
es.array.push { android < 122, chrome < 122, edge < 122, firefox < 55, ie, ios < 16.0, opera < 108, opera_mobile < 81, safari < 16.0, samsung < 26.0 }
es.array.reduce { android < 83, chrome < 83, opera < 69, samsung < 13.0 }
es.array.reduce-right { android < 83, chrome < 83, opera < 69, samsung < 13.0 }
es.array.reverse { ios < 12.2, safari < 12.0.2 }
es.array.slice { ie, samsung < 5.0 }
es.array.sort { android < 70, chrome < 70, edge < 79, ie, ios < 12.0, opera < 57, safari < 12.0, samsung < 10.0 }
es.array.species { ie, samsung < 5.0 }
es.array.splice { ie, samsung < 5.0 }
es.array.to-reversed { android < 110, chrome < 110, edge < 110, firefox < 115, ie, ios < 16.0, opera < 96, safari < 16.0, samsung < 21.0 }
es.array.to-sorted { android < 110, chrome < 110, edge < 110, firefox < 115, ie, ios < 16.0, opera < 96, safari < 16.0, samsung < 21.0 }
es.array.to-spliced { android < 110, chrome < 110, edge < 110, firefox < 115, ie, ios < 16.0, opera < 96, safari < 16.0, samsung < 21.0 }
es.array.unscopables.flat { android < 73, chrome < 73, edge < 79, firefox < 67, ie, ios < 13.0, opera < 60, safari < 13, samsung < 11.0 }
es.array.unscopables.flat-map { android < 73, chrome < 73, edge < 79, firefox < 67, ie, ios < 13.0, opera < 60, safari < 13, samsung < 11.0 }
es.array.unshift { android < 71, chrome < 71, ios < 16.0, opera < 58, safari < 16.0, samsung < 10.0 }
es.array.with { android < 110, chrome < 110, edge < 110, firefox < 115, ie, ios < 16.0, opera < 96, safari < 16.0, samsung < 21.0 }
es.array-buffer.constructor { ie, ios < 12.0, safari < 12.0 }
es.array-buffer.slice { ios < 12.2, safari < 12.1 }
es.array-buffer.detached { android < 114, chrome < 114, edge < 114, firefox < 122, ie, ios < 17.4, opera < 100, safari < 17.4, samsung < 23.0 }
es.array-buffer.transfer { android < 114, chrome < 114, edge < 114, firefox < 122, ie, ios < 17.4, opera < 100, safari < 17.4, samsung < 23.0 }
es.array-buffer.transfer-to-fixed-length { android < 114, chrome < 114, edge < 114, firefox < 122, ie, ios < 17.4, opera < 100, safari < 17.4, samsung < 23.0 }
es.date.to-primitive { ie, samsung < 5.0 }
es.function.has-instance { ie, samsung < 5.0 }
es.function.name { ie }
es.global-this { android < 71, chrome < 71, edge < 79, firefox < 65, ie, ios < 12.2, opera < 58, safari < 12.1, samsung < 10.0 }
es.json.stringify { android < 72, chrome < 72, edge < 79, firefox < 64, ie, ios < 12.2, opera < 59, safari < 12.1, samsung < 11.0 }
es.json.to-string-tag { ie, samsung < 5.0 }
es.map { firefox < 53, ie, samsung < 5.0 }
es.map.group-by { android < 117, chrome < 117, edge < 117, firefox < 119, ie, ios, opera < 103, safari, samsung < 24.0 }
es.math.acosh { ie, samsung < 6.0 }
es.math.asinh { ie }
es.math.atanh { ie }
es.math.cbrt { ie }
es.math.clz32 { ie }
es.math.cosh { ie }
es.math.expm1 { ie }
es.math.fround { ie }
es.math.hypot { android < 78, chrome < 78, ie, opera < 65, samsung < 12.0 }
es.math.imul { ie }
es.math.log10 { ie }
es.math.log1p { ie }
es.math.log2 { ie }
es.math.sign { ie }
es.math.sinh { ie }
es.math.tanh { ie }
es.math.to-string-tag { ie, samsung < 5.0 }
es.math.trunc { ie }
es.number.constructor { ie }
es.number.epsilon { ie }
es.number.is-finite { ie }
es.number.is-integer { ie }
es.number.is-nan { ie }
es.number.is-safe-integer { ie }
es.number.max-safe-integer { ie }
es.number.min-safe-integer { ie }
es.number.parse-float { edge < 79, ie, ios < 11.0 }
es.number.parse-int { edge < 79, ie }
es.number.to-exponential { edge < 18, firefox < 87, ie, ios < 11.0, samsung < 5.0 }
es.number.to-fixed { edge < 79, ie }
es.object.assign { edge < 79, ie, samsung < 5.0 }
es.object.define-getter { android < 62, chrome < 62, ie, opera < 49, samsung < 8.0 }
es.object.define-setter { android < 62, chrome < 62, ie, opera < 49, samsung < 8.0 }
es.object.entries { ie, samsung < 6.0 }
es.object.freeze { ie }
es.object.from-entries { android < 73, chrome < 73, edge < 79, firefox < 63, ie, ios < 12.2, opera < 60, safari < 12.1, samsung < 11.0 }
es.object.get-own-property-descriptor { ie }
es.object.get-own-property-descriptors { ie, samsung < 6.0 }
es.object.get-own-property-names { ie }
es.object.get-prototype-of { ie }
es.object.group-by { android < 117, chrome < 117, edge < 117, firefox < 119, ie, ios, opera < 103, safari, samsung < 24.0 }
es.object.has-own { android < 93, chrome < 93, edge < 93, firefox < 92, ie, ios < 15.4, opera < 79, safari < 15.4, samsung < 17.0 }
es.object.is { ie }
es.object.is-extensible { ie }
es.object.is-frozen { ie }
es.object.is-sealed { ie }
es.object.keys { ie }
es.object.lookup-getter { android < 62, chrome < 62, ie, opera < 49, samsung < 8.0 }
es.object.lookup-setter { android < 62, chrome < 62, ie, opera < 49, samsung < 8.0 }
es.object.prevent-extensions { ie }
es.object.seal { ie }
es.object.to-string { ie, samsung < 5.0 }
es.object.values { ie, samsung < 6.0 }
es.parse-float { edge < 74 }
es.parse-int { edge < 74 }
es.promise { android < 67, chrome < 67, edge < 79, firefox < 69, ie, ios < 11.0, opera < 54, samsung < 9.0 }
es.promise.all-settled { android < 76, chrome < 76, edge < 79, firefox < 71, ie, ios < 13.0, opera < 63, safari < 13, samsung < 12.0 }
es.promise.any { android < 85, chrome < 85, edge < 85, firefox < 79, ie, ios < 14.0, opera < 71, safari < 14.0, samsung < 14.0 }
es.promise.finally { android < 67, chrome < 67, edge < 79, firefox < 69, ie, ios < 13.2.3, opera < 54, safari < 13.0.3, samsung < 9.0 }
es.promise.with-resolvers { android < 119, chrome < 119, edge < 119, firefox < 121, ie, ios < 17.4, opera < 105, safari < 17.4, samsung < 25.0 }
es.reflect.apply { ie, samsung < 5.0 }
es.reflect.construct { ie, samsung < 5.0 }
es.reflect.define-property { ie, samsung < 5.0 }
es.reflect.delete-property { ie, samsung < 5.0 }
es.reflect.get { ie, samsung < 5.0 }
es.reflect.get-own-property-descriptor { ie, samsung < 5.0 }
es.reflect.get-prototype-of { ie, samsung < 5.0 }
es.reflect.has { ie, samsung < 5.0 }
es.reflect.is-extensible { ie, samsung < 5.0 }
es.reflect.own-keys { ie, samsung < 5.0 }
es.reflect.prevent-extensions { ie, samsung < 5.0 }
es.reflect.set { edge < 79, ie, samsung < 5.0 }
es.reflect.set-prototype-of { ie, samsung < 5.0 }
es.reflect.to-string-tag { android < 86, chrome < 86, edge < 86, firefox < 82, ie, ios < 14.0, opera < 72, safari < 14.0, samsung < 14.0 }
es.regexp.constructor { android < 64, chrome < 64, edge < 79, firefox < 78, ie, ios < 11.3, opera < 51, safari < 11.1, samsung < 9.0 }
es.regexp.dot-all { android < 62, chrome < 62, edge < 79, firefox < 78, ie, ios < 11.3, opera < 49, safari < 11.1, samsung < 8.0 }
es.regexp.exec { android < 64, chrome < 64, edge < 79, firefox < 78, ie, ios < 11.3, opera < 51, safari < 11.1, samsung < 9.0 }
es.regexp.flags { android < 111, chrome < 111, edge < 111, firefox < 78, ie, ios < 11.3, opera < 97, safari < 11.1, samsung < 22.0 }
es.regexp.sticky { ie, samsung < 5.0 }
es.regexp.test { edge < 79, ie, samsung < 5.0 }
es.regexp.to-string { edge < 79, ie, samsung < 5.0 }
es.set { firefox < 53, ie, samsung < 5.0 }
es.set.difference.v2 { android < 123, chrome < 123, edge < 123, firefox < 127, ie, ios, opera < 109, opera_mobile < 82, safari, samsung }
es.set.intersection.v2 { android < 123, chrome < 123, edge < 123, firefox < 127, ie, ios, opera < 109, opera_mobile < 82, safari, samsung }
es.set.is-disjoint-from.v2 { android < 123, chrome < 123, edge < 123, firefox < 127, ie, ios, opera < 109, opera_mobile < 82, safari, samsung }
es.set.is-subset-of.v2 { android < 123, chrome < 123, edge < 123, firefox < 127, ie, ios, opera < 109, opera_mobile < 82, safari, samsung }
es.set.is-superset-of.v2 { android < 123, chrome < 123, edge < 123, firefox < 127, ie, ios, opera < 109, opera_mobile < 82, safari, samsung }
es.set.symmetric-difference.v2 { android < 123, chrome < 123, edge < 123, firefox < 127, ie, ios, opera < 109, opera_mobile < 82, safari, samsung }
es.set.union.v2 { android < 123, chrome < 123, edge < 123, firefox < 127, ie, ios, opera < 109, opera_mobile < 82, safari, samsung }
es.string.at-alternative { android < 92, chrome < 92, edge < 92, firefox < 90, ie, ios < 15.4, opera < 78, safari < 15.4, samsung < 16.0 }
es.string.code-point-at { ie }
es.string.ends-with { edge < 79, ie, samsung < 5.0 }
es.string.from-code-point { ie }
es.string.includes { edge < 79, ie, samsung < 5.0 }
es.string.is-well-formed { android < 111, chrome < 111, edge < 111, firefox < 119, ie, ios < 16.4, opera < 97, safari < 16.4, samsung < 22.0 }
es.string.iterator { ie }
es.string.match { edge < 79, ie, samsung < 5.0 }
es.string.match-all { android < 80, chrome < 80, edge < 80, firefox < 73, ie, ios < 13.4, opera < 67, safari < 13.1, samsung < 13.0 }
es.string.pad-end { ie, ios < 11.0, samsung < 7.0 }
es.string.pad-start { ie, ios < 11.0, samsung < 7.0 }
es.string.raw { ie }
es.string.repeat { ie }
es.string.replace { android < 64, chrome < 64, edge < 79, firefox < 78, ie, ios < 14.0, opera < 51, safari < 14.0, samsung < 9.0 }
es.string.replace-all { android < 85, chrome < 85, edge < 85, firefox < 77, ie, ios < 13.4, opera < 71, safari < 13.1, samsung < 14.0 }
es.string.search { edge < 79, ie, samsung < 5.0 }
es.string.split { edge < 79, ie, samsung < 6.0 }
es.string.starts-with { edge < 79, ie, samsung < 5.0 }
es.string.to-well-formed { android < 111, chrome < 111, edge < 111, firefox < 119, ie, ios < 16.4, opera < 97, safari < 16.4, samsung < 22.0 }
es.string.trim { ie, ios < 12.2, safari < 12.1, samsung < 7.0 }
es.string.trim-end { android < 66, chrome < 66, edge < 79, firefox < 61, ie, ios < 12.2, opera < 53, safari < 12.1, samsung < 9.0 }
es.string.trim-start { android < 66, chrome < 66, edge < 79, firefox < 61, ie, ios < 12.0, opera < 53, safari < 12.0, samsung < 9.0 }
es.string.anchor { ie }
es.string.big { ie }
es.string.blink { ie }
es.string.bold { ie }
es.string.fixed { ie }
es.string.fontcolor { ie }
es.string.fontsize { ie }
es.string.italics { ie }
es.string.link { ie }
es.string.small { ie }
es.string.strike { ie }
es.string.sub { ie }
es.string.sup { ie }
es.typed-array.float32-array { firefox < 55, ie, ios < 14.0, safari < 14.0, samsung < 6.0 }
es.typed-array.float64-array { firefox < 55, ie, ios < 14.0, safari < 14.0, samsung < 6.0 }
es.typed-array.int8-array { firefox < 55, ie, ios < 14.0, safari < 14.0, samsung < 6.0 }
es.typed-array.int16-array { firefox < 55, ie, ios < 14.0, safari < 14.0, samsung < 6.0 }
es.typed-array.int32-array { firefox < 55, ie, ios < 14.0, safari < 14.0, samsung < 6.0 }
es.typed-array.uint8-array { firefox < 55, ie, ios < 14.0, safari < 14.0, samsung < 6.0 }
es.typed-array.uint8-clamped-array { firefox < 55, ie, ios < 14.0, safari < 14.0, samsung < 6.0 }
es.typed-array.uint16-array { firefox < 55, ie, ios < 14.0, safari < 14.0, samsung < 6.0 }
es.typed-array.uint32-array { firefox < 55, ie, ios < 14.0, safari < 14.0, samsung < 6.0 }
es.typed-array.at { android < 92, chrome < 92, edge < 92, firefox < 90, ie, ios < 15.4, opera < 78, safari < 15.4, samsung < 16.0 }
es.typed-array.copy-within { ie, samsung < 5.0 }
es.typed-array.every { ie, samsung < 5.0 }
es.typed-array.fill { edge < 79, firefox < 55, ie, ios < 14.5, safari < 14.1, samsung < 7.0 }
es.typed-array.filter { ie, samsung < 5.0 }
es.typed-array.find { ie, samsung < 5.0 }
es.typed-array.find-index { ie, samsung < 5.0 }
es.typed-array.find-last { android < 97, chrome < 97, edge < 97, firefox < 104, ie, ios < 15.4, opera < 83, safari < 15.4, samsung < 18.0 }
es.typed-array.find-last-index { android < 97, chrome < 97, edge < 97, firefox < 104, ie, ios < 15.4, opera < 83, safari < 15.4, samsung < 18.0 }
es.typed-array.for-each { ie, samsung < 5.0 }
es.typed-array.from { firefox < 55, ie, ios < 14.0, safari < 14.0, samsung < 6.0 }
es.typed-array.includes { ie, samsung < 5.0 }
es.typed-array.index-of { ie, samsung < 5.0 }
es.typed-array.iterator { ie, samsung < 5.0 }
es.typed-array.join { ie, samsung < 5.0 }
es.typed-array.last-index-of { ie, samsung < 5.0 }
es.typed-array.map { ie, samsung < 5.0 }
es.typed-array.of { firefox < 55, ie, ios < 14.0, safari < 14.0, samsung < 6.0 }
es.typed-array.reduce { ie, samsung < 5.0 }
es.typed-array.reduce-right { ie, samsung < 5.0 }
es.typed-array.reverse { ie, samsung < 5.0 }
es.typed-array.set { android < 95, chrome < 95, edge < 95, firefox < 54, ie, ios < 14.5, opera < 81, safari < 14.1, samsung < 17.0 }
es.typed-array.slice { ie, samsung < 5.0 }
es.typed-array.some { ie, samsung < 5.0 }
es.typed-array.sort { android < 74, chrome < 74, edge < 79, firefox < 67, ie, ios < 14.5, opera < 61, safari < 14.1, samsung < 11.0 }
es.typed-array.subarray { ie }
es.typed-array.to-locale-string { edge < 79, ie, samsung < 5.0 }
es.typed-array.to-reversed { android < 110, chrome < 110, edge < 110, firefox < 115, ie, ios < 16.0, opera < 96, safari < 16.0, samsung < 21.0 }
es.typed-array.to-sorted { android < 110, chrome < 110, edge < 110, firefox < 115, ie, ios < 16.0, opera < 96, safari < 16.0, samsung < 21.0 }
es.typed-array.to-string { ie, samsung < 5.0 }
es.typed-array.with { android < 110, chrome < 110, edge < 110, firefox < 115, ie, ios < 16.4, opera < 96, safari < 16.4, samsung < 21.0 }
es.weak-map { edge < 79, firefox < 53, ie, samsung < 5.0 }
es.weak-set { firefox < 53, ie, samsung < 5.0 }
esnext.suppressed-error.constructor { android, chrome, edge, firefox, ie, ios, opera, opera_mobile, safari, samsung }
esnext.array.from-async { android < 121, chrome < 121, edge < 121, firefox < 115, ie, ios, opera < 107, opera_mobile < 81, safari, samsung < 25.0 }
esnext.array.group { android, chrome, edge, firefox, ie, ios, opera, opera_mobile, safari, samsung }
esnext.array.group-to-map { android, chrome, edge, firefox, ie, ios, opera, opera_mobile, safari, samsung }
esnext.iterator.constructor { android < 122, chrome < 122, edge < 122, firefox, ie, ios, opera < 108, opera_mobile < 81, safari, samsung < 26.0 }
esnext.iterator.drop { android < 122, chrome < 122, edge < 122, firefox, ie, ios, opera < 108, opera_mobile < 81, safari, samsung < 26.0 }
esnext.iterator.every { android < 122, chrome < 122, edge < 122, firefox, ie, ios, opera < 108, opera_mobile < 81, safari, samsung < 26.0 }
esnext.iterator.filter { android < 122, chrome < 122, edge < 122, firefox, ie, ios, opera < 108, opera_mobile < 81, safari, samsung < 26.0 }
esnext.iterator.find { android < 122, chrome < 122, edge < 122, firefox, ie, ios, opera < 108, opera_mobile < 81, safari, samsung < 26.0 }
esnext.iterator.flat-map { android < 122, chrome < 122, edge < 122, firefox, ie, ios, opera < 108, opera_mobile < 81, safari, samsung < 26.0 }
esnext.iterator.for-each { android < 122, chrome < 122, edge < 122, firefox, ie, ios, opera < 108, opera_mobile < 81, safari, samsung < 26.0 }
esnext.iterator.from { android < 122, chrome < 122, edge < 122, firefox, ie, ios, opera < 108, opera_mobile < 81, safari, samsung < 26.0 }
esnext.iterator.map { android < 122, chrome < 122, edge < 122, firefox, ie, ios, opera < 108, opera_mobile < 81, safari, samsung < 26.0 }
esnext.iterator.reduce { android < 122, chrome < 122, edge < 122, firefox, ie, ios, opera < 108, opera_mobile < 81, safari, samsung < 26.0 }
esnext.iterator.some { android < 122, chrome < 122, edge < 122, firefox, ie, ios, opera < 108, opera_mobile < 81, safari, samsung < 26.0 }
esnext.iterator.take { android < 122, chrome < 122, edge < 122, firefox, ie, ios, opera < 108, opera_mobile < 81, safari, samsung < 26.0 }
esnext.iterator.to-array { android < 122, chrome < 122, edge < 122, firefox, ie, ios, opera < 108, opera_mobile < 81, safari, samsung < 26.0 }
esnext.json.is-raw-json { android < 114, chrome < 114, edge < 114, firefox, ie, ios, opera < 100, safari, samsung < 23.0 }
esnext.json.parse { android < 114, chrome < 114, edge < 114, firefox, ie, ios, opera < 100, safari, samsung < 23.0 }
esnext.json.raw-json { android < 114, chrome < 114, edge < 114, firefox, ie, ios, opera < 100, safari, samsung < 23.0 }
esnext.symbol.async-dispose { android, chrome, edge, firefox, ie, ios, opera, opera_mobile, safari, samsung }
esnext.symbol.dispose { android < 125, chrome < 125, edge < 125, firefox, ie, ios, opera < 111, opera_mobile, safari, samsung }
esnext.symbol.metadata { android, chrome, edge, firefox, ie, ios, opera, opera_mobile, safari, samsung }
web.atob { ie }
web.btoa { ie }
web.dom-collections.for-each { ie, samsung < 7.0 }
web.dom-collections.iterator { android < 66, chrome < 66, edge < 79, firefox < 60, ie, ios < 13.4, opera < 53, safari < 13.1, samsung < 9.0 }
web.dom-exception.constructor { edge < 79, ie, ios < 11.3, safari < 11.1, samsung < 5.0 }
web.dom-exception.stack { android, chrome, edge, ie, ios, opera, opera_mobile, safari, samsung }
web.dom-exception.to-string-tag { edge < 79, ie, ios < 11.3, safari < 11.1, samsung < 5.0 }
web.immediate { android, chrome, edge, firefox, ios, opera, opera_mobile, safari, samsung }
web.queue-microtask { android < 71, chrome < 71, edge < 79, firefox < 69, ie, ios < 12.2, opera < 58, safari < 12.1, samsung < 10.0 }
web.self { android < 86, chrome < 86, edge < 86, ie, opera < 72, samsung < 14.0 }
web.structured-clone { android, chrome, edge, firefox, ie, ios, opera, opera_mobile, safari, samsung }
web.url { android < 67, chrome < 67, edge < 79, firefox < 57, ie, ios < 14.0, opera < 54, safari < 14.0, samsung < 9.0 }
web.url.can-parse { android < 120, chrome < 120, edge < 120, firefox < 115, ie, ios < 17.0, opera < 106, safari < 17.0, samsung < 25.0 }
web.url.parse { android < 126, chrome < 126, edge < 126, firefox < 126, ie, ios, opera < 112, opera_mobile, safari, samsung }
web.url.to-json { android < 71, chrome < 71, edge < 79, firefox < 57, ie, ios < 14.0, opera < 58, safari < 14.0, samsung < 10.0 }
web.url-search-params { android < 67, chrome < 67, edge < 79, firefox < 57, ie, ios < 14.0, opera < 54, safari < 14.0, samsung < 9.0 }
web.url-search-params.delete { android < 118, chrome < 118, edge < 118, firefox < 115, ie, ios < 17.0, opera < 104, safari < 17.0, samsung < 25.0 }
web.url-search-params.has { android < 118, chrome < 118, edge < 118, firefox < 115, ie, ios < 17.0, opera < 104, safari < 17.0, samsung < 25.0 }
web.url-search-params.size { android < 113, chrome < 113, edge < 113, firefox < 112, ie, ios < 17.0, opera < 99, safari < 17.0, samsung < 23.0 }
Type of change
Example configuration
Additional information
Checklist
If user exposed functionality or configuration variables are added/changed:
Summary by CodeRabbit
New Features
Chores
browserslist-useragent-regexp.These updates aim to provide a smoother, faster experience across a wider range of browsers while maintaining support for older versions.