@angular/common 14.2.0-next.1 → 14.2.0-rc.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 (68) hide show
  1. package/esm2020/http/src/client.mjs +3 -3
  2. package/esm2020/http/src/interceptor.mjs +3 -3
  3. package/esm2020/http/src/jsonp.mjs +6 -6
  4. package/esm2020/http/src/module.mjs +15 -15
  5. package/esm2020/http/src/xhr.mjs +3 -3
  6. package/esm2020/http/src/xsrf.mjs +6 -6
  7. package/esm2020/http/testing/src/backend.mjs +3 -3
  8. package/esm2020/http/testing/src/module.mjs +4 -4
  9. package/esm2020/src/common.mjs +2 -1
  10. package/esm2020/src/common_module.mjs +4 -4
  11. package/esm2020/src/directives/ng_class.mjs +3 -3
  12. package/esm2020/src/directives/ng_component_outlet.mjs +3 -3
  13. package/esm2020/src/directives/ng_for_of.mjs +3 -3
  14. package/esm2020/src/directives/ng_if.mjs +3 -3
  15. package/esm2020/src/directives/ng_optimized_image/asserts.mjs +20 -0
  16. package/esm2020/src/directives/ng_optimized_image/error_helper.mjs +13 -0
  17. package/esm2020/src/directives/ng_optimized_image/image_loaders/cloudflare_loader.mjs +35 -0
  18. package/esm2020/src/directives/ng_optimized_image/image_loaders/cloudinary_loader.mjs +43 -0
  19. package/esm2020/src/directives/ng_optimized_image/image_loaders/image_loader.mjs +78 -0
  20. package/esm2020/src/directives/ng_optimized_image/image_loaders/imagekit_loader.mjs +35 -0
  21. package/esm2020/src/directives/ng_optimized_image/image_loaders/imgix_loader.mjs +33 -0
  22. package/esm2020/src/directives/ng_optimized_image/index.mjs +16 -0
  23. package/esm2020/src/directives/ng_optimized_image/lcp_image_observer.mjs +99 -0
  24. package/esm2020/src/directives/ng_optimized_image/ng_optimized_image.mjs +569 -0
  25. package/esm2020/src/directives/ng_optimized_image/preconnect_link_checker.mjs +137 -0
  26. package/esm2020/src/directives/ng_optimized_image/url.mjs +52 -0
  27. package/esm2020/src/directives/ng_plural.mjs +6 -6
  28. package/esm2020/src/directives/ng_style.mjs +3 -3
  29. package/esm2020/src/directives/ng_switch.mjs +9 -9
  30. package/esm2020/src/directives/ng_template_outlet.mjs +3 -3
  31. package/esm2020/src/errors.mjs +1 -1
  32. package/esm2020/src/i18n/localization.mjs +6 -6
  33. package/esm2020/src/location/hash_location_strategy.mjs +3 -3
  34. package/esm2020/src/location/location.mjs +4 -4
  35. package/esm2020/src/location/location_strategy.mjs +6 -6
  36. package/esm2020/src/location/platform_location.mjs +6 -6
  37. package/esm2020/src/pipes/async_pipe.mjs +3 -3
  38. package/esm2020/src/pipes/case_conversion_pipes.mjs +9 -9
  39. package/esm2020/src/pipes/date_pipe.mjs +3 -3
  40. package/esm2020/src/pipes/i18n_plural_pipe.mjs +3 -3
  41. package/esm2020/src/pipes/i18n_select_pipe.mjs +3 -3
  42. package/esm2020/src/pipes/json_pipe.mjs +3 -3
  43. package/esm2020/src/pipes/keyvalue_pipe.mjs +3 -3
  44. package/esm2020/src/pipes/number_pipe.mjs +9 -9
  45. package/esm2020/src/pipes/slice_pipe.mjs +3 -3
  46. package/esm2020/src/version.mjs +1 -1
  47. package/esm2020/testing/src/location_mock.mjs +3 -3
  48. package/esm2020/testing/src/mock_location_strategy.mjs +3 -3
  49. package/esm2020/testing/src/mock_platform_location.mjs +3 -3
  50. package/esm2020/upgrade/src/location_upgrade_module.mjs +4 -4
  51. package/fesm2015/common.mjs +1202 -104
  52. package/fesm2015/common.mjs.map +1 -1
  53. package/fesm2015/http/testing.mjs +8 -8
  54. package/fesm2015/http.mjs +37 -37
  55. package/fesm2015/testing.mjs +10 -10
  56. package/fesm2015/upgrade.mjs +5 -5
  57. package/fesm2020/common.mjs +1200 -104
  58. package/fesm2020/common.mjs.map +1 -1
  59. package/fesm2020/http/testing.mjs +8 -8
  60. package/fesm2020/http.mjs +37 -37
  61. package/fesm2020/testing.mjs +10 -10
  62. package/fesm2020/upgrade.mjs +5 -5
  63. package/http/index.d.ts +1 -1
  64. package/http/testing/index.d.ts +1 -1
  65. package/index.d.ts +307 -1
  66. package/package.json +2 -2
  67. package/testing/index.d.ts +1 -1
  68. package/upgrade/index.d.ts +1 -1
