lighthouse 12.4.0 → 12.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (164) hide show
  1. package/core/audits/audit.js +3 -1
  2. package/core/audits/bootup-time.js +1 -1
  3. package/core/audits/byte-efficiency/duplicated-javascript.js +1 -1
  4. package/core/audits/byte-efficiency/efficient-animated-content.js +1 -1
  5. package/core/audits/byte-efficiency/legacy-javascript.d.ts +0 -65
  6. package/core/audits/byte-efficiency/legacy-javascript.js +11 -363
  7. package/core/audits/byte-efficiency/modern-image-formats.js +1 -1
  8. package/core/audits/byte-efficiency/offscreen-images.js +4 -3
  9. package/core/audits/byte-efficiency/render-blocking-resources.js +6 -3
  10. package/core/audits/byte-efficiency/unminified-css.js +2 -1
  11. package/core/audits/byte-efficiency/unminified-javascript.js +2 -1
  12. package/core/audits/byte-efficiency/unused-css-rules.js +1 -1
  13. package/core/audits/byte-efficiency/unused-javascript.js +2 -2
  14. package/core/audits/byte-efficiency/uses-long-cache-ttl.js +1 -1
  15. package/core/audits/byte-efficiency/uses-optimized-images.js +1 -1
  16. package/core/audits/byte-efficiency/uses-responsive-images.js +1 -1
  17. package/core/audits/byte-efficiency/uses-text-compression.js +2 -1
  18. package/core/audits/critical-request-chains.js +5 -3
  19. package/core/audits/dobetterweb/dom-size.js +1 -1
  20. package/core/audits/dobetterweb/uses-http2.js +1 -1
  21. package/core/audits/insights/cls-culprits-insight.js +1 -1
  22. package/core/audits/insights/document-latency-insight.js +1 -1
  23. package/core/audits/insights/dom-size-insight.js +1 -1
  24. package/core/audits/insights/{long-critical-network-tree-insight.d.ts → duplicated-javascript-insight.d.ts} +3 -3
  25. package/core/audits/insights/duplicated-javascript-insight.js +54 -0
  26. package/core/audits/insights/font-display-insight.js +8 -7
  27. package/core/audits/insights/forced-reflow-insight.d.ts +10 -0
  28. package/core/audits/insights/forced-reflow-insight.js +64 -12
  29. package/core/audits/insights/image-delivery-insight.js +9 -10
  30. package/core/audits/insights/insight-audit.js +9 -4
  31. package/core/audits/insights/interaction-to-next-paint-insight.js +1 -1
  32. package/core/audits/insights/lcp-discovery-insight.js +1 -1
  33. package/core/audits/insights/lcp-phases-insight.js +1 -1
  34. package/core/audits/insights/network-dependency-tree-insight.d.ts +11 -0
  35. package/core/audits/insights/{long-critical-network-tree-insight.js → network-dependency-tree-insight.js} +7 -7
  36. package/core/audits/insights/render-blocking-insight.js +1 -1
  37. package/core/audits/insights/slow-css-selector-insight.js +1 -1
  38. package/core/audits/insights/third-parties-insight.js +1 -1
  39. package/core/audits/insights/use-cache-insight.d.ts +11 -0
  40. package/core/audits/insights/use-cache-insight.js +61 -0
  41. package/core/audits/insights/viewport-insight.js +1 -1
  42. package/core/audits/largest-contentful-paint-element.js +7 -3
  43. package/core/audits/layout-shifts.js +5 -2
  44. package/core/audits/lcp-lazy-loaded.js +1 -1
  45. package/core/audits/long-tasks.js +6 -4
  46. package/core/audits/mainthread-work-breakdown.js +1 -1
  47. package/core/audits/metrics/first-contentful-paint.js +4 -2
  48. package/core/audits/metrics/interactive.js +6 -3
  49. package/core/audits/metrics/largest-contentful-paint.js +7 -3
  50. package/core/audits/metrics/max-potential-fid.js +6 -3
  51. package/core/audits/metrics/speed-index.js +6 -3
  52. package/core/audits/metrics/total-blocking-time.js +6 -3
  53. package/core/audits/metrics.js +4 -3
  54. package/core/audits/predictive-perf.js +4 -3
  55. package/core/audits/prioritize-lcp-image.js +5 -3
  56. package/core/audits/redirects.js +4 -2
  57. package/core/audits/script-treemap-data.js +8 -4
  58. package/core/audits/third-party-facades.js +1 -1
  59. package/core/audits/third-party-summary.js +1 -1
  60. package/core/audits/uses-rel-preconnect.js +7 -5
  61. package/core/audits/uses-rel-preload.js +5 -3
  62. package/core/computed/computed-artifact.d.ts +5 -1
  63. package/core/computed/computed-artifact.js +23 -2
  64. package/core/computed/critical-request-chains.d.ts +5 -1
  65. package/core/computed/critical-request-chains.js +4 -4
  66. package/core/computed/js-bundles.d.ts +1 -1
  67. package/core/computed/metrics/first-contentful-paint-all-frames.js +1 -1
  68. package/core/computed/metrics/first-contentful-paint.js +1 -1
  69. package/core/computed/metrics/interactive.js +1 -1
  70. package/core/computed/metrics/lantern-first-contentful-paint.js +1 -1
  71. package/core/computed/metrics/lantern-interactive.js +1 -1
  72. package/core/computed/metrics/lantern-largest-contentful-paint.js +1 -1
  73. package/core/computed/metrics/lantern-max-potential-fid.js +1 -1
  74. package/core/computed/metrics/lantern-metric.js +1 -1
  75. package/core/computed/metrics/lantern-speed-index.js +1 -1
  76. package/core/computed/metrics/lantern-total-blocking-time.js +1 -1
  77. package/core/computed/metrics/largest-contentful-paint-all-frames.js +1 -1
  78. package/core/computed/metrics/largest-contentful-paint.js +1 -1
  79. package/core/computed/metrics/lcp-breakdown.js +1 -1
  80. package/core/computed/metrics/max-potential-fid.js +1 -1
  81. package/core/computed/metrics/metric.js +2 -0
  82. package/core/computed/metrics/speed-index.js +1 -1
  83. package/core/computed/metrics/time-to-first-byte.js +1 -1
  84. package/core/computed/metrics/timing-summary.d.ts +5 -2
  85. package/core/computed/metrics/timing-summary.js +8 -4
  86. package/core/computed/metrics/total-blocking-time.js +1 -1
  87. package/core/computed/module-duplication.d.ts +1 -1
  88. package/core/computed/navigation-insights.d.ts +11 -3
  89. package/core/computed/navigation-insights.js +7 -4
  90. package/core/computed/page-dependency-graph.d.ts +7 -3
  91. package/core/computed/page-dependency-graph.js +6 -5
  92. package/core/computed/tbt-impact-tasks.js +1 -1
  93. package/core/computed/trace-engine-result.d.ts +36 -2
  94. package/core/computed/trace-engine-result.js +119 -25
  95. package/core/computed/unused-javascript-summary.d.ts +2 -2
  96. package/core/computed/unused-javascript-summary.js +1 -1
  97. package/core/config/default-config.js +19 -15
  98. package/core/config/experimental-config.js +19 -0
  99. package/core/gather/gatherers/source-maps.d.ts +1 -0
  100. package/core/gather/gatherers/source-maps.js +3 -0
  101. package/core/gather/gatherers/trace-elements.d.ts +4 -4
  102. package/core/gather/gatherers/trace-elements.js +8 -4
  103. package/core/gather/gatherers/trace.js +5 -0
  104. package/core/lib/bf-cache-strings.d.ts +0 -122
  105. package/core/lib/bf-cache-strings.js +1 -2
  106. package/core/lib/deprecation-description.js +2 -1
  107. package/core/lib/legacy-javascript/legacy-javascript.d.ts +29 -0
  108. package/core/lib/legacy-javascript/legacy-javascript.js +351 -0
  109. package/core/lib/legacy-javascript/polyfill-graph-data.json +93 -0
  110. package/core/lib/legacy-javascript/polyfill-module-data.json +623 -0
  111. package/core/lib/trace-engine.d.ts +6 -1
  112. package/core/lib/trace-engine.js +1 -2
  113. package/package.json +10 -8
  114. package/shared/localization/locales/ar-XB.json +783 -513
  115. package/shared/localization/locales/ar.json +783 -513
  116. package/shared/localization/locales/bg.json +933 -663
  117. package/shared/localization/locales/ca.json +925 -655
  118. package/shared/localization/locales/cs.json +926 -656
  119. package/shared/localization/locales/da.json +926 -656
  120. package/shared/localization/locales/de.json +803 -533
  121. package/shared/localization/locales/el.json +928 -658
  122. package/shared/localization/locales/en-GB.json +929 -659
  123. package/shared/localization/locales/en-US.json +593 -551
  124. package/shared/localization/locales/en-XA.json +28 -508
  125. package/shared/localization/locales/en-XL.json +593 -551
  126. package/shared/localization/locales/es-419.json +928 -658
  127. package/shared/localization/locales/es.json +787 -517
  128. package/shared/localization/locales/fi.json +925 -655
  129. package/shared/localization/locales/fil.json +929 -659
  130. package/shared/localization/locales/fr.json +927 -657
  131. package/shared/localization/locales/he.json +795 -528
  132. package/shared/localization/locales/hi.json +798 -528
  133. package/shared/localization/locales/hr.json +929 -659
  134. package/shared/localization/locales/hu.json +926 -656
  135. package/shared/localization/locales/id.json +926 -656
  136. package/shared/localization/locales/it.json +930 -660
  137. package/shared/localization/locales/ja.json +927 -657
  138. package/shared/localization/locales/ko.json +936 -666
  139. package/shared/localization/locales/lt.json +933 -663
  140. package/shared/localization/locales/lv.json +809 -539
  141. package/shared/localization/locales/nl.json +925 -655
  142. package/shared/localization/locales/no.json +928 -658
  143. package/shared/localization/locales/pl.json +927 -657
  144. package/shared/localization/locales/pt-PT.json +841 -571
  145. package/shared/localization/locales/pt.json +841 -571
  146. package/shared/localization/locales/ro.json +925 -655
  147. package/shared/localization/locales/ru.json +935 -668
  148. package/shared/localization/locales/sk.json +925 -655
  149. package/shared/localization/locales/sl.json +927 -657
  150. package/shared/localization/locales/sr-Latn.json +925 -655
  151. package/shared/localization/locales/sr.json +925 -655
  152. package/shared/localization/locales/sv.json +936 -666
  153. package/shared/localization/locales/ta.json +935 -668
  154. package/shared/localization/locales/te.json +785 -515
  155. package/shared/localization/locales/th.json +813 -543
  156. package/shared/localization/locales/tr.json +927 -657
  157. package/shared/localization/locales/uk.json +795 -525
  158. package/shared/localization/locales/vi.json +929 -659
  159. package/shared/localization/locales/zh-HK.json +926 -656
  160. package/shared/localization/locales/zh-TW.json +784 -514
  161. package/shared/localization/locales/zh.json +926 -656
  162. package/tsconfig.json +2 -1
  163. package/types/artifacts.d.ts +2 -1
  164. package/core/audits/byte-efficiency/polyfill-graph-data.json +0 -53
