From 88387f3117d7f554c2df125b13aac654c65ad2bd Mon Sep 17 00:00:00 2001 From: William Mantly Date: Thu, 16 Jul 2026 18:27:58 -0400 Subject: [PATCH] Update jq-repeat to 2.1.0; fix editProfile update->slideDown race jq-repeat 2.1.0 (release notes: https://github.com/wmantly/jq-repeat/releases/tag/v2.1.0) brings real fixes (throttled-update race conditions, sorted-list reverse() leaking elements, nested-scope isolation) and a few behavior changes. Audited every usage in this repo against the changelog before upgrading: - push()/unshift() now return the new array length -- every call site in this repo is a bare statement, none consume the return value. No risk. - __setPut/__setTake, jr-order-reverse, nested jq-repeat templates: not used anywhere in this repo (unlike proxy's companion PR, which needed the __setPut/__setTake fix). Real risk found and fixed: update() is now trailing-edge throttled (~50ms) even on the first call, not just rapid subsequent ones. profile.ejs's editUser()/editUserSeccess() call $.scope.editProfile .update()/renderProfile() (which itself calls update()) and immediately slideDown() the same element -- with the old synchronous behavior the form was already populated by then; with throttling it could briefly show stale/empty data. Deferred both slideUp/slideDown pairs by 60ms (past the throttle window), per the library's own migration guidance. Verified live (real bundled image + Playwright, logged in as admin): the edit form's fields show real data, not empty/stale, when checked right as the slide-open completes. --- nodejs/package-lock.json | 8 ++++---- nodejs/package.json | 2 +- nodejs/views/profile.ejs | 17 +++++++++++++---- 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/nodejs/package-lock.json b/nodejs/package-lock.json index 8b40c5b..c904112 100644 --- a/nodejs/package-lock.json +++ b/nodejs/package-lock.json @@ -19,7 +19,7 @@ "express": "^5.2.1", "express-rate-limit": "^8.5.2", "extend": "^3.0.2", - "jq-repeat": "^2.0.1", + "jq-repeat": "^2.1.0", "jquery": "^3.7.1", "jsonwebtoken": "^9.0.3", "ldapts": "^8.1.2", @@ -4357,9 +4357,9 @@ } }, "node_modules/jq-repeat": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/jq-repeat/-/jq-repeat-2.0.1.tgz", - "integrity": "sha512-ATI25tKQG3uHW8f8XPqBe85JsH4PNGHA/YLy1KgMVeYDoUSf9cqGNBum+4A+Pg1WKh9PA6bYyWfYNsgktwIbSg==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/jq-repeat/-/jq-repeat-2.1.0.tgz", + "integrity": "sha512-e1OmSWeBEHEtyOhNVysx0bnT5wd6HlZ37JZgPcGPmACJ0K9bXDPq0xOwrM1slQMSTw7FOSNDX+MD6VwvPeeZyQ==", "license": "MIT", "engines": { "node": ">=14.0.0" diff --git a/nodejs/package.json b/nodejs/package.json index a1cb7a8..440fad1 100755 --- a/nodejs/package.json +++ b/nodejs/package.json @@ -31,7 +31,7 @@ "express": "^5.2.1", "express-rate-limit": "^8.5.2", "extend": "^3.0.2", - "jq-repeat": "^2.0.1", + "jq-repeat": "^2.1.0", "jquery": "^3.7.1", "jsonwebtoken": "^9.0.3", "ldapts": "^8.1.2", diff --git a/nodejs/views/profile.ejs b/nodejs/views/profile.ejs index c286a68..d54f869 100644 --- a/nodejs/views/profile.ejs +++ b/nodejs/views/profile.ejs @@ -40,15 +40,24 @@ var $editCard = $('#editProfile'); $.scope.editProfile.update(user); - $profileCard.slideUp(); - $editCard.slideDown(); + // jq-repeat's update() is trailing-edge throttled (~50ms) as of 2.1.0 -- + // wait for the throttle tick to land before sliding the updated card + // into view, or it can briefly show stale/empty data. + setTimeout(function(){ + $profileCard.slideUp(); + $editCard.slideDown(); + }, 60); } function editUserSeccess(data){ currentUser = data.results; renderProfile(currentUser); - $('#editProfile').slideUp(); - $('#userProfile').slideDown() + // Same throttle-tick wait as editUser() above -- renderProfile() calls + // $.scope.user.update()/passwordReset.update() internally. + setTimeout(function(){ + $('#editProfile').slideUp(); + $('#userProfile').slideDown() + }, 60); } async function toggleActive(uid, active){