@@ -0,0 +1,99 @@
1
+ /**
2
+ * @license
3
+ * Copyright Google LLC All Rights Reserved.
4
+ *
5
+ * Use of this source code is governed by an MIT-style license that can be
6
+ * found in the LICENSE file at https://angular.io/license
7
+ */
8
+ import { inject, Injectable, ɵformatRuntimeError as formatRuntimeError } from '@angular/core';
9
+ import { DOCUMENT } from '../../dom_tokens';
10
+ import { assertDevMode } from './asserts';
11
+ import { imgDirectiveDetails } from './error_helper';
12
+ import { getUrl } from './url';
13
+ import * as i0 from "@angular/core";
14
+ /**
15
+ * Observer that detects whether an image with `NgOptimizedImage`
16
+ * is treated as a Largest Contentful Paint (LCP) element. If so,
17
+ * asserts that the image has the `priority` attribute.
18
+ *
19
+ * Note: this is a dev-mode only class and it does not appear in prod bundles,
20
+ * thus there is no `ngDevMode` use in the code.
21
+ *
22
+ * Based on https://web.dev/lcp/#measure-lcp-in-javascript.
23
+ */
24
+ export class LCPImageObserver {
25
+ constructor() {
26
+ // Map of full image URLs -> original `rawSrc` values.
27
+ this.images = new Map();
28
+ // Keep track of images for which `console.warn` was produced.
29
+ this.alreadyWarned = new Set();
30
+ this.window = null;
31
+ this.observer = null;
32
+ assertDevMode('LCP checker');
33
+ const win = inject(DOCUMENT).defaultView;
34
+ if (typeof win !== 'undefined' && typeof PerformanceObserver !== 'undefined') {
35
+ this.window = win;
36
+ this.observer = this.initPerformanceObserver();
37
+ }
38
+ }
39
+ /**
40
+ * Inits PerformanceObserver and subscribes to LCP events.
41
+ * Based on https://web.dev/lcp/#measure-lcp-in-javascript
42
+ */
43
+ initPerformanceObserver() {
44
+ const observer = new PerformanceObserver((entryList) => {
45
+ const entries = entryList.getEntries();
46
+ if (entries.length === 0)
47
+ return;
48
+ // We use the latest entry produced by the `PerformanceObserver` as the best
49
+ // signal on which element is actually an LCP one. As an example, the first image to load on
50
+ // a page, by virtue of being the only thing on the page so far, is often a LCP candidate
51
+ // and gets reported by PerformanceObserver, but isn't necessarily the LCP element.
52
+ const lcpElement = entries[entries.length - 1];
53
+ // Cast to `any` due to missing `element` on the `LargestContentfulPaint` type of entry.
54
+ // See https://developer.mozilla.org/en-US/docs/Web/API/LargestContentfulPaint
55
+ const imgSrc = lcpElement.element?.src ?? '';
56
+ // Exclude `data:` and `blob:` URLs, since they are not supported by the directive.
57
+ if (imgSrc.startsWith('data:') || imgSrc.startsWith('blob:'))
58
+ return;
59
+ const imgRawSrc = this.images.get(imgSrc);
60
+ if (imgRawSrc && !this.alreadyWarned.has(imgSrc)) {
61
+ this.alreadyWarned.add(imgSrc);
62
+ logMissingPriorityWarning(imgSrc);
63
+ }
64
+ });
65
+ observer.observe({ type: 'largest-contentful-paint', buffered: true });
66
+ return observer;
67
+ }
68
+ registerImage(rewrittenSrc, rawSrc) {
69
+ if (!this.observer)
70
+ return;
71
+ this.images.set(getUrl(rewrittenSrc, this.window).href, rawSrc);
72
+ }
73
+ unregisterImage(rewrittenSrc) {
74
+ if (!this.observer)
75
+ return;
76
+ this.images.delete(getUrl(rewrittenSrc, this.window).href);
77
+ }
78
+ ngOnDestroy() {
79
+ if (!this.observer)
80
+ return;
81
+ this.observer.disconnect();
82
+ this.images.clear();
83
+ this.alreadyWarned.clear();
84
+ }
85
+ }
86
+ LCPImageObserver.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.0-rc.0", ngImport: i0, type: LCPImageObserver, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
87
+ LCPImageObserver.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.2.0-rc.0", ngImport: i0, type: LCPImageObserver, providedIn: 'root' });
88
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.0-rc.0", ngImport: i0, type: LCPImageObserver, decorators: [{
89
+ type: Injectable,
90
+ args: [{ providedIn: 'root' }]
91
+ }], ctorParameters: function () { return []; } });
92
+ function logMissingPriorityWarning(rawSrc) {
93
+ const directiveDetails = imgDirectiveDetails(rawSrc);
94
+ console.warn(formatRuntimeError(2955 /* RuntimeErrorCode.LCP_IMG_MISSING_PRIORITY */, `${directiveDetails} this image is the Largest Contentful Paint (LCP) ` +
95
+ `element but was not marked "priority". This image should be marked ` +
96
+ `"priority" in order to prioritize its loading. ` +
97
+ `To fix this, add the "priority" attribute.`));
98
+ }
99
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGNwX2ltYWdlX29ic2VydmVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vcGFja2FnZXMvY29tbW9uL3NyYy9kaXJlY3RpdmVzL25nX29wdGltaXplZF9pbWFnZS9sY3BfaW1hZ2Vfb2JzZXJ2ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7OztHQU1HO0FBRUgsT0FBTyxFQUFDLE1BQU0sRUFBRSxVQUFVLEVBQWEsbUJBQW1CLElBQUksa0JBQWtCLEVBQUMsTUFBTSxlQUFlLENBQUM7QUFFdkcsT0FBTyxFQUFDLFFBQVEsRUFBQyxNQUFNLGtCQUFrQixDQUFDO0FBRzFDLE9BQU8sRUFBQyxhQUFhLEVBQUMsTUFBTSxXQUFXLENBQUM7QUFDeEMsT0FBTyxFQUFDLG1CQUFtQixFQUFDLE1BQU0sZ0JBQWdCLENBQUM7QUFDbkQsT0FBTyxFQUFDLE1BQU0sRUFBQyxNQUFNLE9BQU8sQ0FBQzs7QUFFN0I7Ozs7Ozs7OztHQVNHO0FBRUgsTUFBTSxPQUFPLGdCQUFnQjtJQVMzQjtRQVJBLHNEQUFzRDtRQUM5QyxXQUFNLEdBQUcsSUFBSSxHQUFHLEVBQWtCLENBQUM7UUFDM0MsOERBQThEO1FBQ3RELGtCQUFhLEdBQUcsSUFBSSxHQUFHLEVBQVUsQ0FBQztRQUVsQyxXQUFNLEdBQWdCLElBQUksQ0FBQztRQUMzQixhQUFRLEdBQTZCLElBQUksQ0FBQztRQUdoRCxhQUFhLENBQUMsYUFBYSxDQUFDLENBQUM7UUFDN0IsTUFBTSxHQUFHLEdBQUcsTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFDLFdBQVcsQ0FBQztRQUN6QyxJQUFJLE9BQU8sR0FBRyxLQUFLLFdBQVcsSUFBSSxPQUFPLG1CQUFtQixLQUFLLFdBQVcsRUFBRTtZQUM1RSxJQUFJLENBQUMsTUFBTSxHQUFHLEdBQUcsQ0FBQztZQUNsQixJQUFJLENBQUMsUUFBUSxHQUFHLElBQUksQ0FBQyx1QkFBdUIsRUFBRSxDQUFDO1NBQ2hEO0lBQ0gsQ0FBQztJQUVEOzs7T0FHRztJQUNLLHVCQUF1QjtRQUM3QixNQUFNLFFBQVEsR0FBRyxJQUFJLG1CQUFtQixDQUFDLENBQUMsU0FBUyxFQUFFLEVBQUU7WUFDckQsTUFBTSxPQUFPLEdBQUcsU0FBUyxDQUFDLFVBQVUsRUFBRSxDQUFDO1lBQ3ZDLElBQUksT0FBTyxDQUFDLE1BQU0sS0FBSyxDQUFDO2dCQUFFLE9BQU87WUFDakMsNEVBQTRFO1lBQzVFLDRGQUE0RjtZQUM1Rix5RkFBeUY7WUFDekYsbUZBQW1GO1lBQ25GLE1BQU0sVUFBVSxHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDO1lBRS9DLHdGQUF3RjtZQUN4Riw4RUFBOEU7WUFDOUUsTUFBTSxNQUFNLEdBQUksVUFBa0IsQ0FBQyxPQUFPLEVBQUUsR0FBRyxJQUFJLEVBQUUsQ0FBQztZQUV0RCxtRkFBbUY7WUFDbkYsSUFBSSxNQUFNLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxJQUFJLE1BQU0sQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDO2dCQUFFLE9BQU87WUFFckUsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUM7WUFDMUMsSUFBSSxTQUFTLElBQUksQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsRUFBRTtnQkFDaEQsSUFBSSxDQUFDLGFBQWEsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUM7Z0JBQy9CLHlCQUF5QixDQUFDLE1BQU0sQ0FBQyxDQUFDO2FBQ25DO1FBQ0gsQ0FBQyxDQUFDLENBQUM7UUFDSCxRQUFRLENBQUMsT0FBTyxDQUFDLEVBQUMsSUFBSSxFQUFFLDBCQUEwQixFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUMsQ0FBQyxDQUFDO1FBQ3JFLE9BQU8sUUFBUSxDQUFDO0lBQ2xCLENBQUM7SUFFRCxhQUFhLENBQUMsWUFBb0IsRUFBRSxNQUFjO1FBQ2hELElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUTtZQUFFLE9BQU87UUFDM0IsSUFBSSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLFlBQVksRUFBRSxJQUFJLENBQUMsTUFBTyxDQUFDLENBQUMsSUFBSSxFQUFFLE1BQU0sQ0FBQyxDQUFDO0lBQ25FLENBQUM7SUFFRCxlQUFlLENBQUMsWUFBb0I7UUFDbEMsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRO1lBQUUsT0FBTztRQUMzQixJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsWUFBWSxFQUFFLElBQUksQ0FBQyxNQUFPLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUM5RCxDQUFDO0lBRUQsV0FBVztRQUNULElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUTtZQUFFLE9BQU87UUFDM0IsSUFBSSxDQUFDLFFBQVEsQ0FBQyxVQUFVLEVBQUUsQ0FBQztRQUMzQixJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssRUFBRSxDQUFDO1FBQ3BCLElBQUksQ0FBQyxhQUFhLENBQUMsS0FBSyxFQUFFLENBQUM7SUFDN0IsQ0FBQzs7d0hBaEVVLGdCQUFnQjs0SEFBaEIsZ0JBQWdCLGNBREosTUFBTTtzR0FDbEIsZ0JBQWdCO2tCQUQ1QixVQUFVO21CQUFDLEVBQUMsVUFBVSxFQUFFLE1BQU0sRUFBQzs7QUFvRWhDLFNBQVMseUJBQXlCLENBQUMsTUFBYztJQUMvQyxNQUFNLGdCQUFnQixHQUFHLG1CQUFtQixDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQ3JELE9BQU8sQ0FBQyxJQUFJLENBQUMsa0JBQWtCLHVEQUUzQixHQUFHLGdCQUFnQixvREFBb0Q7UUFDbkUscUVBQXFFO1FBQ3JFLGlEQUFpRDtRQUNqRCw0Q0FBNEMsQ0FBQyxDQUFDLENBQUM7QUFDekQsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCBHb29nbGUgTExDIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4gKlxuICogVXNlIG9mIHRoaXMgc291cmNlIGNvZGUgaXMgZ292ZXJuZWQgYnkgYW4gTUlULXN0eWxlIGxpY2Vuc2UgdGhhdCBjYW4gYmVcbiAqIGZvdW5kIGluIHRoZSBMSUNFTlNFIGZpbGUgYXQgaHR0cHM6Ly9hbmd1bGFyLmlvL2xpY2Vuc2VcbiAqL1xuXG5pbXBvcnQge2luamVjdCwgSW5qZWN0YWJsZSwgT25EZXN0cm95LCDJtWZvcm1hdFJ1bnRpbWVFcnJvciBhcyBmb3JtYXRSdW50aW1lRXJyb3J9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuXG5pbXBvcnQge0RPQ1VNRU5UfSBmcm9tICcuLi8uLi9kb21fdG9rZW5zJztcbmltcG9ydCB7UnVudGltZUVycm9yQ29kZX0gZnJvbSAnLi4vLi4vZXJyb3JzJztcblxuaW1wb3J0IHthc3NlcnREZXZNb2RlfSBmcm9tICcuL2Fzc2VydHMnO1xuaW1wb3J0IHtpbWdEaXJlY3RpdmVEZXRhaWxzfSBmcm9tICcuL2Vycm9yX2hlbHBlcic7XG5pbXBvcnQge2dldFVybH0gZnJvbSAnLi91cmwnO1xuXG4vKipcbiAqIE9ic2VydmVyIHRoYXQgZGV0ZWN0cyB3aGV0aGVyIGFuIGltYWdlIHdpdGggYE5nT3B0aW1pemVkSW1hZ2VgXG4gKiBpcyB0cmVhdGVkIGFzIGEgTGFyZ2VzdCBDb250ZW50ZnVsIFBhaW50IChMQ1ApIGVsZW1lbnQuIElmIHNvLFxuICogYXNzZXJ0cyB0aGF0IHRoZSBpbWFnZSBoYXMgdGhlIGBwcmlvcml0eWAgYXR0cmlidXRlLlxuICpcbiAqIE5vdGU6IHRoaXMgaXMgYSBkZXYtbW9kZSBvbmx5IGNsYXNzIGFuZCBpdCBkb2VzIG5vdCBhcHBlYXIgaW4gcHJvZCBidW5kbGVzLFxuICogdGh1cyB0aGVyZSBpcyBubyBgbmdEZXZNb2RlYCB1c2UgaW4gdGhlIGNvZGUuXG4gKlxuICogQmFzZWQgb24gaHR0cHM6Ly93ZWIuZGV2L2xjcC8jbWVhc3VyZS1sY3AtaW4tamF2YXNjcmlwdC5cbiAqL1xuQEluamVjdGFibGUoe3Byb3ZpZGVkSW46ICdyb290J30pXG5leHBvcnQgY2xhc3MgTENQSW1hZ2VPYnNlcnZlciBpbXBsZW1lbnRzIE9uRGVzdHJveSB7XG4gIC8vIE1hcCBvZiBmdWxsIGltYWdlIFVSTHMgLT4gb3JpZ2luYWwgYHJhd1NyY2AgdmFsdWVzLlxuICBwcml2YXRlIGltYWdlcyA9IG5ldyBNYXA8c3RyaW5nLCBzdHJpbmc+KCk7XG4gIC8vIEtlZXAgdHJhY2sgb2YgaW1hZ2VzIGZvciB3aGljaCBgY29uc29sZS53YXJuYCB3YXMgcHJvZHVjZWQuXG4gIHByaXZhdGUgYWxyZWFkeVdhcm5lZCA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuXG4gIHByaXZhdGUgd2luZG93OiBXaW5kb3d8bnVsbCA9IG51bGw7XG4gIHByaXZhdGUgb2JzZXJ2ZXI6IFBlcmZvcm1hbmNlT2JzZXJ2ZXJ8bnVsbCA9IG51bGw7XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgYXNzZXJ0RGV2TW9kZSgnTENQIGNoZWNrZXInKTtcbiAgICBjb25zdCB3aW4gPSBpbmplY3QoRE9DVU1FTlQpLmRlZmF1bHRWaWV3O1xuICAgIGlmICh0eXBlb2Ygd2luICE9PSAndW5kZWZpbmVkJyAmJiB0eXBlb2YgUGVyZm9ybWFuY2VPYnNlcnZlciAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIHRoaXMud2luZG93ID0gd2luO1xuICAgICAgdGhpcy5vYnNlcnZlciA9IHRoaXMuaW5pdFBlcmZvcm1hbmNlT2JzZXJ2ZXIoKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogSW5pdHMgUGVyZm9ybWFuY2VPYnNlcnZlciBhbmQgc3Vic2NyaWJlcyB0byBMQ1AgZXZlbnRzLlxuICAgKiBCYXNlZCBvbiBodHRwczovL3dlYi5kZXYvbGNwLyNtZWFzdXJlLWxjcC1pbi1qYXZhc2NyaXB0XG4gICAqL1xuICBwcml2YXRlIGluaXRQZXJmb3JtYW5jZU9ic2VydmVyKCk6IFBlcmZvcm1hbmNlT2JzZXJ2ZXIge1xuICAgIGNvbnN0IG9ic2VydmVyID0gbmV3IFBlcmZvcm1hbmNlT2JzZXJ2ZXIoKGVudHJ5TGlzdCkgPT4ge1xuICAgICAgY29uc3QgZW50cmllcyA9IGVudHJ5TGlzdC5nZXRFbnRyaWVzKCk7XG4gICAgICBpZiAoZW50cmllcy5sZW5ndGggPT09IDApIHJldHVybjtcbiAgICAgIC8vIFdlIHVzZSB0aGUgbGF0ZXN0IGVudHJ5IHByb2R1Y2VkIGJ5IHRoZSBgUGVyZm9ybWFuY2VPYnNlcnZlcmAgYXMgdGhlIGJlc3RcbiAgICAgIC8vIHNpZ25hbCBvbiB3aGljaCBlbGVtZW50IGlzIGFjdHVhbGx5IGFuIExDUCBvbmUuIEFzIGFuIGV4YW1wbGUsIHRoZSBmaXJzdCBpbWFnZSB0byBsb2FkIG9uXG4gICAgICAvLyBhIHBhZ2UsIGJ5IHZpcnR1ZSBvZiBiZWluZyB0aGUgb25seSB0aGluZyBvbiB0aGUgcGFnZSBzbyBmYXIsIGlzIG9mdGVuIGEgTENQIGNhbmRpZGF0ZVxuICAgICAgLy8gYW5kIGdldHMgcmVwb3J0ZWQgYnkgUGVyZm9ybWFuY2VPYnNlcnZlciwgYnV0IGlzbid0IG5lY2Vzc2FyaWx5IHRoZSBMQ1AgZWxlbWVudC5cbiAgICAgIGNvbnN0IGxjcEVsZW1lbnQgPSBlbnRyaWVzW2VudHJpZXMubGVuZ3RoIC0gMV07XG5cbiAgICAgIC8vIENhc3QgdG8gYGFueWAgZHVlIHRvIG1pc3NpbmcgYGVsZW1lbnRgIG9uIHRoZSBgTGFyZ2VzdENvbnRlbnRmdWxQYWludGAgdHlwZSBvZiBlbnRyeS5cbiAgICAgIC8vIFNlZSBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvTGFyZ2VzdENvbnRlbnRmdWxQYWludFxuICAgICAgY29uc3QgaW1nU3JjID0gKGxjcEVsZW1lbnQgYXMgYW55KS5lbGVtZW50Py5zcmMgPz8gJyc7XG5cbiAgICAgIC8vIEV4Y2x1ZGUgYGRhdGE6YCBhbmQgYGJsb2I6YCBVUkxzLCBzaW5jZSB0aGV5IGFyZSBub3Qgc3VwcG9ydGVkIGJ5IHRoZSBkaXJlY3RpdmUuXG4gICAgICBpZiAoaW1nU3JjLnN0YXJ0c1dpdGgoJ2RhdGE6JykgfHwgaW1nU3JjLnN0YXJ0c1dpdGgoJ2Jsb2I6JykpIHJldHVybjtcblxuICAgICAgY29uc3QgaW1nUmF3U3JjID0gdGhpcy5pbWFnZXMuZ2V0KGltZ1NyYyk7XG4gICAgICBpZiAoaW1nUmF3U3JjICYmICF0aGlzLmFscmVhZHlXYXJuZWQuaGFzKGltZ1NyYykpIHtcbiAgICAgICAgdGhpcy5hbHJlYWR5V2FybmVkLmFkZChpbWdTcmMpO1xuICAgICAgICBsb2dNaXNzaW5nUHJpb3JpdHlXYXJuaW5nKGltZ1NyYyk7XG4gICAgICB9XG4gICAgfSk7XG4gICAgb2JzZXJ2ZXIub2JzZXJ2ZSh7dHlwZTogJ2xhcmdlc3QtY29udGVudGZ1bC1wYWludCcsIGJ1ZmZlcmVkOiB0cnVlfSk7XG4gICAgcmV0dXJuIG9ic2VydmVyO1xuICB9XG5cbiAgcmVnaXN0ZXJJbWFnZShyZXdyaXR0ZW5TcmM6IHN0cmluZywgcmF3U3JjOiBzdHJpbmcpIHtcbiAgICBpZiAoIXRoaXMub2JzZXJ2ZXIpIHJldHVybjtcbiAgICB0aGlzLmltYWdlcy5zZXQoZ2V0VXJsKHJld3JpdHRlblNyYywgdGhpcy53aW5kb3chKS5ocmVmLCByYXdTcmMpO1xuICB9XG5cbiAgdW5yZWdpc3RlckltYWdlKHJld3JpdHRlblNyYzogc3RyaW5nKSB7XG4gICAgaWYgKCF0aGlzLm9ic2VydmVyKSByZXR1cm47XG4gICAgdGhpcy5pbWFnZXMuZGVsZXRlKGdldFVybChyZXdyaXR0ZW5TcmMsIHRoaXMud2luZG93ISkuaHJlZik7XG4gIH1cblxuICBuZ09uRGVzdHJveSgpIHtcbiAgICBpZiAoIXRoaXMub2JzZXJ2ZXIpIHJldHVybjtcbiAgICB0aGlzLm9ic2VydmVyLmRpc2Nvbm5lY3QoKTtcbiAgICB0aGlzLmltYWdlcy5jbGVhcigpO1xuICAgIHRoaXMuYWxyZWFkeVdhcm5lZC5jbGVhcigpO1xuICB9XG59XG5cbmZ1bmN0aW9uIGxvZ01pc3NpbmdQcmlvcml0eVdhcm5pbmcocmF3U3JjOiBzdHJpbmcpIHtcbiAgY29uc3QgZGlyZWN0aXZlRGV0YWlscyA9IGltZ0RpcmVjdGl2ZURldGFpbHMocmF3U3JjKTtcbiAgY29uc29sZS53YXJuKGZvcm1hdFJ1bnRpbWVFcnJvcihcbiAgICAgIFJ1bnRpbWVFcnJvckNvZGUuTENQX0lNR19NSVNTSU5HX1BSSU9SSVRZLFxuICAgICAgYCR7ZGlyZWN0aXZlRGV0YWlsc30gdGhpcyBpbWFnZSBpcyB0aGUgTGFyZ2VzdCBDb250ZW50ZnVsIFBhaW50IChMQ1ApIGAgK1xuICAgICAgICAgIGBlbGVtZW50IGJ1dCB3YXMgbm90IG1hcmtlZCBcInByaW9yaXR5XCIuIFRoaXMgaW1hZ2Ugc2hvdWxkIGJlIG1hcmtlZCBgICtcbiAgICAgICAgICBgXCJwcmlvcml0eVwiIGluIG9yZGVyIHRvIHByaW9yaXRpemUgaXRzIGxvYWRpbmcuIGAgK1xuICAgICAgICAgIGBUbyBmaXggdGhpcywgYWRkIHRoZSBcInByaW9yaXR5XCIgYXR0cmlidXRlLmApKTtcbn1cbiJdfQ==