From 5af1e0bb5ae4b8b98e409845f03b78d3f4b6904e Mon Sep 17 00:00:00 2001
From: Sean Doyle
Date: Sun, 14 Nov 2021 20:48:35 -0500
Subject: [PATCH] Treat response `turbo-frame[disabled]` as missing
When a response body has a `turbo-frame` element with an `[id]` that
matches the requesting frame, ignore it if it's `[disabled]`.
---
src/core/frames/frame_controller.ts | 4 ++--
src/tests/fixtures/frames.html | 6 ++++++
src/tests/fixtures/frames/disabled.html | 13 +++++++++++++
.../fixtures/frames/disabled_recursive.html | 16 ++++++++++++++++
src/tests/functional/frame_tests.ts | 15 +++++++++++++--
5 files changed, 50 insertions(+), 4 deletions(-)
create mode 100644 src/tests/fixtures/frames/disabled.html
create mode 100644 src/tests/fixtures/frames/disabled_recursive.html
diff --git a/src/core/frames/frame_controller.ts b/src/core/frames/frame_controller.ts
index b85ba3bcb..8068cc92e 100644
--- a/src/core/frames/frame_controller.ts
+++ b/src/core/frames/frame_controller.ts
@@ -290,11 +290,11 @@ export class FrameController implements AppearanceObserverDelegate, FetchRequest
let element
const id = CSS.escape(this.id)
- if (element = activateElement(container.querySelector(`turbo-frame#${id}`), this.currentURL)) {
+ if (element = activateElement(container.querySelector(`turbo-frame:not([disabled])#${id}`), this.currentURL)) {
return element
}
- if (element = activateElement(container.querySelector(`turbo-frame[src][recurse~=${id}]`), this.currentURL)) {
+ if (element = activateElement(container.querySelector(`turbo-frame:not([disabled])[src][recurse~=${id}]`), this.currentURL)) {
await element.loaded
return await this.extractForeignFrameElement(element)
}
diff --git a/src/tests/fixtures/frames.html b/src/tests/fixtures/frames.html
index 40debb498..b99e41739 100644
--- a/src/tests/fixtures/frames.html
+++ b/src/tests/fixtures/frames.html
@@ -100,9 +100,15 @@ Frames: #nested-child
data-turbo-eval=false script
+
+
+
+
+
+
Visit self.html
Visit form-redirect.html
diff --git a/src/tests/fixtures/frames/disabled.html b/src/tests/fixtures/frames/disabled.html
new file mode 100644
index 000000000..b38300b0c
--- /dev/null
+++ b/src/tests/fixtures/frames/disabled.html
@@ -0,0 +1,13 @@
+
+
+
+
+ Disabled Frame
+
+
+
+
+ Frame: #disabled loaded
+
+
+
diff --git a/src/tests/fixtures/frames/disabled_recursive.html b/src/tests/fixtures/frames/disabled_recursive.html
new file mode 100644
index 000000000..ac48697bd
--- /dev/null
+++ b/src/tests/fixtures/frames/disabled_recursive.html
@@ -0,0 +1,16 @@
+
+
+
+
+ Disabled Recursive Frame
+
+
+
+
+ Frame: #disabled_recursive loaded
+
+ Frame: #disabled_composer loaded
+
+
+
+
diff --git a/src/tests/functional/frame_tests.ts b/src/tests/functional/frame_tests.ts
index 95300a8a5..665d3e2f5 100644
--- a/src/tests/functional/frame_tests.ts
+++ b/src/tests/functional/frame_tests.ts
@@ -146,6 +146,12 @@ export class FrameTests extends TurboDriveTestCase {
this.assert.ok(await this.querySelector("#recursive details:not([open])"))
}
+ async "test loading a page with a does not lazily loads the matching frame"() {
+ await this.nextBeat
+
+ this.assert.notOk(await this.hasSelector("#disabled_recursive h2"))
+ }
+
async "test submitting a form that redirects to a page with a which lazily loads a matching frame"() {
await this.nextBeat
await this.clickSelector("#recursive summary")
@@ -156,6 +162,12 @@ export class FrameTests extends TurboDriveTestCase {
this.assert.ok(await this.querySelector("#recursive details:not([open])"))
}
+ async "test loading a page with a does not lazily load the matching frame"() {
+ await this.nextBeat
+
+ this.assert.notOk(await this.hasSelector("#disabled h2"))
+ }
+
async "test removing [disabled] attribute from eager-loaded frame navigates it"() {
await this.remote.execute(() => document.getElementById("frame")?.setAttribute("disabled", ""))
await this.remote.execute((src: string) => document.getElementById("frame")?.setAttribute("src", "/src/tests/fixtures/frames/frame.html"))
@@ -205,8 +217,7 @@ export class FrameTests extends TurboDriveTestCase {
async "test 'turbo:frame-render' is triggered after frame has finished rendering"() {
await this.clickSelector("#frame-part")
- await this.nextEventNamed("turbo:frame-render") // recursive
- const { fetchResponse } = await this.nextEventNamed("turbo:frame-render")
+ const { fetchResponse } = await this.nextEventOnTarget("part", "turbo:frame-render")
this.assert.include(fetchResponse.response.url, "/src/tests/fixtures/frames/part.html")
}