Diff
Modified: trunk/LayoutTests/ChangeLog (199788 => 199789)
--- trunk/LayoutTests/ChangeLog 2016-04-20 21:54:09 UTC (rev 199788)
+++ trunk/LayoutTests/ChangeLog 2016-04-20 21:58:44 UTC (rev 199789)
@@ -1,3 +1,15 @@
+2016-04-19 Timothy Hatcher <[email protected]>
+
+ Web Inspector: Make debounce use an ES6 Proxy
+
+ https://bugs.webkit.org/show_bug.cgi?id=156756
+ rdar://problem/25809771
+
+ Reviewed by Joseph Pecoraro.
+
+ * inspector/unit-tests/debounce-expected.txt: Added.
+ * inspector/unit-tests/debounce.html: Added.
+
2016-04-20 Ryan Haddad <[email protected]>
Rebaseline tests for iOS simulator.
Added: trunk/LayoutTests/inspector/unit-tests/debounce-expected.txt (0 => 199789)
--- trunk/LayoutTests/inspector/unit-tests/debounce-expected.txt (rev 0)
+++ trunk/LayoutTests/inspector/unit-tests/debounce-expected.txt 2016-04-20 21:58:44 UTC (rev 199789)
@@ -0,0 +1,30 @@
+Testing debounce proxy support.
+
+
+== Running test suite: Debouce
+-- Running test case: Basic Debounce
+PASS: Debounced successfully.
+PASS: Call delayed at least 100ms.
+PASS: `this` is the right object.
+PASS: Arguments length is 2.
+PASS: First argument is 4.
+PASS: Second argument is 'abc'.
+
+-- Running test case: Multiple Debounce Delays
+PASS: Debounced successfully.
+PASS: Call delayed at least 400ms.
+PASS: `this` is the right object.
+PASS: Arguments length is 2.
+PASS: First argument is 4.
+PASS: Second argument is 'abc'.
+
+-- Running test case: Soon Debounce
+PASS: Debounced successfully.
+PASS: `this` is the right object.
+PASS: Arguments length is 2.
+PASS: First argument is 4.
+PASS: Second argument is 'abc'.
+
+-- Running test case: Cancel Debounce
+PASS: Debounced function canceled.
+
Added: trunk/LayoutTests/inspector/unit-tests/debounce.html (0 => 199789)
--- trunk/LayoutTests/inspector/unit-tests/debounce.html (rev 0)
+++ trunk/LayoutTests/inspector/unit-tests/debounce.html 2016-04-20 21:58:44 UTC (rev 199789)
@@ -0,0 +1,152 @@
+<!doctype html>
+<html>
+<head>
+<script src=""
+<script>
+function test()
+{
+ let suite = InspectorTest.createAsyncSuite("Debouce");
+
+ suite.addTestCase({
+ name: "Basic Debounce",
+ test: function(resolve, reject) {
+ let callCount = 0;
+ let startTime = performance.now();
+
+ let object = {
+ test(foo, bar) {
+ if (++callCount === 1)
+ InspectorTest.pass("Debounced successfully.");
+ else
+ InspectorTest.fail("Debounced function called multiple times.");
+
+ InspectorTest.expectThat(performance.now() - startTime >= 100, "Call delayed at least 100ms.");
+
+ InspectorTest.expectThat(this === object, "`this` is the right object.");
+ InspectorTest.expectThat(arguments.length === 2, "Arguments length is 2.");
+ InspectorTest.expectThat(foo === 4, "First argument is 4.");
+ InspectorTest.expectThat(bar === "abc", "Second argument is 'abc'.");
+
+ resolve();
+ }
+ };
+
+ let debounceProxy = object.debounce(100);
+ debounceProxy.test(1, 'xyz');
+ debounceProxy.test(2, 'fgh');
+ debounceProxy.test(3, 'ert');
+ debounceProxy.test(4, 'abc');
+
+ if (!callCount)
+ return;
+
+ InspectorTest.fail("Debounced function called immediately.");
+ resolve();
+ }
+ });
+
+ suite.addTestCase({
+ name: "Multiple Debounce Delays",
+ test: function(resolve, reject) {
+ let callCount = 0;
+ let startTime = performance.now();
+
+ let object = {
+ test(foo, bar) {
+ if (++callCount === 1)
+ InspectorTest.pass("Debounced successfully.");
+ else
+ InspectorTest.fail("Debounced function called multiple times.");
+
+ InspectorTest.expectThat(performance.now() - startTime >= 400, "Call delayed at least 400ms.");
+
+ InspectorTest.expectThat(this === object, "`this` is the right object.");
+ InspectorTest.expectThat(arguments.length === 2, "Arguments length is 2.");
+ InspectorTest.expectThat(foo === 4, "First argument is 4.");
+ InspectorTest.expectThat(bar === "abc", "Second argument is 'abc'.");
+
+ resolve();
+ }
+ };
+
+ object.debounce(100).test(1, 'xyz');
+ object.debounce(200).test(2, 'fgh');
+ object.debounce(300).test(3, 'ert');
+ object.debounce(400).test(4, 'abc');
+
+ if (!callCount)
+ return;
+
+ InspectorTest.fail("Debounced function called immediately.");
+ resolve();
+ }
+ });
+
+ suite.addTestCase({
+ name: "Soon Debounce",
+ test: function(resolve, reject) {
+ let callCount = 0;
+
+ let object = {
+ test(foo, bar) {
+ if (++callCount === 1)
+ InspectorTest.pass("Debounced successfully.");
+ else
+ InspectorTest.fail("Debounced function called multiple times.");
+
+ InspectorTest.expectThat(this === object, "`this` is the right object.");
+ InspectorTest.expectThat(arguments.length === 2, "Arguments length is 2.");
+ InspectorTest.expectThat(foo === 4, "First argument is 4.");
+ InspectorTest.expectThat(bar === "abc", "Second argument is 'abc'.");
+
+ resolve();
+ }
+ };
+
+ object.soon.test(1, 'xyz');
+ object.soon.test(2, 'fgh');
+ object.soon.test(3, 'ert');
+ object.soon.test(4, 'abc');
+
+ if (!callCount)
+ return;
+
+ InspectorTest.fail("Debounced function called immediately.");
+ resolve();
+ }
+ });
+
+ suite.addTestCase({
+ name: "Cancel Debounce",
+ test: function(resolve, reject) {
+ let callCount = 0;
+ let startTime = performance.now();
+
+ let object = {
+ test(foo, bar) {
+ InspectorTest.fail("Debounced function call should have been canceled.");
+ resolve();
+ }
+ };
+
+ object.debounce(100).test(1, 'xyz');
+ object.test.cancelDebounce();
+
+ setTimeout(() => { InspectorTest.pass("Debounced function canceled."); resolve(); }, 200);
+
+ if (!callCount)
+ return;
+
+ InspectorTest.fail("Debounced function called immediately.");
+ resolve();
+ }
+ });
+
+ suite.runTestCasesAndFinish();
+}
+</script>
+</head>
+<body _onload_="runTest()">
+ <p>Testing debounce proxy support.</p>
+</body>
+</html>
Modified: trunk/Source/WebInspectorUI/ChangeLog (199788 => 199789)
--- trunk/Source/WebInspectorUI/ChangeLog 2016-04-20 21:54:09 UTC (rev 199788)
+++ trunk/Source/WebInspectorUI/ChangeLog 2016-04-20 21:58:44 UTC (rev 199789)
@@ -1,3 +1,25 @@
+2016-04-19 Timothy Hatcher <[email protected]>
+
+ Web Inspector: Make debounce use an ES6 Proxy
+
+ https://bugs.webkit.org/show_bug.cgi?id=156756
+ rdar://problem/25809771
+
+ Reviewed by Joseph Pecoraro.
+
+ * UserInterface/Base/Utilities.js:
+ (Object.prototype.soon): Added.
+ (Object.prototype.debounce): Added.
+ (Function.prototype.debounce): Deleted.
+ (Function.prototype.cancelDebounce): Added.
+
+ * UserInterface/Views/BezierEditor.js:
+ (WebInspector.BezierEditor.createBezierInput): Use new debounce proxy.
+ * UserInterface/Views/VisualStyleBackgroundPicker.js:
+ (WebInspector.VisualStyleBackgroundPicker): Ditto.
+ * UserInterface/Views/VisualStyleURLInput.js:
+ (WebInspector.VisualStyleURLInput): Ditto.
+
2016-04-19 Joseph Pecoraro <[email protected]>
Web Inspector: Picking Snapshot from navigation bar popup does to switch views
Modified: trunk/Source/WebInspectorUI/UserInterface/Base/Utilities.js (199788 => 199789)
--- trunk/Source/WebInspectorUI/UserInterface/Base/Utilities.js 2016-04-20 21:54:09 UTC (rev 199788)
+++ trunk/Source/WebInspectorUI/UserInterface/Base/Utilities.js 2016-04-20 21:58:44 UTC (rev 199789)
@@ -1194,27 +1194,64 @@
});
(function() {
- // The `debounce` function lets you call a function with a delay and
- // if the function keeps getting called, the delay gets reset.
- // Note: The last call's arguments end being the ones that get used.
- // Use: foo.bar.debounce(200, foo)("Argument 1", "Argument 2")
+ // The `debounce` function lets you call any function on an object with a delay
+ // and if the function keeps getting called, the delay gets reset. Since `debounce`
+ // returns a Proxy, you can cache it and call multiple functions with the same delay.
- const debounceSymbol = Symbol("function-debounce-timeout");
+ // Use: object.debounce(200).foo("Argument 1", "Argument 2")
+ // Note: The last call's arguments get used for the delayed call.
- Object.defineProperty(Function.prototype, "debounce",
+ const debounceTimeoutSymbol = Symbol("debounce-timeout");
+ const debounceSoonProxySymbol = Symbol("debounce-soon-proxy");
+
+ Object.defineProperty(Object.prototype, "soon",
{
- value: function(delay, thisObject)
+ get: function()
{
- return () => {
- clearTimeout(this[debounceSymbol]);
+ if (!this[debounceSoonProxySymbol])
+ this[debounceSoonProxySymbol] = this.debounce(0);
+ return this[debounceSoonProxySymbol];
+ }
+ });
- let args = arguments;
- this[debounceSymbol] = setTimeout(() => {
- this.apply(thisObject, args);
- }, delay);
- };
+ Object.defineProperty(Object.prototype, "debounce",
+ {
+ value: function(delay)
+ {
+ console.assert(delay >= 0);
+
+ return new Proxy(this, {
+ get(target, property, receiver) {
+ return (...args) => {
+ let original = target[property];
+ console.assert(typeof original === "function");
+
+ if (original[debounceTimeoutSymbol])
+ clearTimeout(original[debounceTimeoutSymbol]);
+
+ let performWork = () => {
+ original[debounceTimeoutSymbol] = undefined;
+ original.apply(target, args);
+ };
+
+ original[debounceTimeoutSymbol] = setTimeout(performWork, delay);
+ };
+ }
+ });
}
});
+
+ Object.defineProperty(Function.prototype, "cancelDebounce",
+ {
+ value: function()
+ {
+ if (!this[debounceTimeoutSymbol])
+ return;
+
+ clearTimeout(this[debounceTimeoutSymbol]);
+ this[debounceTimeoutSymbol] = undefined;
+ }
+ });
})();
function appendWebInspectorSourceURL(string)
Modified: trunk/Source/WebInspectorUI/UserInterface/Views/BezierEditor.js (199788 => 199789)
--- trunk/Source/WebInspectorUI/UserInterface/Views/BezierEditor.js 2016-04-20 21:54:09 UTC (rev 199788)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/BezierEditor.js 2016-04-20 21:58:44 UTC (rev 199789)
@@ -92,7 +92,7 @@
{
let key = "_bezier" + id + "Input";
this[key] = this._numberInputContainer.createChild("input", className);
- this[key].addEventListener("input", this._handleNumberInputInput.debounce(250, this));
+ this[key].addEventListener("input", this.debounce(250)._handleNumberInputInput);
this[key].addEventListener("keydown", this._handleNumberInputKeydown.bind(this));
}
Modified: trunk/Source/WebInspectorUI/UserInterface/Views/VisualStyleBackgroundPicker.js (199788 => 199789)
--- trunk/Source/WebInspectorUI/UserInterface/Views/VisualStyleBackgroundPicker.js 2016-04-20 21:54:09 UTC (rev 199788)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/VisualStyleBackgroundPicker.js 2016-04-20 21:58:44 UTC (rev 199789)
@@ -37,7 +37,7 @@
this._valueInputElement.classList.add("value-input");
this._valueInputElement.type = "url";
this._valueInputElement.placeholder = WebInspector.UIString("Enter a URL");
- this._valueInputElement.addEventListener("input", this._valueInputValueChanged.debounce(250, this));
+ this._valueInputElement.addEventListener("input", this.debounce(250)._valueInputValueChanged);
this.contentElement.appendChild(this._valueInputElement);
this._valueTypePickerElement = document.createElement("select");
Modified: trunk/Source/WebInspectorUI/UserInterface/Views/VisualStyleURLInput.js (199788 => 199789)
--- trunk/Source/WebInspectorUI/UserInterface/Views/VisualStyleURLInput.js 2016-04-20 21:54:09 UTC (rev 199788)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/VisualStyleURLInput.js 2016-04-20 21:58:44 UTC (rev 199789)
@@ -32,7 +32,7 @@
this._urlInputElement = document.createElement("input");
this._urlInputElement.type = "url";
this._urlInputElement.placeholder = WebInspector.UIString("Enter a URL");
- this._urlInputElement.addEventListener("keyup", this._valueDidChange.debounce(250, this));
+ this._urlInputElement.addEventListener("keyup", this.debounce(250)._valueDidChange);
this.contentElement.appendChild(this._urlInputElement);
}