@hotwired/turbo 7.2.5 → 7.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/turbo.es2017-esm.js +135 -75
- package/dist/turbo.es2017-umd.js +135 -75
- package/dist/types/core/drive/form_submission.d.ts +8 -4
- package/dist/types/core/drive/head_snapshot.d.ts +3 -3
- package/dist/types/core/drive/history.d.ts +3 -3
- package/dist/types/core/drive/navigator.d.ts +1 -1
- package/dist/types/core/drive/page_view.d.ts +2 -2
- package/dist/types/core/drive/visit.d.ts +3 -3
- package/dist/types/core/errors.d.ts +2 -0
- package/dist/types/core/frames/frame_controller.d.ts +6 -2
- package/dist/types/core/frames/frame_view.d.ts +2 -2
- package/dist/types/core/index.d.ts +5 -4
- package/dist/types/core/native/browser_adapter.d.ts +1 -1
- package/dist/types/core/renderer.d.ts +1 -1
- package/dist/types/core/session.d.ts +12 -12
- package/dist/types/core/snapshot.d.ts +1 -1
- package/dist/types/core/streams/stream_actions.d.ts +2 -2
- package/dist/types/core/types.d.ts +3 -3
- package/dist/types/core/url.d.ts +1 -1
- package/dist/types/core/view.d.ts +1 -1
- package/dist/types/elements/frame_element.d.ts +1 -1
- package/dist/types/elements/stream_element.d.ts +2 -2
- package/dist/types/http/fetch_request.d.ts +7 -7
- package/dist/types/http/index.d.ts +1 -1
- package/dist/types/observers/cache_observer.d.ts +5 -1
- package/dist/types/observers/form_link_click_observer.d.ts +1 -1
- package/dist/types/polyfills/custom-elements-native-shim.d.ts +1 -0
- package/dist/types/tests/helpers/dom_test_case.d.ts +1 -2
- package/dist/types/tests/helpers/page.d.ts +10 -10
- package/dist/types/tests/unit/deprecated_adapter_support_tests.d.ts +1 -0
- package/dist/types/tests/unit/export_tests.d.ts +1 -5
- package/dist/types/tests/unit/stream_element_tests.d.ts +0 -10
- package/dist/types/util.d.ts +1 -1
- package/package.json +16 -10
- package/dist/types/tests/helpers/intern_test_case.d.ts +0 -19
- package/dist/types/tests/unit/deprecated_adapter_support_test.d.ts +0 -24
- package/dist/types/tests/unit/index.d.ts +0 -3
package/dist/turbo.es2017-esm.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*
|
|
2
|
-
Turbo 7.
|
|
2
|
+
Turbo 7.3.0
|
|
3
3
|
Copyright © 2023 37signals LLC
|
|
4
4
|
*/
|
|
5
5
|
(function () {
|
|
@@ -87,16 +87,13 @@ function clickCaptured(event) {
|
|
|
87
87
|
(function () {
|
|
88
88
|
if ("submitter" in Event.prototype)
|
|
89
89
|
return;
|
|
90
|
-
let prototype;
|
|
90
|
+
let prototype = window.Event.prototype;
|
|
91
91
|
if ("SubmitEvent" in window && /Apple Computer/.test(navigator.vendor)) {
|
|
92
92
|
prototype = window.SubmitEvent.prototype;
|
|
93
93
|
}
|
|
94
94
|
else if ("SubmitEvent" in window) {
|
|
95
95
|
return;
|
|
96
96
|
}
|
|
97
|
-
else {
|
|
98
|
-
prototype = window.Event.prototype;
|
|
99
|
-
}
|
|
100
97
|
addEventListener("click", clickCaptured, true);
|
|
101
98
|
Object.defineProperty(prototype, "submitter", {
|
|
102
99
|
get() {
|
|
@@ -113,14 +110,14 @@ var FrameLoadingStyle;
|
|
|
113
110
|
FrameLoadingStyle["lazy"] = "lazy";
|
|
114
111
|
})(FrameLoadingStyle || (FrameLoadingStyle = {}));
|
|
115
112
|
class FrameElement extends HTMLElement {
|
|
113
|
+
static get observedAttributes() {
|
|
114
|
+
return ["disabled", "complete", "loading", "src"];
|
|
115
|
+
}
|
|
116
116
|
constructor() {
|
|
117
117
|
super();
|
|
118
118
|
this.loaded = Promise.resolve();
|
|
119
119
|
this.delegate = new FrameElement.delegateConstructor(this);
|
|
120
120
|
}
|
|
121
|
-
static get observedAttributes() {
|
|
122
|
-
return ["disabled", "complete", "loading", "src"];
|
|
123
|
-
}
|
|
124
121
|
connectedCallback() {
|
|
125
122
|
this.delegate.connect();
|
|
126
123
|
}
|
|
@@ -560,7 +557,7 @@ class FetchRequest {
|
|
|
560
557
|
credentials: "same-origin",
|
|
561
558
|
headers: this.headers,
|
|
562
559
|
redirect: "follow",
|
|
563
|
-
body: this.
|
|
560
|
+
body: this.isSafe ? null : this.body,
|
|
564
561
|
signal: this.abortSignal,
|
|
565
562
|
referrer: (_a = this.delegate.referrer) === null || _a === void 0 ? void 0 : _a.href,
|
|
566
563
|
};
|
|
@@ -570,8 +567,8 @@ class FetchRequest {
|
|
|
570
567
|
Accept: "text/html, application/xhtml+xml",
|
|
571
568
|
};
|
|
572
569
|
}
|
|
573
|
-
get
|
|
574
|
-
return this.method
|
|
570
|
+
get isSafe() {
|
|
571
|
+
return this.method === FetchMethod.get;
|
|
575
572
|
}
|
|
576
573
|
get abortSignal() {
|
|
577
574
|
return this.abortController.signal;
|
|
@@ -631,9 +628,6 @@ class AppearanceObserver {
|
|
|
631
628
|
}
|
|
632
629
|
|
|
633
630
|
class StreamMessage {
|
|
634
|
-
constructor(fragment) {
|
|
635
|
-
this.fragment = importStreamElements(fragment);
|
|
636
|
-
}
|
|
637
631
|
static wrap(message) {
|
|
638
632
|
if (typeof message == "string") {
|
|
639
633
|
return new this(createDocumentFragment(message));
|
|
@@ -642,6 +636,9 @@ class StreamMessage {
|
|
|
642
636
|
return message;
|
|
643
637
|
}
|
|
644
638
|
}
|
|
639
|
+
constructor(fragment) {
|
|
640
|
+
this.fragment = importStreamElements(fragment);
|
|
641
|
+
}
|
|
645
642
|
}
|
|
646
643
|
StreamMessage.contentType = "text/vnd.turbo-stream.html";
|
|
647
644
|
function importStreamElements(fragment) {
|
|
@@ -681,6 +678,9 @@ function formEnctypeFromString(encoding) {
|
|
|
681
678
|
}
|
|
682
679
|
}
|
|
683
680
|
class FormSubmission {
|
|
681
|
+
static confirmMethod(message, _element, _submitter) {
|
|
682
|
+
return Promise.resolve(confirm(message));
|
|
683
|
+
}
|
|
684
684
|
constructor(delegate, formElement, submitter, mustRedirect = false) {
|
|
685
685
|
this.state = FormSubmissionState.initialized;
|
|
686
686
|
this.delegate = delegate;
|
|
@@ -694,9 +694,6 @@ class FormSubmission {
|
|
|
694
694
|
this.fetchRequest = new FetchRequest(this, this.method, this.location, this.body, this.formElement);
|
|
695
695
|
this.mustRedirect = mustRedirect;
|
|
696
696
|
}
|
|
697
|
-
static confirmMethod(message, _element, _submitter) {
|
|
698
|
-
return Promise.resolve(confirm(message));
|
|
699
|
-
}
|
|
700
697
|
get method() {
|
|
701
698
|
var _a;
|
|
702
699
|
const method = ((_a = this.submitter) === null || _a === void 0 ? void 0 : _a.getAttribute("formmethod")) || this.formElement.getAttribute("method") || "";
|
|
@@ -724,8 +721,8 @@ class FormSubmission {
|
|
|
724
721
|
var _a;
|
|
725
722
|
return formEnctypeFromString(((_a = this.submitter) === null || _a === void 0 ? void 0 : _a.getAttribute("formenctype")) || this.formElement.enctype);
|
|
726
723
|
}
|
|
727
|
-
get
|
|
728
|
-
return this.fetchRequest.
|
|
724
|
+
get isSafe() {
|
|
725
|
+
return this.fetchRequest.isSafe;
|
|
729
726
|
}
|
|
730
727
|
get stringFormData() {
|
|
731
728
|
return [...this.formData].reduce((entries, [name, value]) => {
|
|
@@ -755,7 +752,7 @@ class FormSubmission {
|
|
|
755
752
|
}
|
|
756
753
|
}
|
|
757
754
|
prepareRequest(request) {
|
|
758
|
-
if (!request.
|
|
755
|
+
if (!request.isSafe) {
|
|
759
756
|
const token = getCookieValue(getMetaContent("csrf-param")) || getMetaContent("csrf-token");
|
|
760
757
|
if (token) {
|
|
761
758
|
request.headers["X-CSRF-Token"] = token;
|
|
@@ -769,6 +766,7 @@ class FormSubmission {
|
|
|
769
766
|
var _a;
|
|
770
767
|
this.state = FormSubmissionState.waiting;
|
|
771
768
|
(_a = this.submitter) === null || _a === void 0 ? void 0 : _a.setAttribute("disabled", "");
|
|
769
|
+
this.setSubmitsWith();
|
|
772
770
|
dispatch("turbo:submit-start", {
|
|
773
771
|
target: this.formElement,
|
|
774
772
|
detail: { formSubmission: this },
|
|
@@ -804,17 +802,46 @@ class FormSubmission {
|
|
|
804
802
|
var _a;
|
|
805
803
|
this.state = FormSubmissionState.stopped;
|
|
806
804
|
(_a = this.submitter) === null || _a === void 0 ? void 0 : _a.removeAttribute("disabled");
|
|
805
|
+
this.resetSubmitterText();
|
|
807
806
|
dispatch("turbo:submit-end", {
|
|
808
807
|
target: this.formElement,
|
|
809
808
|
detail: Object.assign({ formSubmission: this }, this.result),
|
|
810
809
|
});
|
|
811
810
|
this.delegate.formSubmissionFinished(this);
|
|
812
811
|
}
|
|
812
|
+
setSubmitsWith() {
|
|
813
|
+
if (!this.submitter || !this.submitsWith)
|
|
814
|
+
return;
|
|
815
|
+
if (this.submitter.matches("button")) {
|
|
816
|
+
this.originalSubmitText = this.submitter.innerHTML;
|
|
817
|
+
this.submitter.innerHTML = this.submitsWith;
|
|
818
|
+
}
|
|
819
|
+
else if (this.submitter.matches("input")) {
|
|
820
|
+
const input = this.submitter;
|
|
821
|
+
this.originalSubmitText = input.value;
|
|
822
|
+
input.value = this.submitsWith;
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
resetSubmitterText() {
|
|
826
|
+
if (!this.submitter || !this.originalSubmitText)
|
|
827
|
+
return;
|
|
828
|
+
if (this.submitter.matches("button")) {
|
|
829
|
+
this.submitter.innerHTML = this.originalSubmitText;
|
|
830
|
+
}
|
|
831
|
+
else if (this.submitter.matches("input")) {
|
|
832
|
+
const input = this.submitter;
|
|
833
|
+
input.value = this.originalSubmitText;
|
|
834
|
+
}
|
|
835
|
+
}
|
|
813
836
|
requestMustRedirect(request) {
|
|
814
|
-
return !request.
|
|
837
|
+
return !request.isSafe && this.mustRedirect;
|
|
815
838
|
}
|
|
816
839
|
requestAcceptsTurboStreamResponse(request) {
|
|
817
|
-
return !request.
|
|
840
|
+
return !request.isSafe || hasAttribute("data-turbo-stream", this.submitter, this.formElement);
|
|
841
|
+
}
|
|
842
|
+
get submitsWith() {
|
|
843
|
+
var _a;
|
|
844
|
+
return (_a = this.submitter) === null || _a === void 0 ? void 0 : _a.getAttribute("data-turbo-submits-with");
|
|
818
845
|
}
|
|
819
846
|
}
|
|
820
847
|
function buildFormData(formElement, submitter) {
|
|
@@ -1054,8 +1081,8 @@ class View {
|
|
|
1054
1081
|
}
|
|
1055
1082
|
|
|
1056
1083
|
class FrameView extends View {
|
|
1057
|
-
|
|
1058
|
-
this.element.innerHTML = ""
|
|
1084
|
+
missing() {
|
|
1085
|
+
this.element.innerHTML = `<strong class="turbo-frame-error">Content missing</strong>`;
|
|
1059
1086
|
}
|
|
1060
1087
|
get snapshot() {
|
|
1061
1088
|
return new Snapshot(this.element);
|
|
@@ -1216,16 +1243,16 @@ class FormLinkClickObserver {
|
|
|
1216
1243
|
}
|
|
1217
1244
|
|
|
1218
1245
|
class Bardo {
|
|
1219
|
-
constructor(delegate, permanentElementMap) {
|
|
1220
|
-
this.delegate = delegate;
|
|
1221
|
-
this.permanentElementMap = permanentElementMap;
|
|
1222
|
-
}
|
|
1223
1246
|
static async preservingPermanentElements(delegate, permanentElementMap, callback) {
|
|
1224
1247
|
const bardo = new this(delegate, permanentElementMap);
|
|
1225
1248
|
bardo.enter();
|
|
1226
1249
|
await callback();
|
|
1227
1250
|
bardo.leave();
|
|
1228
1251
|
}
|
|
1252
|
+
constructor(delegate, permanentElementMap) {
|
|
1253
|
+
this.delegate = delegate;
|
|
1254
|
+
this.permanentElementMap = permanentElementMap;
|
|
1255
|
+
}
|
|
1229
1256
|
enter() {
|
|
1230
1257
|
for (const id in this.permanentElementMap) {
|
|
1231
1258
|
const [currentPermanentElement, newPermanentElement] = this.permanentElementMap[id];
|
|
@@ -1332,10 +1359,6 @@ function elementIsFocusable(element) {
|
|
|
1332
1359
|
}
|
|
1333
1360
|
|
|
1334
1361
|
class FrameRenderer extends Renderer {
|
|
1335
|
-
constructor(delegate, currentSnapshot, newSnapshot, renderElement, isPreview, willRender = true) {
|
|
1336
|
-
super(currentSnapshot, newSnapshot, renderElement, isPreview, willRender);
|
|
1337
|
-
this.delegate = delegate;
|
|
1338
|
-
}
|
|
1339
1362
|
static renderElement(currentElement, newElement) {
|
|
1340
1363
|
var _a;
|
|
1341
1364
|
const destinationRange = document.createRange();
|
|
@@ -1348,6 +1371,10 @@ class FrameRenderer extends Renderer {
|
|
|
1348
1371
|
currentElement.appendChild(sourceRange.extractContents());
|
|
1349
1372
|
}
|
|
1350
1373
|
}
|
|
1374
|
+
constructor(delegate, currentSnapshot, newSnapshot, renderElement, isPreview, willRender = true) {
|
|
1375
|
+
super(currentSnapshot, newSnapshot, renderElement, isPreview, willRender);
|
|
1376
|
+
this.delegate = delegate;
|
|
1377
|
+
}
|
|
1351
1378
|
get shouldRender() {
|
|
1352
1379
|
return true;
|
|
1353
1380
|
}
|
|
@@ -1406,18 +1433,6 @@ function readScrollBehavior(value, defaultValue) {
|
|
|
1406
1433
|
}
|
|
1407
1434
|
|
|
1408
1435
|
class ProgressBar {
|
|
1409
|
-
constructor() {
|
|
1410
|
-
this.hiding = false;
|
|
1411
|
-
this.value = 0;
|
|
1412
|
-
this.visible = false;
|
|
1413
|
-
this.trickle = () => {
|
|
1414
|
-
this.setValue(this.value + Math.random() / 100);
|
|
1415
|
-
};
|
|
1416
|
-
this.stylesheetElement = this.createStylesheetElement();
|
|
1417
|
-
this.progressElement = this.createProgressElement();
|
|
1418
|
-
this.installStylesheetElement();
|
|
1419
|
-
this.setValue(0);
|
|
1420
|
-
}
|
|
1421
1436
|
static get defaultCSS() {
|
|
1422
1437
|
return unindent `
|
|
1423
1438
|
.turbo-progress-bar {
|
|
@@ -1435,6 +1450,18 @@ class ProgressBar {
|
|
|
1435
1450
|
}
|
|
1436
1451
|
`;
|
|
1437
1452
|
}
|
|
1453
|
+
constructor() {
|
|
1454
|
+
this.hiding = false;
|
|
1455
|
+
this.value = 0;
|
|
1456
|
+
this.visible = false;
|
|
1457
|
+
this.trickle = () => {
|
|
1458
|
+
this.setValue(this.value + Math.random() / 100);
|
|
1459
|
+
};
|
|
1460
|
+
this.stylesheetElement = this.createStylesheetElement();
|
|
1461
|
+
this.progressElement = this.createProgressElement();
|
|
1462
|
+
this.installStylesheetElement();
|
|
1463
|
+
this.setValue(0);
|
|
1464
|
+
}
|
|
1438
1465
|
show() {
|
|
1439
1466
|
if (!this.visible) {
|
|
1440
1467
|
this.visible = true;
|
|
@@ -1605,10 +1632,6 @@ function elementWithoutNonce(element) {
|
|
|
1605
1632
|
}
|
|
1606
1633
|
|
|
1607
1634
|
class PageSnapshot extends Snapshot {
|
|
1608
|
-
constructor(element, headSnapshot) {
|
|
1609
|
-
super(element);
|
|
1610
|
-
this.headSnapshot = headSnapshot;
|
|
1611
|
-
}
|
|
1612
1635
|
static fromHTMLString(html = "") {
|
|
1613
1636
|
return this.fromDocument(parseHTMLDocument(html));
|
|
1614
1637
|
}
|
|
@@ -1618,6 +1641,10 @@ class PageSnapshot extends Snapshot {
|
|
|
1618
1641
|
static fromDocument({ head, body }) {
|
|
1619
1642
|
return new this(body, new HeadSnapshot(head));
|
|
1620
1643
|
}
|
|
1644
|
+
constructor(element, headSnapshot) {
|
|
1645
|
+
super(element);
|
|
1646
|
+
this.headSnapshot = headSnapshot;
|
|
1647
|
+
}
|
|
1621
1648
|
clone() {
|
|
1622
1649
|
const clonedElement = this.element.cloneNode(true);
|
|
1623
1650
|
const selectElements = this.element.querySelectorAll("select");
|
|
@@ -2117,10 +2144,11 @@ class BrowserAdapter {
|
|
|
2117
2144
|
|
|
2118
2145
|
class CacheObserver {
|
|
2119
2146
|
constructor() {
|
|
2147
|
+
this.selector = "[data-turbo-temporary]";
|
|
2148
|
+
this.deprecatedSelector = "[data-turbo-cache=false]";
|
|
2120
2149
|
this.started = false;
|
|
2121
|
-
this.
|
|
2122
|
-
const
|
|
2123
|
-
for (const element of staleElements) {
|
|
2150
|
+
this.removeTemporaryElements = ((_event) => {
|
|
2151
|
+
for (const element of this.temporaryElements) {
|
|
2124
2152
|
element.remove();
|
|
2125
2153
|
}
|
|
2126
2154
|
});
|
|
@@ -2128,15 +2156,25 @@ class CacheObserver {
|
|
|
2128
2156
|
start() {
|
|
2129
2157
|
if (!this.started) {
|
|
2130
2158
|
this.started = true;
|
|
2131
|
-
addEventListener("turbo:before-cache", this.
|
|
2159
|
+
addEventListener("turbo:before-cache", this.removeTemporaryElements, false);
|
|
2132
2160
|
}
|
|
2133
2161
|
}
|
|
2134
2162
|
stop() {
|
|
2135
2163
|
if (this.started) {
|
|
2136
2164
|
this.started = false;
|
|
2137
|
-
removeEventListener("turbo:before-cache", this.
|
|
2165
|
+
removeEventListener("turbo:before-cache", this.removeTemporaryElements, false);
|
|
2138
2166
|
}
|
|
2139
2167
|
}
|
|
2168
|
+
get temporaryElements() {
|
|
2169
|
+
return [...document.querySelectorAll(this.selector), ...this.temporaryElementsWithDeprecation];
|
|
2170
|
+
}
|
|
2171
|
+
get temporaryElementsWithDeprecation() {
|
|
2172
|
+
const elements = document.querySelectorAll(this.deprecatedSelector);
|
|
2173
|
+
if (elements.length) {
|
|
2174
|
+
console.warn(`The ${this.deprecatedSelector} selector is deprecated and will be removed in a future version. Use ${this.selector} instead.`);
|
|
2175
|
+
}
|
|
2176
|
+
return [...elements];
|
|
2177
|
+
}
|
|
2140
2178
|
}
|
|
2141
2179
|
|
|
2142
2180
|
class FrameRedirector {
|
|
@@ -2335,7 +2373,7 @@ class Navigator {
|
|
|
2335
2373
|
if (formSubmission == this.formSubmission) {
|
|
2336
2374
|
const responseHTML = await fetchResponse.responseHTML;
|
|
2337
2375
|
if (responseHTML) {
|
|
2338
|
-
const shouldCacheSnapshot = formSubmission.
|
|
2376
|
+
const shouldCacheSnapshot = formSubmission.isSafe;
|
|
2339
2377
|
if (!shouldCacheSnapshot) {
|
|
2340
2378
|
this.view.clearSnapshotCache();
|
|
2341
2379
|
}
|
|
@@ -3295,6 +3333,9 @@ var Turbo = /*#__PURE__*/Object.freeze({
|
|
|
3295
3333
|
StreamActions: StreamActions
|
|
3296
3334
|
});
|
|
3297
3335
|
|
|
3336
|
+
class TurboFrameMissingError extends Error {
|
|
3337
|
+
}
|
|
3338
|
+
|
|
3298
3339
|
class FrameController {
|
|
3299
3340
|
constructor(element) {
|
|
3300
3341
|
this.fetchResponseLoaded = (_fetchResponse) => { };
|
|
@@ -3395,30 +3436,16 @@ class FrameController {
|
|
|
3395
3436
|
try {
|
|
3396
3437
|
const html = await fetchResponse.responseHTML;
|
|
3397
3438
|
if (html) {
|
|
3398
|
-
const
|
|
3399
|
-
const
|
|
3400
|
-
if (
|
|
3401
|
-
|
|
3402
|
-
const renderer = new FrameRenderer(this, this.view.snapshot, snapshot, FrameRenderer.renderElement, false, false);
|
|
3403
|
-
if (this.view.renderPromise)
|
|
3404
|
-
await this.view.renderPromise;
|
|
3405
|
-
this.changeHistory();
|
|
3406
|
-
await this.view.render(renderer);
|
|
3407
|
-
this.complete = true;
|
|
3408
|
-
session.frameRendered(fetchResponse, this.element);
|
|
3409
|
-
session.frameLoaded(this.element);
|
|
3410
|
-
this.fetchResponseLoaded(fetchResponse);
|
|
3439
|
+
const document = parseHTMLDocument(html);
|
|
3440
|
+
const pageSnapshot = PageSnapshot.fromDocument(document);
|
|
3441
|
+
if (pageSnapshot.isVisitable) {
|
|
3442
|
+
await this.loadFrameResponse(fetchResponse, document);
|
|
3411
3443
|
}
|
|
3412
|
-
else
|
|
3413
|
-
|
|
3414
|
-
this.visitResponse(fetchResponse.response);
|
|
3444
|
+
else {
|
|
3445
|
+
await this.handleUnvisitableFrameResponse(fetchResponse);
|
|
3415
3446
|
}
|
|
3416
3447
|
}
|
|
3417
3448
|
}
|
|
3418
|
-
catch (error) {
|
|
3419
|
-
console.error(error);
|
|
3420
|
-
this.view.invalidate();
|
|
3421
|
-
}
|
|
3422
3449
|
finally {
|
|
3423
3450
|
this.fetchResponseLoaded = () => { };
|
|
3424
3451
|
}
|
|
@@ -3471,7 +3498,6 @@ class FrameController {
|
|
|
3471
3498
|
this.resolveVisitPromise();
|
|
3472
3499
|
}
|
|
3473
3500
|
async requestFailedWithResponse(request, response) {
|
|
3474
|
-
console.error(response);
|
|
3475
3501
|
await this.loadResponse(response);
|
|
3476
3502
|
this.resolveVisitPromise();
|
|
3477
3503
|
}
|
|
@@ -3489,9 +3515,13 @@ class FrameController {
|
|
|
3489
3515
|
const frame = this.findFrameElement(formSubmission.formElement, formSubmission.submitter);
|
|
3490
3516
|
frame.delegate.proposeVisitIfNavigatedWithAction(frame, formSubmission.formElement, formSubmission.submitter);
|
|
3491
3517
|
frame.delegate.loadResponse(response);
|
|
3518
|
+
if (!formSubmission.isSafe) {
|
|
3519
|
+
session.clearCache();
|
|
3520
|
+
}
|
|
3492
3521
|
}
|
|
3493
3522
|
formSubmissionFailedWithResponse(formSubmission, fetchResponse) {
|
|
3494
3523
|
this.element.delegate.loadResponse(fetchResponse);
|
|
3524
|
+
session.clearCache();
|
|
3495
3525
|
}
|
|
3496
3526
|
formSubmissionErrored(formSubmission, error) {
|
|
3497
3527
|
console.error(error);
|
|
@@ -3519,6 +3549,24 @@ class FrameController {
|
|
|
3519
3549
|
willRenderFrame(currentElement, _newElement) {
|
|
3520
3550
|
this.previousFrameElement = currentElement.cloneNode(true);
|
|
3521
3551
|
}
|
|
3552
|
+
async loadFrameResponse(fetchResponse, document) {
|
|
3553
|
+
const newFrameElement = await this.extractForeignFrameElement(document.body);
|
|
3554
|
+
if (newFrameElement) {
|
|
3555
|
+
const snapshot = new Snapshot(newFrameElement);
|
|
3556
|
+
const renderer = new FrameRenderer(this, this.view.snapshot, snapshot, FrameRenderer.renderElement, false, false);
|
|
3557
|
+
if (this.view.renderPromise)
|
|
3558
|
+
await this.view.renderPromise;
|
|
3559
|
+
this.changeHistory();
|
|
3560
|
+
await this.view.render(renderer);
|
|
3561
|
+
this.complete = true;
|
|
3562
|
+
session.frameRendered(fetchResponse, this.element);
|
|
3563
|
+
session.frameLoaded(this.element);
|
|
3564
|
+
this.fetchResponseLoaded(fetchResponse);
|
|
3565
|
+
}
|
|
3566
|
+
else if (this.willHandleFrameMissingFromResponse(fetchResponse)) {
|
|
3567
|
+
this.handleFrameMissingFromResponse(fetchResponse);
|
|
3568
|
+
}
|
|
3569
|
+
}
|
|
3522
3570
|
async visit(url) {
|
|
3523
3571
|
var _a;
|
|
3524
3572
|
const request = new FetchRequest(this, FetchMethod.get, url, new URLSearchParams(), this.element);
|
|
@@ -3571,6 +3619,10 @@ class FrameController {
|
|
|
3571
3619
|
session.history.update(method, expandURL(this.element.src || ""), this.restorationIdentifier);
|
|
3572
3620
|
}
|
|
3573
3621
|
}
|
|
3622
|
+
async handleUnvisitableFrameResponse(fetchResponse) {
|
|
3623
|
+
console.warn(`The response (${fetchResponse.statusCode}) from <turbo-frame id="${this.element.id}"> is performing a full page visit due to turbo-visit-control.`);
|
|
3624
|
+
await this.visitResponse(fetchResponse.response);
|
|
3625
|
+
}
|
|
3574
3626
|
willHandleFrameMissingFromResponse(fetchResponse) {
|
|
3575
3627
|
this.element.setAttribute("complete", "");
|
|
3576
3628
|
const response = fetchResponse.response;
|
|
@@ -3589,6 +3641,14 @@ class FrameController {
|
|
|
3589
3641
|
});
|
|
3590
3642
|
return !event.defaultPrevented;
|
|
3591
3643
|
}
|
|
3644
|
+
handleFrameMissingFromResponse(fetchResponse) {
|
|
3645
|
+
this.view.missing();
|
|
3646
|
+
this.throwFrameMissingError(fetchResponse);
|
|
3647
|
+
}
|
|
3648
|
+
throwFrameMissingError(fetchResponse) {
|
|
3649
|
+
const message = `The response (${fetchResponse.statusCode}) did not contain the expected <turbo-frame id="${this.element.id}"> and will be ignored. To perform a full page visit instead, set turbo-visit-control to reload.`;
|
|
3650
|
+
throw new TurboFrameMissingError(message);
|
|
3651
|
+
}
|
|
3592
3652
|
async visitResponse(response) {
|
|
3593
3653
|
const wrapped = new FetchResponse(response);
|
|
3594
3654
|
const responseHTML = await wrapped.responseHTML;
|