Skip to content

Commit e3a93c9

Browse files
committed
Merge pull request #410 from brigade/trim-cache
Trim cache length in cachePop, not just cachePush
2 parents a62cc86 + e4fed72 commit e3a93c9

File tree

2 files changed

+142
-7
lines changed

2 files changed

+142
-7
lines changed

jquery.pjax.js

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -744,14 +744,11 @@ function cachePush(id, value) {
744744
cacheMapping[id] = value
745745
cacheBackStack.push(id)
746746

747-
// Remove all entires in forward history stack after pushing
748-
// a new page.
749-
while (cacheForwardStack.length)
750-
delete cacheMapping[cacheForwardStack.shift()]
747+
// Remove all entries in forward history stack after pushing a new page.
748+
trimCacheStack(cacheForwardStack, 0)
751749

752750
// Trim back history stack to max cache length.
753-
while (cacheBackStack.length > pjax.defaults.maxCacheLength)
754-
delete cacheMapping[cacheBackStack.shift()]
751+
trimCacheStack(cacheBackStack, pjax.defaults.maxCacheLength)
755752
}
756753

757754
// Shifts cache from directional history cache. Should be
@@ -778,6 +775,21 @@ function cachePop(direction, id, value) {
778775
pushStack.push(id)
779776
if (id = popStack.pop())
780777
delete cacheMapping[id]
778+
779+
// Trim whichever stack we just pushed to to max cache length.
780+
trimCacheStack(pushStack, pjax.defaults.maxCacheLength)
781+
}
782+
783+
// Trim a cache stack (either cacheBackStack or cacheForwardStack) to be no
784+
// longer than the specified length, deleting cached DOM elements as necessary.
785+
//
786+
// stack - Array of state IDs
787+
// length - Maximum length to trim to
788+
//
789+
// Returns nothing.
790+
function trimCacheStack(stack, length) {
791+
while (stack.length > length)
792+
delete cacheMapping[stack.shift()]
781793
}
782794

783795
// Public: Find version identifier for the initial page load.

test/unit/pjax.js

Lines changed: 124 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -891,7 +891,7 @@ if ($.support.pjax) {
891891
// Test is fragile
892892
asyncTest("no initial pjax:popstate event", function() {
893893
var frame = this.frame
894-
var count = 0;
894+
var count = 0
895895

896896
window.iframeLoad = function() {
897897
count++
@@ -941,6 +941,129 @@ if ($.support.pjax) {
941941
window.iframeLoad()
942942
})
943943

944+
asyncTest("hitting the back button obeys maxCacheLength", function() {
945+
var frame = this.frame
946+
var count = 0
947+
var didHitServer
948+
949+
// Reduce the maxCacheLength for this spec to make it easier to test.
950+
frame.$.pjax.defaults.maxCacheLength = 1
951+
952+
// This event will fire only when we request a page from the server, so we
953+
// can use it to detect a cache miss.
954+
frame.$("#main").on("pjax:beforeSend", function() {
955+
didHitServer = true
956+
})
957+
958+
frame.$("#main").on("pjax:end", function() {
959+
count++
960+
961+
// First, navigate twice.
962+
if (count == 1) {
963+
frame.$.pjax({url: "env.html", container: "#main"})
964+
} else if (count == 2) {
965+
frame.$.pjax({url: "hello.html", container: "#main"})
966+
} else if (count == 3) {
967+
// There should now be one item in the back cache.
968+
didHitServer = false
969+
frame.history.back()
970+
} else if (count == 4) {
971+
equal(frame.location.pathname, "/env.html", "Went backward")
972+
equal(didHitServer, false, "Hit cache")
973+
frame.history.back()
974+
} else if (count == 5) {
975+
equal(frame.location.pathname, "/hello.html", "Went backward")
976+
equal(didHitServer, true, "Hit server")
977+
start()
978+
}
979+
})
980+
981+
frame.$.pjax({url: "hello.html", container: "#main"})
982+
})
983+
984+
asyncTest("hitting the forward button obeys maxCacheLength", function() {
985+
var frame = this.frame
986+
var count = 0
987+
var didHitServer
988+
989+
// Reduce the maxCacheLength for this spec to make it easier to test.
990+
frame.$.pjax.defaults.maxCacheLength = 1
991+
992+
// This event will fire only when we request a page from the server, so we
993+
// can use it to detect a cache miss.
994+
frame.$("#main").on("pjax:beforeSend", function() {
995+
didHitServer = true
996+
})
997+
998+
frame.$("#main").on("pjax:end", function() {
999+
count++
1000+
1001+
if (count == 1) {
1002+
frame.$.pjax({url: "env.html", container: "#main"})
1003+
} else if (count == 2) {
1004+
frame.$.pjax({url: "hello.html", container: "#main"})
1005+
} else if (count == 3) {
1006+
frame.history.back()
1007+
} else if (count == 4) {
1008+
frame.history.back()
1009+
} else if (count == 5) {
1010+
// There should now be one item in the forward cache.
1011+
didHitServer = false
1012+
frame.history.forward()
1013+
} else if (count == 6) {
1014+
equal(frame.location.pathname, "/env.html", "Went forward")
1015+
equal(didHitServer, false, "Hit cache")
1016+
frame.history.forward()
1017+
} else if (count == 7) {
1018+
equal(frame.location.pathname, "/hello.html", "Went forward")
1019+
equal(didHitServer, true, "Hit server")
1020+
start()
1021+
}
1022+
})
1023+
1024+
frame.$.pjax({url: "hello.html", container: "#main"})
1025+
})
1026+
1027+
asyncTest("setting maxCacheLength to 0 disables caching", function() {
1028+
var frame = this.frame
1029+
var count = 0
1030+
var didHitServer
1031+
1032+
// Set maxCacheLength to 0 to disable caching completely.
1033+
frame.$.pjax.defaults.maxCacheLength = 0
1034+
1035+
// This event will fire only when we request a page from the server, so we
1036+
// can use it to detect a cache miss.
1037+
frame.$("#main").on("pjax:beforeSend", function() {
1038+
didHitServer = true
1039+
})
1040+
1041+
frame.$("#main").on("pjax:end", function() {
1042+
count++
1043+
1044+
if (count == 1) {
1045+
didHitServer = false
1046+
frame.$.pjax({url: "env.html", container: "#main"})
1047+
} else if (count == 2) {
1048+
equal(frame.location.pathname, "/env.html", "Navigated to a new page")
1049+
equal(didHitServer, true, "Hit server")
1050+
didHitServer = false
1051+
frame.history.back()
1052+
} else if (count == 3) {
1053+
equal(frame.location.pathname, "/hello.html", "Went backward")
1054+
equal(didHitServer, true, "Hit server")
1055+
didHitServer = false
1056+
frame.history.forward()
1057+
} else if (count == 4) {
1058+
equal(frame.location.pathname, "/env.html", "Went forward")
1059+
equal(didHitServer, true, "Hit server")
1060+
start()
1061+
}
1062+
})
1063+
1064+
frame.$.pjax({url: "hello.html", container: "#main"})
1065+
})
1066+
9441067
asyncTest("popstate preserves GET data", function() {
9451068
var frame = this.frame
9461069

0 commit comments

Comments
 (0)