Diff
Modified: trunk/LayoutTests/inspector/unit-tests/map-utilities-expected.txt (294774 => 294775)
--- trunk/LayoutTests/inspector/unit-tests/map-utilities-expected.txt 2022-05-24 22:43:17 UTC (rev 294774)
+++ trunk/LayoutTests/inspector/unit-tests/map-utilities-expected.txt 2022-05-24 23:07:20 UTC (rev 294775)
@@ -14,7 +14,7 @@
PASS: Map has `key` => `undefined`.
PASS: Map take `doesNotExistKey` => `undefined`.
--- Running test case: Map.prototype.getOrInitialize
+-- Running test case: Map.prototype.getOrInitialize.Raw
PASS: Map does not have `key`.
PASS: Map should have initialized `key` with `value`.
PASS: Map does have `key` => `value`.
@@ -21,3 +21,10 @@
PASS: Map should get `key` with `value` without re-initializing.
PASS: Map still has `key` => `value`.
+-- Running test case: Map.prototype.getOrInitialize.Function
+PASS: Map does not have `key`.
+PASS: Map should have initialized `key` with `value`.
+PASS: Map does have `key` => `value`.
+PASS: Map should get `key` with `value` without re-initializing.
+PASS: Map still has `key` => `value`.
+
Modified: trunk/LayoutTests/inspector/unit-tests/map-utilities.html (294774 => 294775)
--- trunk/LayoutTests/inspector/unit-tests/map-utilities.html 2022-05-24 22:43:17 UTC (rev 294774)
+++ trunk/LayoutTests/inspector/unit-tests/map-utilities.html 2022-05-24 23:07:20 UTC (rev 294775)
@@ -47,7 +47,7 @@
});
suite.addTestCase({
- name: "Map.prototype.getOrInitialize",
+ name: "Map.prototype.getOrInitialize.Raw",
test() {
const key = "key";
const value = "value";
@@ -62,6 +62,22 @@
}
});
+ suite.addTestCase({
+ name: "Map.prototype.getOrInitialize.Function",
+ test() {
+ const key = "key";
+ const value = () => "value";
+ const value2 = () => InspectorTest.fail("Should not be reached.");
+
+ let map = new Map;
+ InspectorTest.expectEqual(map.get(key), undefined, "Map does not have `key`.");
+ InspectorTest.expectEqual(map.getOrInitialize(key, value), value(), "Map should have initialized `key` with `value`.");
+ InspectorTest.expectEqual(map.get(key), value(), "Map does have `key` => `value`.");
+ InspectorTest.expectEqual(map.getOrInitialize(key, value2), value(), "Map should get `key` with `value` without re-initializing.");
+ InspectorTest.expectEqual(map.get(key), value(), "Map still has `key` => `value`.");
+ }
+ });
+
suite.runTestCasesAndFinish();
}
</script>
Added: trunk/LayoutTests/inspector/unit-tests/weakmap-utilities-expected.txt (0 => 294775)
--- trunk/LayoutTests/inspector/unit-tests/weakmap-utilities-expected.txt (rev 0)
+++ trunk/LayoutTests/inspector/unit-tests/weakmap-utilities-expected.txt 2022-05-24 23:07:20 UTC (rev 294775)
@@ -0,0 +1,16 @@
+
+== Running test suite: WeakMap
+-- Running test case: WeakMap.prototype.getOrInitialize.Raw
+PASS: Map does not have `key`.
+PASS: Map should have initialized `key` with `value`.
+PASS: Map does have `key` => `value`.
+PASS: Map should get `key` with `value` without re-initializing.
+PASS: Map still has `key` => `value`.
+
+-- Running test case: WeakMap.prototype.getOrInitialize.Function
+PASS: Map does not have `key`.
+PASS: Map should have initialized `key` with `value`.
+PASS: Map does have `key` => `value`.
+PASS: Map should get `key` with `value` without re-initializing.
+PASS: Map still has `key` => `value`.
+
Added: trunk/LayoutTests/inspector/unit-tests/weakmap-utilities.html (0 => 294775)
--- trunk/LayoutTests/inspector/unit-tests/weakmap-utilities.html (rev 0)
+++ trunk/LayoutTests/inspector/unit-tests/weakmap-utilities.html 2022-05-24 23:07:20 UTC (rev 294775)
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src=""
+<script>
+function test()
+{
+ let suite = InspectorTest.createSyncSuite("WeakMap");
+
+ suite.addTestCase({
+ name: "WeakMap.prototype.getOrInitialize.Raw",
+ test() {
+ const key = {value: "key"};
+ const value = "value";
+ const value2 = "value2";
+
+ let map = new WeakMap;
+ InspectorTest.expectEqual(map.get(key), undefined, "Map does not have `key`.");
+ InspectorTest.expectEqual(map.getOrInitialize(key, value), value, "Map should have initialized `key` with `value`.");
+ InspectorTest.expectEqual(map.get(key), value, "Map does have `key` => `value`.");
+ InspectorTest.expectEqual(map.getOrInitialize(key, value2), value, "Map should get `key` with `value` without re-initializing.");
+ InspectorTest.expectEqual(map.get(key), value, "Map still has `key` => `value`.");
+ }
+ });
+
+ suite.addTestCase({
+ name: "WeakMap.prototype.getOrInitialize.Function",
+ test() {
+ const key = {value: "key"};
+ const value = () => "value";
+ const value2 = () => InspectorTest.fail("Should not be reached.");
+
+ let map = new WeakMap;
+ InspectorTest.expectEqual(map.get(key), undefined, "Map does not have `key`.");
+ InspectorTest.expectEqual(map.getOrInitialize(key, value), value(), "Map should have initialized `key` with `value`.");
+ InspectorTest.expectEqual(map.get(key), value(), "Map does have `key` => `value`.");
+ InspectorTest.expectEqual(map.getOrInitialize(key, value2), value(), "Map should get `key` with `value` without re-initializing.");
+ InspectorTest.expectEqual(map.get(key), value(), "Map still has `key` => `value`.");
+ }
+ });
+
+ suite.runTestCasesAndFinish();
+}
+</script>
+</head>
+<body _onLoad_="runTest()">
+</body>
+</html>
Modified: trunk/Source/WebInspectorUI/UserInterface/Base/Utilities.js (294774 => 294775)
--- trunk/Source/WebInspectorUI/UserInterface/Base/Utilities.js 2022-05-24 22:43:17 UTC (rev 294774)
+++ trunk/Source/WebInspectorUI/UserInterface/Base/Utilities.js 2022-05-24 23:07:20 UTC (rev 294775)
@@ -148,11 +148,36 @@
if (value)
return value;
+ if (typeof initialValue === "function")
+ initialValue = initialValue();
+
+ console.assert(initialValue !== undefined, "getOrInitialize should not be used with undefined.");
+
this.set(key, initialValue);
return initialValue;
}
});
+Object.defineProperty(WeakMap.prototype, "getOrInitialize",
+{
+ value(key, initialValue)
+ {
+ console.assert(initialValue !== undefined, "getOrInitialize should not be used with undefined.");
+
+ let value = this.get(key);
+ if (value)
+ return value;
+
+ if (typeof initialValue === "function")
+ initialValue = initialValue();
+
+ console.assert(initialValue !== undefined, "getOrInitialize should not be used with undefined.");
+
+ this.set(key, initialValue);
+ return initialValue;
+ }
+});
+
Object.defineProperty(Set.prototype, "find",
{
value(predicate)
Modified: trunk/Source/WebInspectorUI/UserInterface/Views/ScreenshotsTimelineOverviewGraph.js (294774 => 294775)
--- trunk/Source/WebInspectorUI/UserInterface/Views/ScreenshotsTimelineOverviewGraph.js 2022-05-24 22:43:17 UTC (rev 294774)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/ScreenshotsTimelineOverviewGraph.js 2022-05-24 23:07:20 UTC (rev 294775)
@@ -37,6 +37,8 @@
this._screenshotsTimeline = timeline;
this._lastSelectedRecordInLayout = null;
+
+ this.reset();
}
// Protected
@@ -46,6 +48,13 @@
return 60;
}
+ reset()
+ {
+ super.reset();
+
+ this._imageElementForRecord = new WeakMap;
+ }
+
layout()
{
super.layout();
@@ -57,27 +66,37 @@
let secondsPerPixel = this.timelineOverview.secondsPerPixel;
- this._lastSelectedRecordInLayout = this.selectedRecord;
-
for (let record of this._visibleRecords()) {
- let imageElement = this.element.appendChild(document.createElement("img"));
- imageElement.src = ""
- if (record === this.selectedRecord)
- imageElement.classList.add("selected");
+ this.element.appendChild(this._imageElementForRecord.getOrInitialize(record, () => {
+ let imageElement = document.createElement("img");
+ imageElement.width = record.width * (this.height / record.height);
+ imageElement.height = this.height;
+ imageElement.style.left = (record.startTime - this.startTime) / secondsPerPixel + "px";
- imageElement.height = this.height;
- let widthScale = this.height / record.height;
- let pixelWidth = record.width * widthScale;
- imageElement.width = pixelWidth;
+ imageElement.hidden = true;
+ imageElement.addEventListener("load", (event) => {
+ imageElement.hidden = false;
+ }, {once: true});
+ imageElement.src = ""
- imageElement.style.left = (record.startTime - this.startTime) / secondsPerPixel + "px";
- imageElement.addEventListener("click", (event) => {
- // Ensure that the container "click" listener added by `WI.TimelineOverview` isn't called.
- event.__timelineRecordClickEventHandled = true;
+ imageElement.addEventListener("click", (event) => {
+ // Ensure that the container "click" listener added by `WI.TimelineOverview` isn't called.
+ event.__timelineRecordClickEventHandled = true;
- this.selectedRecord = record;
- });
+ this.selectedRecord = record;
+ });
+
+ return imageElement;
+ }));
}
+
+ if (this._lastSelectedRecordInLayout)
+ this._imageElementForRecord.get(this._lastSelectedRecordInLayout)?.classList.remove("selected");
+
+ this._lastSelectedRecordInLayout = this.selectedRecord;
+
+ if (this._lastSelectedRecordInLayout)
+ this._imageElementForRecord.get(this._lastSelectedRecordInLayout)?.classList.add("selected");
}
updateSelectedRecord()
Modified: trunk/Source/WebInspectorUI/UserInterface/Views/ScreenshotsTimelineView.css (294774 => 294775)
--- trunk/Source/WebInspectorUI/UserInterface/Views/ScreenshotsTimelineView.css 2022-05-24 22:43:17 UTC (rev 294774)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/ScreenshotsTimelineView.css 2022-05-24 23:07:20 UTC (rev 294775)
@@ -26,7 +26,6 @@
.timeline-view.screenshots {
white-space: nowrap;
overflow-x: auto;
- scroll-snap-type: x mandatory;
background-color: hsl(0, 0%, 90%);
}
@@ -46,7 +45,6 @@
.timeline-view.screenshots > img.selected {
box-shadow: 0 0 0 2px var(--glyph-color-active), var(--shadow);
- scroll-snap-align: center;
}
@media (prefers-color-scheme: dark) {
Modified: trunk/Source/WebInspectorUI/UserInterface/Views/ScreenshotsTimelineView.js (294774 => 294775)
--- trunk/Source/WebInspectorUI/UserInterface/Views/ScreenshotsTimelineView.js 2022-05-24 22:43:17 UTC (rev 294774)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/ScreenshotsTimelineView.js 2022-05-24 23:07:20 UTC (rev 294775)
@@ -36,6 +36,8 @@
this.element.classList.add("screenshots");
this._selectedRecord = null;
+
+ this._imageElementForRecord = new WeakMap;
}
// Public
@@ -44,12 +46,9 @@
{
super.reset();
- this.clear();
- }
+ this.selectRecord(null);
- clear()
- {
- this.selectRecord(null);
+ this._imageElementForRecord = new WeakMap;
}
// Protected
@@ -68,18 +67,35 @@
this.element.removeChildren();
+ let selectedElement = null;
+
for (let record of this._visibleRecords()) {
- let imageElement = this.element.appendChild(document.createElement("img"));
- imageElement.src = ""
+ this.element.appendChild(this._imageElementForRecord.getOrInitialize(record, () => {
+ let imageElement = document.createElement("img");
- if (record === this._selectedRecord)
- imageElement.classList.add("selected");
+ imageElement.hidden = true;
+ imageElement.addEventListener("load", (event) => {
+ imageElement.hidden = false;
+ }, {once: true});
+ imageElement.src = ""
- imageElement.addEventListener("click", (event) => {
- this._selectTimelineRecord(record);
- });
+ imageElement.addEventListener("click", (event) => {
+ this._selectTimelineRecord(record);
+ });
+
+ if (record === this._selectedRecord)
+ selectedElement = imageElement;
+
+ return imageElement;
+ }));
}
+ if (selectedElement) {
+ selectedElement.classList.add("selected");
+
+ selectedElement.scrollIntoView({inline: "center"});
+ }
+
if (!this.element.childNodes.length)
this.element.appendChild(WI.createMessageTextView(WI.UIString("No screenshots", "No screenshots @ Screenshots Timeline", "Placeholder text shown when there are no images to display in the Screenshots timeline.")));
}
@@ -86,8 +102,22 @@
selectRecord(record)
{
+ if (record === this._selectedRecord)
+ return;
+
+ if (this._selectedRecord)
+ this._imageElementForRecord.get(this._selectedRecord)?.classList.remove("selected");
+
this._selectedRecord = record;
- this.needsLayout();
+
+ if (this._selectedRecord) {
+ let element = this._imageElementForRecord.get(this._selectedRecord);
+ if (element) {
+ element.classList.add("selected");
+
+ element.scrollIntoView({inline: "center"});
+ }
+ }
}
// Private