@@ -0,0 +1,351 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+ /**
8
+ * @fileoverview Identifies polyfills and transforms that should not be present if needing to support only Baseline browsers.
9
+ * @see https://docs.google.com/document/d/1ItjJwAd6e0Ts6yMbvh8TN3BBh_sAd58rYE1whnpuxaA/edit Design document (old, based on module/nomodule pattern)
10
+ * @see https://docs.google.com/spreadsheets/d/1z28Au8wo8-c2UsM2lDVEOJcI3jOkb2c951xEBqzBKCc/edit?usp=sharing Legacy babel transforms / polyfills
11
+ * ./core/scripts/legacy-javascript - verification tool.
12
+ */
13
+
14
+ /** @typedef {{name: string, expression: string, estimateBytes?: (content: string) => number}} Pattern */
15
+ /** @typedef {{name: string, line: number, column: number}} PatternMatchResult */
16
+ /** @typedef {{matches: PatternMatchResult[], estimatedByteSavings: number}} Result */
17
+
18
+ import fs from 'fs';
19
+
20
+ import {LH_ROOT} from '../../../shared/root.js';
21
+
22
+ const polyfillModuleDataJson = fs.readFileSync(
23
+ `${LH_ROOT}/core/lib/legacy-javascript/polyfill-module-data.json`, 'utf-8');
24
+
25
+ /** @type {import('../../scripts/legacy-javascript/create-polyfill-module-data.js').PolyfillModuleData} */
26
+ const polyfillModuleData = JSON.parse(polyfillModuleDataJson);
27
+
28
+ const graphJson = fs.readFileSync(
29
+ `${LH_ROOT}/core/lib/legacy-javascript/polyfill-graph-data.json`, 'utf-8');
30
+
31
+ /** @type {import('../../scripts/legacy-javascript/create-polyfill-size-estimation.js').PolyfillSizeEstimator} */
32
+ const graph = JSON.parse(graphJson);
33
+
34
+ /**
35
+ * Takes a list of patterns (consisting of a name identifier and a RegExp expression string)
36
+ * and via `match` returns match results with line / column information for a given code input.
37
+ * Only returns the first match per pattern given.
38
+ */
39
+ class CodePatternMatcher {
40
+ /**
41
+ * @param {Pattern[]} patterns
42
+ */
43
+ constructor(patterns) {
44
+ this.patterns = patterns;
45
+ }
46
+
47
+ /**
48
+ * @param {string} code
49
+ * @return {PatternMatchResult[]}
50
+ */
51
+ match(code) {
52
+ if (!this.re) {
53
+ const patternsExpression =
54
+ this.patterns.map(pattern => `(${pattern.expression})`).join('|');
55
+ this.re = new RegExp(`(^\r\n|\r|\n)|${patternsExpression}`, 'g');
56
+ }
57
+
58
+ // Reset RegExp state.
59
+ this.re.lastIndex = 0;
60
+
61
+ const seen = new Set();
62
+ /** @type {PatternMatchResult[]} */
63
+ const matches = [];
64
+ /** @type {RegExpExecArray | null} */
65
+ let result;
66
+ let line = 0;
67
+ let lineBeginsAtIndex = 0;
68
+ // Each pattern maps to one subgroup in the generated regex. For each iteration of RegExp.exec,
69
+ // only one subgroup will be defined. Exec until no more matches.
70
+ while ((result = this.re.exec(code)) !== null) {
71
+ // Discard first value in `result` - it's just the entire match.
72
+ const captureGroups = result.slice(1);
73
+ // isNewline - truthy if matching a newline, used to track the line number.
74
+ // `patternExpressionMatches` maps to each possible pattern in `this.patterns`.
75
+ // Only one of [isNewline, ...patternExpressionMatches] is ever truthy.
76
+ const [isNewline, ...patternExpressionMatches] = captureGroups;
77
+ if (isNewline) {
78
+ line++;
79
+ lineBeginsAtIndex = result.index + 1;
80
+ continue;
81
+ }
82
+ const pattern = this.patterns[patternExpressionMatches.findIndex(Boolean)];
83
+
84
+ if (seen.has(pattern)) {
85
+ continue;
86
+ }
87
+ seen.add(pattern);
88
+
89
+ matches.push({
90
+ name: pattern.name,
91
+ line,
92
+ column: result.index - lineBeginsAtIndex,
93
+ });
94
+ }
95
+
96
+ return matches;
97
+ }
98
+ }
99
+
100
+ /**
101
+ * @param {string?} object
102
+ * @param {string} property
103
+ * @param {string} coreJs3Module
104
+ */
105
+ function buildPolyfillExpression(object, property, coreJs3Module) {
106
+ const qt = (/** @type {string} */ token) =>
107
+ `['"]${token}['"]`; // don't worry about matching string delims
108
+
109
+ let expression = '';
110
+
111
+ if (object) {
112
+ // String.prototype.startsWith =
113
+ expression += `${object}\\.${property}\\s?=[^=]`;
114
+ } else {
115
+ // Promise =
116
+ // window.Promise =// Promise =Z
117
+ // but not: SomePromise =
118
+ expression += `(?:window\\.|[\\s;]+)${property}\\s?=[^=]`;
119
+ }
120
+
121
+ // String.prototype['startsWith'] =
122
+ if (object) {
123
+ expression += `|${object}\\[${qt(property)}\\]\\s?=[^=]`;
124
+ }
125
+
126
+ // Object.defineProperty(String.prototype, 'startsWith'
127
+ expression += `|defineProperty\\(${object || 'window'},\\s?${qt(property)}`;
128
+
129
+ // es-shims
130
+ // no(Object,{entries:r},{entries:function
131
+ if (object) {
132
+ expression += `|\\(${object},\\s*{${property}:.*},\\s*{${property}`;
133
+ }
134
+
135
+ // core-js
136
+ if (object) {
137
+ const objectWithoutPrototype = object.replace('.prototype', '');
138
+ // e(e.S,"Object",{values
139
+ // Minified + mangled pattern found in CDN babel-polyfill.
140
+ // see https://cdnjs.cloudflare.com/ajax/libs/babel-polyfill/7.2.5/polyfill.min.js
141
+ // TODO: perhaps this is the wrong place to check for a CDN polyfill. Remove?
142
+ // expression += `|;e\\([^,]+,${qt(objectWithoutPrototype)},{${property}:`;
143
+
144
+ // core-js@3 minified pattern.
145
+ // {target:"Array",proto:true},{fill:fill
146
+ // {target:"Array",proto:true,forced:!HAS_SPECIES_SUPPORT||!USES_TO_LENGTH},{filter:
147
+ expression += `|{target:${qt(objectWithoutPrototype)}[^;]*},{${property}:`;
148
+ } else {
149
+ // Detect polyfills for new classes: Map, Set, WeakSet, etc.
150
+ // TODO: so far, no class polyfills are enabled for detection.
151
+ // See `modulesToSkip` in create-polyfill-module-data.js
152
+
153
+ // collection("Map",
154
+ // expression += `|collection\\(${qt(property)},`;
155
+ }
156
+
157
+ // Un-minified code may have module names.
158
+ // core-js/modules/es.object.is-frozen
159
+ expression += `|${coreJs3Module.replaceAll('.', '\\.')}(?:\\.js)?"`;
160
+
161
+ return expression;
162
+ }
163
+
164
+ function getCoreJsPolyfillData() {
165
+ return polyfillModuleData.filter(d => d.corejs).map(d => {
166
+ return {
167
+ name: d.name,
168
+ coreJs3Module: d.modules[0],
169
+ };
170
+ });
171
+ }
172
+
173
+ /**
174
+ * @return {Pattern[]}
175
+ */
176
+ function getPolyfillPatterns() {
177
+ /** @type {Pattern[]} */
178
+ const patterns = [];
179
+
180
+ for (const {name, coreJs3Module} of getCoreJsPolyfillData()) {
181
+ const parts = name.split('.');
182
+ const object = parts.length > 1 ? parts.slice(0, parts.length - 1).join('.') : null;
183
+ const property = parts[parts.length - 1];
184
+ patterns.push({
185
+ name,
186
+ expression: buildPolyfillExpression(object, property, coreJs3Module),
187
+ });
188
+ }
189
+
190
+ return patterns;
191
+ }
192
+
193
+ /**
194
+ * @return {Pattern[]}
195
+ */
196
+ function getTransformPatterns() {
197
+ /**
198
+ * @param {string} content
199
+ * @param {RegExp|string} pattern
200
+ * @return {number}
201
+ */
202
+ const count = (content, pattern) => {
203
+ // Split is slightly faster than match.
204
+ if (typeof pattern === 'string') {
205
+ return content.split(pattern).length - 1;
206
+ }
207
+
208
+ return (content.match(pattern) ?? []).length;
209
+ };
210
+
211
+ // For expression: prefer a string that is found in the transform runtime support code (those won't ever be minified).
212
+
213
+ return [
214
+ // @babel/plugin-transform-classes
215
+ //
216
+ // input:
217
+ //
218
+ // class MyTestClass {
219
+ // log() {
220
+ // console.log(1);
221
+ // }
222
+ // };
223
+ //
224
+ // output:
225
+ //
226
+ // function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }
227
+ // function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }
228
+ // function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; }
229
+ // function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
230
+ // function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
231
+ // let MyTestClass = function () {
232
+ // function MyTestClass() {
233
+ // _classCallCheck(this, MyTestClass);
234
+ // }
235
+ // return _createClass(MyTestClass, [{
236
+ // key: "log",
237
+ // value: function log() {
238
+ // console.log(1);
239
+ // }
240
+ // }]);
241
+ // }();
242
+ {
243
+ name: '@babel/plugin-transform-classes',
244
+ expression: 'Cannot call a class as a function',
245
+ estimateBytes: content => {
246
+ return 1000 + (count(content, '_classCallCheck') - 1) * '_classCallCheck()'.length;
247
+ },
248
+ },
249
+ {
250
+ name: '@babel/plugin-transform-regenerator',
251
+ expression: 'Generator is already running|regeneratorRuntime',
252
+ // Example of this transform: https://gist.github.com/connorjclark/af8bccfff377ac44efc104a79bc75da2
253
+ // `regeneratorRuntime.awrap` is generated for every usage of `await`, and adds ~80 bytes each.
254
+ estimateBytes: content => {
255
+ return count(content, /regeneratorRuntime\(?\)?\.a?wrap/g) * 80;
256
+ },
257
+ },
258
+ {
259
+ name: '@babel/plugin-transform-spread',
260
+ expression: 'Invalid attempt to spread non-iterable instance',
261
+ estimateBytes: content => {
262
+ const per = '_toConsumableArray()'.length;
263
+ return 1169 + count(content, /\.apply\(void 0,\s?_toConsumableArray/g) * per;
264
+ },
265
+ },
266
+ ];
267
+ }
268
+
269
+ /**
270
+ * @param {string} content
271
+ * @param {PatternMatchResult[]} matches
272
+ * @return {number}
273
+ */
274
+ function estimateWastedBytes(content, matches) {
275
+ // Split up results based on polyfill / transform. Only transforms start with @.
276
+ const polyfillResults = matches.filter(m => !m.name.startsWith('@'));
277
+ const transformResults = matches.filter(m => m.name.startsWith('@'));
278
+
279
+ let estimatedWastedBytesFromPolyfills = 0;
280
+ const modulesSeen = new Set();
281
+ for (const result of polyfillResults) {
282
+ const modules = graph.dependencies[result.name];
283
+ if (!modules) continue; // Shouldn't happen.
284
+ for (const module of modules) {
285
+ modulesSeen.add(module);
286
+ }
287
+ }
288
+
289
+ estimatedWastedBytesFromPolyfills += [...modulesSeen].reduce((acc, moduleIndex) => {
290
+ return acc + graph.moduleSizes[moduleIndex];
291
+ }, 0);
292
+ estimatedWastedBytesFromPolyfills = Math.min(estimatedWastedBytesFromPolyfills, graph.maxSize);
293
+
294
+ let estimatedWastedBytesFromTransforms = 0;
295
+
296
+ for (const result of transformResults) {
297
+ const pattern = getTransformPatterns().find(p => p.name === result.name);
298
+ if (!pattern || !pattern.estimateBytes || !content) continue;
299
+ estimatedWastedBytesFromTransforms += pattern.estimateBytes(content);
300
+ }
301
+
302
+ const estimatedWastedBytes =
303
+ estimatedWastedBytesFromPolyfills + estimatedWastedBytesFromTransforms;
304
+ return estimatedWastedBytes;
305
+ }
306
+
307
+ const matcher = new CodePatternMatcher([
308
+ ...getPolyfillPatterns(),
309
+ ...getTransformPatterns(),
310
+ ]);
311
+
312
+ /**
313
+ * @param {string} content
314
+ * @param {import('../cdt/generated/SourceMap.js')|null} map
315
+ * @return {Result}
316
+ */
317
+ function detectLegacyJavaScript(content, map) {
318
+ if (!content) return {matches: [], estimatedByteSavings: 0};
319
+
320
+ // Start with pattern matching against the downloaded script.
321
+ let matches = matcher.match(content);
322
+
323
+ // If it's a bundle with source maps, add in the polyfill modules by name too.
324
+ if (map) {
325
+ for (const {name, modules} of polyfillModuleData) {
326
+ // Skip if the pattern matching found a match for this polyfill.
327
+ if (matches.some(m => m.name === name)) continue;
328
+
329
+ const source = map.sourceURLs().find(source => modules.some(module => {
330
+ return source.endsWith(`/${module}.js`) || source.includes(`node_modules/${module}/`);
331
+ }));
332
+ if (!source) continue;
333
+
334
+ const mapping = map.mappings().find(m => m.sourceURL === source);
335
+ if (mapping) {
336
+ matches.push({name, line: mapping.lineNumber, column: mapping.columnNumber});
337
+ } else {
338
+ matches.push({name, line: 0, column: 0});
339
+ }
340
+ }
341
+ }
342
+
343
+ matches = matches.sort((a, b) => a.name > b.name ? 1 : a.name === b.name ? 0 : -1);
344
+
345
+ return {
346
+ matches,
347
+ estimatedByteSavings: estimateWastedBytes(content, matches),
348
+ };
349
+ }
350
+
351
+ export {detectLegacyJavaScript, getTransformPatterns, getCoreJsPolyfillData};
@@ -0,0 +1,93 @@
1
+ {
2
+ "moduleSizes": [26070, 498, 282, 294, 281, 467, 161, 236, 229, 765, 546, 339, 1608, 723, 729, 1545, 438, 214, 657, 111, 759, 537, 209, 281, 685, 217, 757, 631, 293, 182, 475, 79, 407, 140, 366, 792, 269, 222, 158, 280, 188, 137, 158, 105, 189, 543, 160, 742, 1436, 88, 904, 146, 314, 375, 183, 1083, 195, 503, 269, 208, 334, 350, 460, 568, 229, 1155, 334, 266, 30, 120, 309, 370, 358, 1952, 1638, 304, 153, 274, 1288, 192, 543, 74, 144, 137, 33, 336, 457, 2122, 535, 711, 1323, 117, 1961, 244, 557, 318, 119, 124, 108, 144, 96, 133, 441, 210, 1627, 1956, 693, 1426, 863, 637, 301, 51, 708, 583, 119, 600, 221, 370, 728, 1085, 552, 629, 125, 1746, 97, 441, 543, 2756, 371, 447, 548, 243, 266, 217, 99, 440, 183, 546, 137, 464, 207, 983, 503, 237, 382, 249, 675, 402, 254, 223, 164, 214, 191, 831, 218, 202, 232, 124, 249, 160, 251, 217, 717, 78, 561, 1627, 256, 386, 225, 432, 499, 394, 364, 445, 634, 667, 177, 346, 470, 663, 142, 588, 414, 617, 1559, 380, 2520, 1040, 417, 289, 238, 220, 214, 303, 163, 141, 510, 397, 137, 137, 133, 133, 390, 266, 137, 183, 215, 191, 485, 328, 575, 799, 533, 148, 215, 589, 589, 130, 362, 562, 471, 179, 186, 1266, 1456, 521, 1536, 427, 444, 406, 912, 150, 283, 144, 485, 470, 205, 1268, 796, 658, 306, 3751, 814, 146, 2328, 1226, 922, 237, 206, 198, 250, 283, 60, 3000],
3
+ "dependencies": {
4
+ "Array.prototype.at": [0, 5, 69, 105, 106, 116, 164],
5
+ "Array.prototype.concat": [0, 16, 21, 22, 26, 34, 40, 76, 78, 155, 165],
6
+ "Array.prototype.copyWithin": [0, 5, 9, 37, 69, 105, 106, 116, 166],
7
+ "Array.prototype.every": [0, 15, 17, 21, 22, 26, 53, 59, 76, 78, 155, 167],
8
+ "Array.prototype.fill": [0, 5, 10, 69, 105, 106, 116, 168],
9
+ "Array.prototype.filter": [0, 15, 16, 21, 22, 26, 53, 59, 76, 78, 155, 169],
10
+ "Array.prototype.find": [0, 5, 15, 21, 22, 26, 53, 59, 69, 76, 78, 105, 106, 116, 155, 173],
11
+ "Array.prototype.findIndex": [0, 5, 15, 21, 22, 26, 53, 59, 69, 76, 78, 105, 106, 116, 155, 170],
12
+ "Array.prototype.findLast": [0, 5, 14, 53, 59, 69, 105, 106, 116, 172],
13
+ "Array.prototype.findLastIndex": [0, 5, 14, 53, 59, 69, 105, 106, 116, 171],
14
+ "Array.prototype.flat": [0, 21, 22, 26, 40, 50, 53, 59, 76, 78, 155, 175],
15
+ "Array.prototype.flatMap": [0, 21, 22, 26, 40, 50, 53, 59, 76, 78, 155, 174],
16
+ "Array.prototype.forEach": [0, 11, 15, 17, 21, 22, 26, 53, 59, 76, 78, 155, 176],
17
+ "Array.from": [0, 12, 23, 24, 26, 34, 53, 59, 62, 63, 75, 78, 88, 155, 177],
18
+ "Array.prototype.includes": [0, 5, 69, 105, 106, 116, 178],
19
+ "Array.prototype.indexOf": [0, 17, 59, 179],
20
+ "Array.isArray": [0, 76, 180],
21
+ "Array.prototype.join": [0, 17, 181],
22
+ "Array.prototype.map": [0, 15, 16, 21, 22, 26, 53, 59, 76, 78, 155, 182],
23
+ "Array.of": [0, 26, 34, 78, 155, 183],
24
+ "Array.prototype.slice": [0, 16, 19, 26, 34, 76, 78, 155, 184],
25
+ "Array.prototype.some": [0, 15, 17, 21, 22, 26, 53, 59, 76, 78, 155, 185],
26
+ "Array.prototype.sort": [0, 17, 19, 20, 26, 37, 42, 43, 46, 155, 156, 186],
27
+ "Array.prototype.unshift": [0, 18, 37, 40, 76, 187],
28
+ "Math.acosh": [0, 97, 188],
29
+ "Math.asinh": [0, 189],
30
+ "Math.atanh": [0, 190],
31
+ "Math.cbrt": [0, 100, 191],
32
+ "Math.clz32": [0, 192],
33
+ "Math.cosh": [0, 93, 193],
34
+ "Math.expm1": [0, 93, 194],
35
+ "Math.fround": [0, 94, 95, 99, 100, 195],
36
+ "Math.hypot": [0, 196],
37
+ "Math.imul": [0, 197],
38
+ "Math.log10": [0, 96, 198],
39
+ "Math.log1p": [0, 97, 199],
40
+ "Math.log2": [0, 98, 200],
41
+ "Math.sign": [0, 100, 201],
42
+ "Math.sinh": [0, 93, 202],
43
+ "Math.tanh": [0, 93, 203],
44
+ "Math.trunc": [0, 204],
45
+ "Object.assign": [0, 104, 116, 205],
46
+ "Object.create": [0, 69, 105, 106, 116, 206],
47
+ "Object.entries": [0, 29, 112, 116, 119, 207],
48
+ "Object.freeze": [0, 8, 19, 51, 73, 109, 113, 208],
49
+ "Object.fromEntries": [0, 26, 34, 53, 59, 62, 63, 75, 87, 88, 155, 209],
50
+ "Object.getOwnPropertyDescriptor": [0, 210],
51
+ "Object.getOwnPropertyDescriptors": [0, 34, 211],
52
+ "Object.getPrototypeOf": [0, 29, 112, 212],
53
+ "Object.hasOwn": [0, 213],
54
+ "Object.is": [0, 134, 217],
55
+ "Object.isExtensible": [0, 8, 113, 214],
56
+ "Object.isFrozen": [0, 8, 215],
57
+ "Object.isSealed": [0, 8, 216],
58
+ "Object.keys": [0, 116, 218],
59
+ "Object.preventExtensions": [0, 8, 19, 51, 73, 109, 113, 219],
60
+ "Object.seal": [0, 8, 19, 51, 73, 109, 113, 220],
61
+ "Object.setPrototypeOf": [0, 4, 58, 83, 118, 221],
62
+ "Object.values": [0, 29, 112, 116, 119, 222],
63
+ "Promise.any": [0, 24, 26, 47, 53, 59, 62, 63, 75, 87, 88, 102, 122, 123, 124, 125, 155, 224],
64
+ "Reflect.apply": [0, 52, 225],
65
+ "Reflect.construct": [0, 3, 19, 26, 52, 55, 69, 78, 105, 106, 116, 155, 226],
66
+ "Reflect.deleteProperty": [0, 227],
67
+ "Reflect.get": [0, 29, 79, 112, 230],
68
+ "Reflect.getOwnPropertyDescriptor": [0, 228],
69
+ "Reflect.getPrototypeOf": [0, 29, 112, 229],
70
+ "Reflect.has": [0, 231],
71
+ "Reflect.isExtensible": [0, 8, 113, 232],
72
+ "Reflect.ownKeys": [0, 233],
73
+ "Reflect.preventExtensions": [0, 51, 234],
74
+ "Reflect.setPrototypeOf": [0, 4, 58, 83, 118, 235],
75
+ "String.prototype.codePointAt": [0, 26, 141, 155, 156, 236],
76
+ "String.prototype.endsWith": [0, 26, 28, 59, 85, 103, 155, 156, 237],
77
+ "String.fromCodePoint": [0, 238],
78
+ "String.prototype.includes": [0, 26, 28, 85, 103, 155, 156, 239],
79
+ "String.prototype.matchAll": [0, 3, 6, 26, 29, 31, 59, 69, 78, 85, 89, 90, 105, 106, 112, 116, 126, 127, 128, 129, 130, 131, 132, 135, 139, 141, 155, 156, 241],
80
+ "String.raw": [0, 26, 155, 156, 242],
81
+ "String.prototype.repeat": [0, 26, 142, 155, 156, 243],
82
+ "String.prototype.replaceAll": [0, 26, 65, 85, 128, 129, 155, 156, 244],
83
+ "String.prototype.startsWith": [0, 26, 28, 59, 85, 103, 155, 156, 245],
84
+ "String.prototype.substr": [0, 26, 155, 156, 246],
85
+ "String.prototype.trim": [0, 26, 144, 146, 155, 156, 163, 251],
86
+ "String.prototype.trimEnd": [0, 26, 143, 144, 146, 155, 156, 163, 247, 249],
87
+ "String.prototype.trimStart": [0, 26, 144, 145, 146, 155, 156, 163, 248, 250],
88
+ "String.prototype.link": [0, 26, 30, 140, 155, 156, 240],
89
+ "Promise.allSettled": [0, 24, 26, 47, 53, 59, 62, 63, 75, 87, 88, 102, 122, 123, 124, 125, 155, 223, 252],
90
+ "focus-visible": [253]
91
+ },
92
+ "maxSize": 155835
93
+ }