Skip to content

Commit 33a11f1

Browse files
Merge pull request #1285 from domchristie/tidy_same_page_anchor_visits_2
Simplify same page anchor visits
2 parents 1c50324 + ffc3ea3 commit 33a11f1

File tree

7 files changed

+30
-93
lines changed

7 files changed

+30
-93
lines changed

src/core/drive/history.js

Lines changed: 13 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
1-
import { nextMicrotask, uuid } from "../../util"
1+
import { uuid } from "../../util"
22

33
export class History {
44
location
55
restorationIdentifier = uuid()
66
restorationData = {}
77
started = false
8-
pageLoaded = false
98
currentIndex = 0
109

1110
constructor(delegate) {
@@ -15,7 +14,6 @@ export class History {
1514
start() {
1615
if (!this.started) {
1716
addEventListener("popstate", this.onPopState, false)
18-
addEventListener("load", this.onPageLoad, false)
1917
this.currentIndex = history.state?.turbo?.restorationIndex || 0
2018
this.started = true
2119
this.replace(new URL(window.location.href))
@@ -25,7 +23,6 @@ export class History {
2523
stop() {
2624
if (this.started) {
2725
removeEventListener("popstate", this.onPopState, false)
28-
removeEventListener("load", this.onPageLoad, false)
2926
this.started = false
3027
}
3128
}
@@ -81,32 +78,18 @@ export class History {
8178
// Event handlers
8279

8380
onPopState = (event) => {
84-
if (this.shouldHandlePopState()) {
85-
const { turbo } = event.state || {}
86-
if (turbo) {
87-
this.location = new URL(window.location.href)
88-
const { restorationIdentifier, restorationIndex } = turbo
89-
this.restorationIdentifier = restorationIdentifier
90-
const direction = restorationIndex > this.currentIndex ? "forward" : "back"
91-
this.delegate.historyPoppedToLocationWithRestorationIdentifierAndDirection(this.location, restorationIdentifier, direction)
92-
this.currentIndex = restorationIndex
93-
}
81+
const { turbo } = event.state || {}
82+
this.location = new URL(window.location.href)
83+
84+
if (turbo) {
85+
const { restorationIdentifier, restorationIndex } = turbo
86+
this.restorationIdentifier = restorationIdentifier
87+
const direction = restorationIndex > this.currentIndex ? "forward" : "back"
88+
this.delegate.historyPoppedToLocationWithRestorationIdentifierAndDirection(this.location, restorationIdentifier, direction)
89+
this.currentIndex = restorationIndex
90+
} else {
91+
this.currentIndex++
92+
this.delegate.historyPoppedWithEmptyState(this.location)
9493
}
9594
}
96-
97-
onPageLoad = async (_event) => {
98-
await nextMicrotask()
99-
this.pageLoaded = true
100-
}
101-
102-
// Private
103-
104-
shouldHandlePopState() {
105-
// Safari dispatches a popstate event after window's load event, ignore it
106-
return this.pageIsLoaded()
107-
}
108-
109-
pageIsLoaded() {
110-
return this.pageLoaded || document.readyState == "complete"
111-
}
11295
}

src/core/drive/navigator.js

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { getVisitAction } from "../../util"
22
import { FormSubmission } from "./form_submission"
3-
import { expandURL, getAnchor, getRequestURL } from "../url"
3+
import { expandURL } from "../url"
44
import { Visit } from "./visit"
55
import { PageSnapshot } from "./page_snapshot"
66

@@ -139,20 +139,10 @@ export class Navigator {
139139
delete this.currentVisit
140140
}
141141

142+
// Same-page links are no longer handled with a Visit.
143+
// This method is still needed for Turbo Native adapters.
142144
locationWithActionIsSamePage(location, action) {
143-
const anchor = getAnchor(location)
144-
const currentAnchor = getAnchor(this.view.lastRenderedLocation)
145-
const isRestorationToTop = action === "restore" && typeof anchor === "undefined"
146-
147-
return (
148-
action !== "replace" &&
149-
getRequestURL(location) === getRequestURL(this.view.lastRenderedLocation) &&
150-
(isRestorationToTop || (anchor != null && anchor !== currentAnchor))
151-
)
152-
}
153-
154-
visitScrolledToSamePageLocation(oldURL, newURL) {
155-
this.delegate.visitScrolledToSamePageLocation(oldURL, newURL)
145+
return false
156146
}
157147

158148
// Visits

src/core/drive/visit.js

Lines changed: 2 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,6 @@ export class Visit {
8585
this.snapshot = snapshot
8686
this.snapshotHTML = snapshotHTML
8787
this.response = response
88-
this.isSamePage = this.delegate.locationWithActionIsSamePage(this.location, this.action)
8988
this.isPageRefresh = this.view.isPageRefresh(this)
9089
this.visitCachedSnapshot = visitCachedSnapshot
9190
this.willRender = willRender
@@ -113,10 +112,6 @@ export class Visit {
113112
return this.history.getRestorationDataForIdentifier(this.restorationIdentifier)
114113
}
115114

116-
get silent() {
117-
return this.isSamePage
118-
}
119-
120115
start() {
121116
if (this.state == VisitState.initialized) {
122117
this.recordTimingMetric(TimingMetric.visitStart)
@@ -253,7 +248,7 @@ export class Visit {
253248
const isPreview = this.shouldIssueRequest()
254249
this.render(async () => {
255250
this.cacheSnapshot()
256-
if (this.isSamePage || this.isPageRefresh) {
251+
if (this.isPageRefresh) {
257252
this.adapter.visitRendered(this)
258253
} else {
259254
if (this.view.renderPromise) await this.view.renderPromise
@@ -281,17 +276,6 @@ export class Visit {
281276
}
282277
}
283278

284-
goToSamePageAnchor() {
285-
if (this.isSamePage) {
286-
this.render(async () => {
287-
this.cacheSnapshot()
288-
this.performScroll()
289-
this.changeHistory()
290-
this.adapter.visitRendered(this)
291-
})
292-
}
293-
}
294-
295279
// Fetch request delegate
296280

297281
prepareRequest(request) {
@@ -353,9 +337,6 @@ export class Visit {
353337
} else {
354338
this.scrollToAnchor() || this.view.scrollToTop()
355339
}
356-
if (this.isSamePage) {
357-
this.delegate.visitScrolledToSamePageLocation(this.view.lastRenderedLocation, this.location)
358-
}
359340

360341
this.scrolled = true
361342
}
@@ -394,9 +375,7 @@ export class Visit {
394375
}
395376

396377
shouldIssueRequest() {
397-
if (this.isSamePage) {
398-
return false
399-
} else if (this.action == "restore") {
378+
if (this.action == "restore") {
400379
return !this.hasCachedSnapshot()
401380
} else {
402381
return this.willRender

src/core/native/browser_adapter.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ export class BrowserAdapter {
2424

2525
visit.loadCachedSnapshot()
2626
visit.issueRequest()
27-
visit.goToSamePageAnchor()
2827
}
2928

3029
visitRequestStarted(visit) {

src/core/session.js

Lines changed: 9 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,12 @@ export class Session {
216216
}
217217
}
218218

219+
historyPoppedWithEmptyState(location) {
220+
this.history.replace(location)
221+
this.view.lastRenderedLocation = location
222+
this.view.cacheSnapshot()
223+
}
224+
219225
// Scroll observer delegate
220226

221227
scrollPositionChanged(position) {
@@ -260,7 +266,7 @@ export class Session {
260266
// Navigator delegate
261267

262268
allowsVisitingLocationWithAction(location, action) {
263-
return this.locationWithActionIsSamePage(location, action) || this.applicationAllowsVisitingLocation(location)
269+
return this.applicationAllowsVisitingLocation(location)
264270
}
265271

266272
visitProposedToLocation(location, options) {
@@ -276,9 +282,7 @@ export class Session {
276282
this.view.markVisitDirection(visit.direction)
277283
}
278284
extendURLWithDeprecatedProperties(visit.location)
279-
if (!visit.silent) {
280-
this.notifyApplicationAfterVisitingLocation(visit.location, visit.action)
281-
}
285+
this.notifyApplicationAfterVisitingLocation(visit.location, visit.action)
282286
}
283287

284288
visitCompleted(visit) {
@@ -287,14 +291,6 @@ export class Session {
287291
this.notifyApplicationAfterPageLoad(visit.getTimingMetrics())
288292
}
289293

290-
locationWithActionIsSamePage(location, action) {
291-
return this.navigator.locationWithActionIsSamePage(location, action)
292-
}
293-
294-
visitScrolledToSamePageLocation(oldURL, newURL) {
295-
this.notifyApplicationAfterVisitingSamePageLocation(oldURL, newURL)
296-
}
297-
298294
// Form submit observer delegate
299295

300296
willSubmitForm(form, submitter) {
@@ -334,9 +330,7 @@ export class Session {
334330
// Page view delegate
335331

336332
viewWillCacheSnapshot() {
337-
if (!this.navigator.currentVisit?.silent) {
338-
this.notifyApplicationBeforeCachingSnapshot()
339-
}
333+
this.notifyApplicationBeforeCachingSnapshot()
340334
}
341335

342336
allowsImmediateRender({ element }, options) {
@@ -428,15 +422,6 @@ export class Session {
428422
})
429423
}
430424

431-
notifyApplicationAfterVisitingSamePageLocation(oldURL, newURL) {
432-
dispatchEvent(
433-
new HashChangeEvent("hashchange", {
434-
oldURL: oldURL.toString(),
435-
newURL: newURL.toString()
436-
})
437-
)
438-
}
439-
440425
notifyApplicationAfterFrameLoad(frame) {
441426
return dispatch("turbo:frame-load", { target: frame })
442427
}

src/tests/functional/navigation_tests.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,7 @@ test("following a same-origin link inside an SVG element", async ({ page }) => {
299299
await page.keyboard.press("Enter")
300300

301301
await expect(page).toHaveURL(withPathname("/src/tests/fixtures/one.html"))
302-
expect(await visitAction(page)).toEqual("advance")
302+
expect(await visitAction(page)).toEqual("load")
303303
})
304304

305305
test("following a cross-origin link inside an SVG element", async ({ page }) => {

src/util.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,7 @@ export function findLinkFromClickTarget(target) {
248248
const link = findClosestRecursively(target, "a[href], a[xlink\\:href]")
249249

250250
if (!link) return null
251+
if (link.href.startsWith("#")) return null
251252
if (link.hasAttribute("download")) return null
252253

253254
const linkTarget = link.getAttribute("target")

0 commit comments

Comments
 (0)