Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2022)

Unified Diff: Tools/GardeningServer/lib/util.html

Issue 526633002: Apply object updates from the network without blowing away object identity or UI attributes. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Initial Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « Tools/GardeningServer/lib/test/util-tests.html ('k') | Tools/GardeningServer/model/ct-commit-list.html » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: Tools/GardeningServer/lib/util.html
diff --git a/Tools/GardeningServer/lib/util.html b/Tools/GardeningServer/lib/util.html
new file mode 100644
index 0000000000000000000000000000000000000000..1f5e8b1611eba81ac90848259b6ec4774b9fb135
--- /dev/null
+++ b/Tools/GardeningServer/lib/util.html
@@ -0,0 +1,130 @@
+<!--
+Copyright 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="sugar.html">
+
+<script>
+
+var util = util || {};
ojan 2014/09/02 04:08:02 I have an allergy to generic util namespaces. They
Jeffrey Yasskin 2014/09/02 21:45:51 Done.
+
+(function () {
+'use strict';
+
+// Returns true if |updateLeft| can do a field-wise merge from |source| to |target|.
+// We assume |target| and |source| have the same type.
+// If they're arrays, true if the elements have a |fingerprint| property.
Jeffrey Yasskin 2014/08/30 03:07:24 Other possible names for the |fingerprint| propert
ojan 2014/09/02 04:08:02 I probalby would go with key, but fingerprint is f
Jeffrey Yasskin 2014/09/02 21:45:51 Done.
+// If they're objects, true if they're not null. (null should be assigned).
+// Otherwise, false.
+util.canUpdateLeft = function(target, source) {
ojan 2014/09/02 04:08:02 This is only used in side this file, so no need to
Jeffrey Yasskin 2014/09/02 21:45:51 Right, although it made it a little easier to desc
+ if (Array.isArray(target)) {
+ if (target.length === 0) {
+ // If both arrays are empty, do the no-op merge instead of changing the
+ // object identity.
+ return source.length === 0 || source[0].fingerprint !== undefined;
+ }
+ return target[0].fingerprint !== undefined;
+ } else if (target === null || source === null) {
+ return false;
+ } else if (typeof target === 'object') {
+ return true;
+ }
+ return false;
+};
+
+// |target| and |source| must have the same type, which must return true from
+// util.canUpdateLeft(). An array is treated the same as a dictionary where the
+// key of an object is its fingerprint. This function will:
+//
+// * Ignore elements listed in an object's constructor's |uiStateProperties| array.
+// * Remove elements from |target| whose key isn't in |source|.
+// * Copy elements from |source| whose key isn't in |target| or which are !canUpdateLeft().
+// In particular, we copy |null| rather than trying to merge it.
+// * If a matching element defines an |updateLeft| method, call that to let types customize the update process.
+// * Call updateLeft recursively for other matching elements.
+util.updateLeft = function(target, source)
Jeffrey Yasskin 2014/08/30 03:07:24 Other names for |updateLeft| include |assign|, |in
ojan 2014/09/02 04:08:02 updateLeft sgtm
+{
+ if (!util.canUpdateLeft(target, source)) {
+ throw new TypeError('Unexpected types to updateLeft(): ' +
+ [target, source].map(JSON.stringify).join(', '));
+ }
+
+ if (target.updateLeft) {
+ target.updateLeft(source);
+ return;
+ }
+
+ function updateByIndices(targetIndex, sourceIndex) {
+ if (util.canUpdateLeft(target[targetIndex], source[sourceIndex])) {
+ util.updateLeft(target[targetIndex], source[sourceIndex]);
+ } else {
+ target[targetIndex] = source[sourceIndex];
+ }
+ }
+
+ function indicesByFingerprint(array) {
ojan 2014/09/02 04:08:02 Since this isn't using any closed variables, it co
Jeffrey Yasskin 2014/09/02 21:45:51 Done.
+ var indices = {};
+ array.forEach(function(elem, index) {
+ indices[elem.fingerprint] = index;
+ });
+ return indices;
+ }
+
+ if (Array.isArray(target)) {
+ var sourceIndices = indicesByFingerprint(source);
ojan 2014/09/02 04:08:02 This would be a bit easier to read if you move the
Jeffrey Yasskin 2014/09/02 21:45:51 Done. I decided to pull these all the way out of u
+ // Remove elements from |target| that aren't in |source|.
+ target.remove(function(elem) {
+ return !sourceIndices.hasOwnProperty(elem.fingerprint);
+ });
+
+ var targetIndices = indicesByFingerprint(target);
+ Object.keys(sourceIndices, function(fingerprint, sourceIndex) {
+ if (targetIndices.hasOwnProperty(fingerprint)) {
+ // Recursively update elements that are present in both arrays.
+ updateByIndices(targetIndices[fingerprint], sourceIndex);
+ } else {
+ // And add elements in |source| that weren't in |target|. Because this
+ // adds to the end, it doesn't mess up |targetIndices|.
+ target.push(source[sourceIndex]);
+ }
+ });
+
+ // Sort |target| into the same order as |source|.
+ target.sort(function(a, b) {
+ return sourceIndices[a.fingerprint] - sourceIndices[b.fingerprint];
+ });
+ } else {
+ // They're objects. Prepare to filter out properties that reflect local UI
+ // state that wasn't loaded from the server.
+ var uiStateProperties = target.constructor.uiStateProperties;
Jeffrey Yasskin 2014/08/30 03:07:24 |uiStateProperties| could be |transientProperties|
ojan 2014/09/02 04:08:02 transient sgtm.
Jeffrey Yasskin 2014/09/02 21:45:51 Done.
+ var isUiStateProperty = function(name) {
+ return uiStateProperties && uiStateProperties.indexOf(name) !== -1;
+ };
+
+ // Remove elements from |target| that aren't in |source|.
+ Object.keys(target, function(key) {
+ if (isUiStateProperty(key))
+ return;
+ if (!source.hasOwnProperty(key))
+ delete target[key];
+ });
+
+ Object.keys(source, function(key, sourceValue) {
+ if (isUiStateProperty(key))
+ return;
+ if (target.hasOwnProperty(key)) {
+ // Recursively update elements that are present in both arrays.
+ updateByIndices(key, key);
+ } else {
+ // And add elements in |source| that weren't in |target|.
+ target[key] = sourceValue;
+ }
+ });
+ }
+};
+
+})();
+
+</script>
« no previous file with comments | « Tools/GardeningServer/lib/test/util-tests.html ('k') | Tools/GardeningServer/model/ct-commit-list.html » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698