diff --git a/Appraisals b/Appraisals
index a28c31403..98bc285fc 100644
--- a/Appraisals
+++ b/Appraisals
@@ -17,6 +17,7 @@ end
appraise 'shakapacker' do
gem 'rails', '~> 7.0.x'
gem 'shakapacker', '7.0.2'
+ gem 'turbo-rails'
end
appraise 'base' do
diff --git a/gemfiles/base.gemfile.lock b/gemfiles/base.gemfile.lock
index 4576466d3..89ddd222b 100644
--- a/gemfiles/base.gemfile.lock
+++ b/gemfiles/base.gemfile.lock
@@ -236,6 +236,10 @@ GEM
thor (1.2.2)
tilt (2.2.0)
timeout (0.4.0)
+ turbo-rails (1.4.0)
+ actionpack (>= 6.0.0)
+ activejob (>= 6.0.0)
+ railties (>= 6.0.0)
tzinfo (2.0.6)
concurrent-ruby (~> 1.0)
websocket (1.2.9)
@@ -267,6 +271,7 @@ DEPENDENCIES
react-rails!
selenium-webdriver
test-unit (~> 2.5)
+ turbo-rails
BUNDLED WITH
2.4.9
diff --git a/gemfiles/shakapacker.gemfile b/gemfiles/shakapacker.gemfile
index 86c2338d1..75713c5a0 100644
--- a/gemfiles/shakapacker.gemfile
+++ b/gemfiles/shakapacker.gemfile
@@ -4,5 +4,6 @@ source "http://rubygems.org"
gem "rails", "~> 7.0.x"
gem "shakapacker", "7.0.2"
+gem "turbo-rails"
gemspec path: "../"
diff --git a/gemfiles/shakapacker.gemfile.lock b/gemfiles/shakapacker.gemfile.lock
index d805cd469..e1f3038c0 100644
--- a/gemfiles/shakapacker.gemfile.lock
+++ b/gemfiles/shakapacker.gemfile.lock
@@ -244,6 +244,10 @@ GEM
thor (1.2.2)
tilt (2.2.0)
timeout (0.4.0)
+ turbo-rails (1.5.0)
+ actionpack (>= 6.0.0)
+ activejob (>= 6.0.0)
+ railties (>= 6.0.0)
tzinfo (2.0.6)
concurrent-ruby (~> 1.0)
websocket (1.2.9)
@@ -276,6 +280,7 @@ DEPENDENCIES
selenium-webdriver
shakapacker (= 7.0.2)
test-unit (~> 2.5)
+ turbo-rails
BUNDLED WITH
2.4.9
diff --git a/test/dummy/app/controllers/counters_controller.rb b/test/dummy/app/controllers/counters_controller.rb
new file mode 100644
index 000000000..5e9bdba98
--- /dev/null
+++ b/test/dummy/app/controllers/counters_controller.rb
@@ -0,0 +1,9 @@
+class CountersController < ApplicationController
+ def index
+ @counters = [{ name: "Counter 1" }]
+ end
+
+ def create
+ @counter = { name: "Counter 2" }
+ end
+end
diff --git a/test/dummy/app/javascript/components/Counter.js b/test/dummy/app/javascript/components/Counter.js
new file mode 100644
index 000000000..f1bcd6446
--- /dev/null
+++ b/test/dummy/app/javascript/components/Counter.js
@@ -0,0 +1,23 @@
+var React = require("react");
+var createReactClass = require("create-react-class");
+
+module.exports = createReactClass({
+ getInitialState: function () {
+ return { count: 0 };
+ },
+ handleClick: function () {
+ this.setState({ count: this.state.count + 1 });
+ },
+ render: function () {
+ return (
+
+
+ {this.props.name} - {this.state.count}
+
+
+
+ );
+ },
+});
diff --git a/test/dummy/app/javascript/controllers/mount_counters.js b/test/dummy/app/javascript/controllers/mount_counters.js
new file mode 100644
index 000000000..363687524
--- /dev/null
+++ b/test/dummy/app/javascript/controllers/mount_counters.js
@@ -0,0 +1,26 @@
+var { Controller } = require("@hotwired/stimulus");
+var ReactRailsUJS = require("react_ujs");
+
+module.exports = class extends Controller {
+ connect() {
+ this.observeChange();
+ }
+
+ disconnect() {
+ this.observer.disconnect();
+ }
+
+ observeChange() {
+ var element = this.element;
+ var callback = function (mutationsList, _observer) {
+ mutationsList.forEach(function (mutation) {
+ if (mutation.type === "childList") {
+ ReactRailsUJS.mountComponents(element);
+ }
+ });
+ };
+
+ this.observer = new MutationObserver(callback);
+ this.observer.observe(this.element, { childList: true });
+ }
+};
diff --git a/test/dummy/app/javascript/packs/application.js b/test/dummy/app/javascript/packs/application.js
index bffb39c69..74444a371 100644
--- a/test/dummy/app/javascript/packs/application.js
+++ b/test/dummy/app/javascript/packs/application.js
@@ -1,8 +1,15 @@
-var ctx = require.context("components", true)
-var ReactRailsUJS = require("react_ujs")
-ReactRailsUJS.useContext(ctx)
-var React = require("react")
+require("@hotwired/turbo-rails");
+var { Application } = require("@hotwired/stimulus");
+var MountCountersController = require("../controllers/mount_counters");
-window.GlobalComponent = function(props) {
- return React.createElement("h1", null, "Global Component")
-}
+window.Stimulus = Application.start();
+Stimulus.register("mount-counters", MountCountersController);
+
+var ctx = require.context("components", true);
+var ReactRailsUJS = require("react_ujs");
+ReactRailsUJS.useContext(ctx);
+var React = require("react");
+
+window.GlobalComponent = function (props) {
+ return React.createElement("h1", null, "Global Component");
+};
diff --git a/test/dummy/app/views/counters/create.turbo_stream.erb b/test/dummy/app/views/counters/create.turbo_stream.erb
new file mode 100644
index 000000000..e0e93eb23
--- /dev/null
+++ b/test/dummy/app/views/counters/create.turbo_stream.erb
@@ -0,0 +1,3 @@
+<%= turbo_stream.append :counters do %>
+ <%= react_component("Counter", @counter) %>
+<% end %>
diff --git a/test/dummy/app/views/counters/index.html.erb b/test/dummy/app/views/counters/index.html.erb
new file mode 100644
index 000000000..bbac3df62
--- /dev/null
+++ b/test/dummy/app/views/counters/index.html.erb
@@ -0,0 +1,10 @@
+React 18 bug reproduction
+
+<%= turbo_frame_tag :counters, data: { controller: "mount-counters" } do %>
+ <% @counters.each do |counter| %>
+ <%= react_component("Counter", counter) %>
+ <% end %>
+<% end %>
+<%= form_with(url: counters_path, method: :post, data: { turbo: true, turbo_stream: true }) do |form| %>
+ <%= form.submit "Add counter" %>
+<% end %>
diff --git a/test/dummy/config/routes.rb b/test/dummy/config/routes.rb
index ef57ce2ac..6fdeabe75 100644
--- a/test/dummy/config/routes.rb
+++ b/test/dummy/config/routes.rb
@@ -3,6 +3,7 @@
Dummy::Application.routes.draw do
get "no-turbolinks", to: "pages#no_turbolinks"
resources :pages, only: [:show]
+ resources :counters, only: [:create, :index]
resources :server, only: [:show] do
collection do
get :console_example
diff --git a/test/dummy/package.json b/test/dummy/package.json
index f4908130e..e436baa7c 100644
--- a/test/dummy/package.json
+++ b/test/dummy/package.json
@@ -6,6 +6,8 @@
"@babel/preset-react": "^7.17.12",
"@babel/preset-typescript": "^7.17.12",
"@babel/runtime": "^7.18.3",
+ "@hotwired/stimulus": "^3.2.2",
+ "@hotwired/turbo-rails": "^7.3.0",
"babel-loader": "^8.2.5",
"babel-plugin-macros": "^3.1.0",
"compression-webpack-plugin": "^9.2.0",
@@ -14,8 +16,8 @@
"css-minimizer-webpack-plugin": "^2.0.0",
"mini-css-extract-plugin": "^1.6.2",
"pnp-webpack-plugin": "^1.7.0",
- "react": "^17.0.2",
- "react-dom": "^17.0.2",
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0",
"react_ujs": "file:.yalc/react_ujs",
"shakapacker": "7.0.2",
"style-loader": "^3.3.1",
diff --git a/test/dummy/yarn.lock b/test/dummy/yarn.lock
index 00473501d..3d84a0d5f 100644
--- a/test/dummy/yarn.lock
+++ b/test/dummy/yarn.lock
@@ -161,12 +161,12 @@
dependencies:
"@babel/types" "^7.18.6"
-"@babel/helper-module-imports@^7.22.5":
- version "7.22.5"
- resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.22.5.tgz#1a8f4c9f4027d23f520bd76b364d44434a72660c"
- integrity sha512-8Dl6+HD/cKifutF5qGd/8ZJi84QeAKh+CEe1sBzz8UayBBGg1dAIJrdHOcOM5b2MpzWL2yuotJTtGjETq0qjXg==
+"@babel/helper-module-imports@^7.22.15":
+ version "7.22.15"
+ resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz#16146307acdc40cc00c3b2c647713076464bdbf0"
+ integrity sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==
dependencies:
- "@babel/types" "^7.22.5"
+ "@babel/types" "^7.22.15"
"@babel/helper-module-transforms@^7.18.6", "@babel/helper-module-transforms@^7.20.11", "@babel/helper-module-transforms@^7.21.2":
version "7.21.2"
@@ -257,20 +257,20 @@
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz#7eea834cf32901ffdc1a7ee555e2f9c27e249ca2"
integrity sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==
-"@babel/helper-validator-identifier@^7.22.5":
- version "7.22.5"
- resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz#9544ef6a33999343c8740fa51350f30eeaaaf193"
- integrity sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==
+"@babel/helper-validator-identifier@^7.22.20":
+ version "7.22.20"
+ resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz#c4ae002c61d2879e724581d96665583dbc1dc0e0"
+ integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==
"@babel/helper-validator-option@^7.18.6", "@babel/helper-validator-option@^7.21.0":
version "7.21.0"
resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.21.0.tgz#8224c7e13ace4bafdc4004da2cf064ef42673180"
integrity sha512-rmL/B8/f0mKS2baE9ZpyTcTavvEuWhTTW8amjzXNvYG4AwBsqTLikfXsEofsJEfKHf+HQVQbFOHy6o+4cnC/fQ==
-"@babel/helper-validator-option@^7.22.5":
- version "7.22.5"
- resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.22.5.tgz#de52000a15a177413c8234fa3a8af4ee8102d0ac"
- integrity sha512-R3oB6xlIVKUnxNUxbmgq7pKjxpru24zlimpE8WK47fACIlM0II/Hm1RS8IaOI7NgCr6LNS+jl5l75m20npAziw==
+"@babel/helper-validator-option@^7.22.15":
+ version "7.22.15"
+ resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz#694c30dfa1d09a6534cdfcafbe56789d36aba040"
+ integrity sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA==
"@babel/helper-wrap-function@^7.18.9":
version "7.20.5"
@@ -507,9 +507,9 @@
"@babel/helper-plugin-utils" "^7.18.6"
"@babel/plugin-syntax-jsx@^7.22.5":
- version "7.22.5"
- resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.22.5.tgz#a6b68e84fb76e759fc3b93e901876ffabbe1d918"
- integrity sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==
+ version "7.23.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.23.3.tgz#8f2e4f8a9b5f9aa16067e142c1ac9cd9f810f473"
+ integrity sha512-EB2MELswq55OHUoRZLGg/zC7QWUKfNLpE57m/S2yr1uEneIgsTgrSzXP3NXEsMkVn76OlaVVnzN+ugObuYGwhg==
dependencies:
"@babel/helper-plugin-utils" "^7.22.5"
@@ -768,10 +768,10 @@
dependencies:
"@babel/helper-plugin-utils" "^7.18.6"
-"@babel/plugin-transform-react-display-name@^7.22.5":
- version "7.22.5"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.22.5.tgz#3c4326f9fce31c7968d6cb9debcaf32d9e279a2b"
- integrity sha512-PVk3WPYudRF5z4GKMEYUrLjPl38fJSKNaEOkFuoprioowGuWN6w2RKznuFNSlJx7pzzXXStPUnNSOEO0jL5EVw==
+"@babel/plugin-transform-react-display-name@^7.23.3":
+ version "7.23.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.23.3.tgz#70529f034dd1e561045ad3c8152a267f0d7b6200"
+ integrity sha512-GnvhtVfA2OAtzdX58FJxU19rhoGeQzyVndw3GgtdECQvQFXPEZIOVULHVZGAYmOgmqjXpVpfocAbSjh99V/Fqw==
dependencies:
"@babel/helper-plugin-utils" "^7.22.5"
@@ -800,16 +800,16 @@
"@babel/plugin-syntax-jsx" "^7.18.6"
"@babel/types" "^7.21.0"
-"@babel/plugin-transform-react-jsx@^7.22.5":
- version "7.22.5"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.22.5.tgz#932c291eb6dd1153359e2a90cb5e557dcf068416"
- integrity sha512-rog5gZaVbUip5iWDMTYbVM15XQq+RkUKhET/IHR6oizR+JEoN6CAfTTuHcK4vwUyzca30qqHqEpzBOnaRMWYMA==
+"@babel/plugin-transform-react-jsx@^7.22.15", "@babel/plugin-transform-react-jsx@^7.22.5":
+ version "7.22.15"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.22.15.tgz#7e6266d88705d7c49f11c98db8b9464531289cd6"
+ integrity sha512-oKckg2eZFa8771O/5vi7XeTvmM6+O9cxZu+kanTU7tD4sin5nO/G8jGJhq8Hvt2Z0kUoEDRayuZLaUlYl8QuGA==
dependencies:
"@babel/helper-annotate-as-pure" "^7.22.5"
- "@babel/helper-module-imports" "^7.22.5"
+ "@babel/helper-module-imports" "^7.22.15"
"@babel/helper-plugin-utils" "^7.22.5"
"@babel/plugin-syntax-jsx" "^7.22.5"
- "@babel/types" "^7.22.5"
+ "@babel/types" "^7.22.15"
"@babel/plugin-transform-react-pure-annotations@^7.18.6":
version "7.18.6"
@@ -819,10 +819,10 @@
"@babel/helper-annotate-as-pure" "^7.18.6"
"@babel/helper-plugin-utils" "^7.18.6"
-"@babel/plugin-transform-react-pure-annotations@^7.22.5":
- version "7.22.5"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.22.5.tgz#1f58363eef6626d6fa517b95ac66fe94685e32c0"
- integrity sha512-gP4k85wx09q+brArVinTXhWiyzLl9UpmGva0+mWyKxk6JZequ05x3eUcIUE+FyttPKJFRRVtAvQaJ6YF9h1ZpA==
+"@babel/plugin-transform-react-pure-annotations@^7.23.3":
+ version "7.23.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.23.3.tgz#fabedbdb8ee40edf5da96f3ecfc6958e3783b93c"
+ integrity sha512-qMFdSS+TUhB7Q/3HVPnEdYJDQIk57jkntAwSuz9xfSE4n+3I+vHYCli3HoHawN1Z3RfCz/y1zXA/JXjG6cVImQ==
dependencies:
"@babel/helper-annotate-as-pure" "^7.22.5"
"@babel/helper-plugin-utils" "^7.22.5"
@@ -1020,16 +1020,16 @@
"@babel/plugin-transform-react-pure-annotations" "^7.18.6"
"@babel/preset-react@^7.22.5":
- version "7.22.5"
- resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.22.5.tgz#c4d6058fbf80bccad02dd8c313a9aaa67e3c3dd6"
- integrity sha512-M+Is3WikOpEJHgR385HbuCITPTaPRaNkibTEa9oiofmJvIsrceb4yp9RL9Kb+TE8LznmeyZqpP+Lopwcx59xPQ==
+ version "7.23.3"
+ resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.23.3.tgz#f73ca07e7590f977db07eb54dbe46538cc015709"
+ integrity sha512-tbkHOS9axH6Ysf2OUEqoSZ6T3Fa2SrNH6WTWSPBboxKzdxNc9qOICeLXkNG0ZEwbQ1HY8liwOce4aN/Ceyuq6w==
dependencies:
"@babel/helper-plugin-utils" "^7.22.5"
- "@babel/helper-validator-option" "^7.22.5"
- "@babel/plugin-transform-react-display-name" "^7.22.5"
- "@babel/plugin-transform-react-jsx" "^7.22.5"
+ "@babel/helper-validator-option" "^7.22.15"
+ "@babel/plugin-transform-react-display-name" "^7.23.3"
+ "@babel/plugin-transform-react-jsx" "^7.22.15"
"@babel/plugin-transform-react-jsx-development" "^7.22.5"
- "@babel/plugin-transform-react-pure-annotations" "^7.22.5"
+ "@babel/plugin-transform-react-pure-annotations" "^7.23.3"
"@babel/preset-typescript@^7.17.12":
version "7.21.0"
@@ -1086,13 +1086,13 @@
"@babel/helper-validator-identifier" "^7.19.1"
to-fast-properties "^2.0.0"
-"@babel/types@^7.22.5":
- version "7.22.5"
- resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.22.5.tgz#cd93eeaab025880a3a47ec881f4b096a5b786fbe"
- integrity sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==
+"@babel/types@^7.22.15", "@babel/types@^7.22.5":
+ version "7.23.3"
+ resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.23.3.tgz#d5ea892c07f2ec371ac704420f4dcdb07b5f9598"
+ integrity sha512-OZnvoH2l8PK5eUvEcUyCt/sXgr/h+UWpVuBbOljwcrAgUl6lpchoQ++PHGyQy1AtYnVA6CEq3y5xeEI10brpXw==
dependencies:
"@babel/helper-string-parser" "^7.22.5"
- "@babel/helper-validator-identifier" "^7.22.5"
+ "@babel/helper-validator-identifier" "^7.22.20"
to-fast-properties "^2.0.0"
"@discoveryjs/json-ext@^0.5.0":
@@ -1100,19 +1100,37 @@
resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70"
integrity sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==
-"@jest/schemas@^29.6.0":
- version "29.6.0"
- resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-29.6.0.tgz#0f4cb2c8e3dca80c135507ba5635a4fd755b0040"
- integrity sha512-rxLjXyJBTL4LQeJW3aKo0M/+GkCOXsO+8i9Iu7eDb6KwtP65ayoDsitrdPBtujxQ88k4wI2FNYfa6TOGwSn6cQ==
+"@hotwired/stimulus@^3.2.2":
+ version "3.2.2"
+ resolved "https://registry.yarnpkg.com/@hotwired/stimulus/-/stimulus-3.2.2.tgz#071aab59c600fed95b97939e605ff261a4251608"
+ integrity sha512-eGeIqNOQpXoPAIP7tC1+1Yc1yl1xnwYqg+3mzqxyrbE5pg5YFBZcA6YoTiByJB6DKAEsiWtl6tjTJS4IYtbB7A==
+
+"@hotwired/turbo-rails@^7.3.0":
+ version "7.3.0"
+ resolved "https://registry.yarnpkg.com/@hotwired/turbo-rails/-/turbo-rails-7.3.0.tgz#422c21752509f3edcd6c7b2725bbe9e157815f51"
+ integrity sha512-fvhO64vp/a2UVQ3jue9WTc2JisMv9XilIC7ViZmXAREVwiQ2S4UC7Go8f9A1j4Xu7DBI6SbFdqILk5ImqVoqyA==
+ dependencies:
+ "@hotwired/turbo" "^7.3.0"
+ "@rails/actioncable" "^7.0"
+
+"@hotwired/turbo@^7.3.0":
+ version "7.3.0"
+ resolved "https://registry.yarnpkg.com/@hotwired/turbo/-/turbo-7.3.0.tgz#2226000fff1aabda9fd9587474565c9929dbf15d"
+ integrity sha512-Dcu+NaSvHLT7EjrDrkEmH4qET2ZJZ5IcCWmNXxNQTBwlnE5tBZfN6WxZ842n5cHV52DH/AKNirbPBtcEXDLW4g==
+
+"@jest/schemas@^29.6.3":
+ version "29.6.3"
+ resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-29.6.3.tgz#430b5ce8a4e0044a7e3819663305a7b3091c8e03"
+ integrity sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==
dependencies:
"@sinclair/typebox" "^0.27.8"
-"@jest/types@^29.6.1":
- version "29.6.1"
- resolved "https://registry.yarnpkg.com/@jest/types/-/types-29.6.1.tgz#ae79080278acff0a6af5eb49d063385aaa897bf2"
- integrity sha512-tPKQNMPuXgvdOn2/Lg9HNfUvjYVGolt04Hp03f5hAk878uwOLikN+JzeLY0HcVgKgFl9Hs3EIqpu3WX27XNhnw==
+"@jest/types@^29.6.3":
+ version "29.6.3"
+ resolved "https://registry.yarnpkg.com/@jest/types/-/types-29.6.3.tgz#1131f8cf634e7e84c5e77bab12f052af585fba59"
+ integrity sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==
dependencies:
- "@jest/schemas" "^29.6.0"
+ "@jest/schemas" "^29.6.3"
"@types/istanbul-lib-coverage" "^2.0.0"
"@types/istanbul-reports" "^3.0.0"
"@types/node" "*"
@@ -1141,6 +1159,11 @@
resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78"
integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==
+"@jridgewell/resolve-uri@^3.1.0":
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz#c08679063f279615a3326583ba3a90d1d82cc721"
+ integrity sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==
+
"@jridgewell/set-array@^1.0.0", "@jridgewell/set-array@^1.0.1":
version "1.1.2"
resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72"
@@ -1159,6 +1182,11 @@
resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24"
integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==
+"@jridgewell/sourcemap-codec@^1.4.14":
+ version "1.4.15"
+ resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32"
+ integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==
+
"@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.9":
version "0.3.17"
resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz#793041277af9073b0951a7fe0f0d8c4c98c36985"
@@ -1168,12 +1196,12 @@
"@jridgewell/sourcemap-codec" "1.4.14"
"@jridgewell/trace-mapping@^0.3.18":
- version "0.3.18"
- resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz#25783b2086daf6ff1dcb53c9249ae480e4dd4cd6"
- integrity sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==
+ version "0.3.20"
+ resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz#72e45707cf240fa6b081d0366f8265b0cd10197f"
+ integrity sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==
dependencies:
- "@jridgewell/resolve-uri" "3.1.0"
- "@jridgewell/sourcemap-codec" "1.4.14"
+ "@jridgewell/resolve-uri" "^3.1.0"
+ "@jridgewell/sourcemap-codec" "^1.4.14"
"@leichtgewicht/ip-codec@^2.0.1":
version "2.0.4"
@@ -1195,6 +1223,11 @@
schema-utils "^3.0.0"
source-map "^0.7.3"
+"@rails/actioncable@^7.0":
+ version "7.1.1"
+ resolved "https://registry.yarnpkg.com/@rails/actioncable/-/actioncable-7.1.1.tgz#e8c49769d41f35a4473133c259cc98adc04dddf8"
+ integrity sha512-ZRJ9rdwFQQjRbtgJnweY0/4UQyxN6ojEGRdib0JkjnuIciv+4ok/aAeZmBJqNreTMaBqS0eHyA9hCArwN58opg==
+
"@sinclair/typebox@^0.27.8":
version "0.27.8"
resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.27.8.tgz#6667fac16c436b5434a387a34dedb013198f6e6e"
@@ -1288,21 +1321,21 @@
"@types/node" "*"
"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0":
- version "2.0.4"
- resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz#8467d4b3c087805d63580480890791277ce35c44"
- integrity sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==
+ version "2.0.6"
+ resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz#7739c232a1fee9b4d3ce8985f314c0c6d33549d7"
+ integrity sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==
"@types/istanbul-lib-report@*":
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#c14c24f18ea8190c118ee7562b7ff99a36552686"
- integrity sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==
+ version "3.0.3"
+ resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz#53047614ae72e19fc0401d872de3ae2b4ce350bf"
+ integrity sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==
dependencies:
"@types/istanbul-lib-coverage" "*"
"@types/istanbul-reports@^3.0.0":
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz#9153fe98bba2bd565a63add9436d6f0d7f8468ff"
- integrity sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==
+ version "3.0.4"
+ resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz#0f03e3d2f670fbdac586e34b433783070cc16f54"
+ integrity sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==
dependencies:
"@types/istanbul-lib-report" "*"
@@ -1371,14 +1404,14 @@
"@types/node" "*"
"@types/yargs-parser@*":
- version "21.0.0"
- resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.0.tgz#0c60e537fa790f5f9472ed2776c2b71ec117351b"
- integrity sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==
+ version "21.0.3"
+ resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.3.tgz#815e30b786d2e8f0dcd85fd5bcf5e1a04d008f15"
+ integrity sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==
"@types/yargs@^17.0.8":
- version "17.0.24"
- resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.24.tgz#b3ef8d50ad4aa6aecf6ddc97c580a00f5aa11902"
- integrity sha512-6i0aC7jV6QzQB8ne1joVZ0eSFIstHsCrobmOtghM11yGlH0j43FKL2UhWdELkyps0zuf7qVTUVCCR+tgSlyLLw==
+ version "17.0.31"
+ resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.31.tgz#8fd0089803fd55d8a285895a18b88cb71a99683c"
+ integrity sha512-bocYSx4DI8TmdlvxqGpVNXOgCNR1Jj0gNPhhAY+iz1rgKDAaYrAYdFYnhDV1IFuiuVc9HkOwyDcFxaTElF3/wg==
dependencies:
"@types/yargs-parser" "*"
@@ -1850,9 +1883,9 @@ chrome-trace-event@^1.0.2:
integrity sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==
ci-info@^3.2.0:
- version "3.8.0"
- resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.8.0.tgz#81408265a5380c929f0bc665d62256628ce9ef91"
- integrity sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==
+ version "3.9.0"
+ resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.9.0.tgz#4279a62028a7b1f262f3473fc9605f5e218c59b4"
+ integrity sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==
clone-deep@^4.0.1:
version "4.0.1"
@@ -2240,6 +2273,13 @@ cssnano@^6.0.1:
cssnano-preset-default "^6.0.1"
lilconfig "^2.1.0"
+csso@5.0.5:
+ version "5.0.5"
+ resolved "https://registry.yarnpkg.com/csso/-/csso-5.0.5.tgz#f9b7fe6cc6ac0b7d90781bb16d5e9874303e2ca6"
+ integrity sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==
+ dependencies:
+ css-tree "~2.2.0"
+
csso@^4.2.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/csso/-/csso-4.2.0.tgz#ea3a561346e8dc9f546d6febedd50187cf389529"
@@ -2247,13 +2287,6 @@ csso@^4.2.0:
dependencies:
css-tree "^1.1.2"
-csso@^5.0.5:
- version "5.0.5"
- resolved "https://registry.yarnpkg.com/csso/-/csso-5.0.5.tgz#f9b7fe6cc6ac0b7d90781bb16d5e9874303e2ca6"
- integrity sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==
- dependencies:
- css-tree "~2.2.0"
-
debug@2.6.9:
version "2.6.9"
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
@@ -2974,12 +3007,12 @@ isobject@^3.0.1:
resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df"
integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8=
-jest-util@^29.6.1:
- version "29.6.1"
- resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-29.6.1.tgz#c9e29a87a6edbf1e39e6dee2b4689b8a146679cb"
- integrity sha512-NRFCcjc+/uO3ijUVyNOQJluf8PtGCe/W6cix36+M3cTFgiYqFOOW5MgN4JOOcvbUhcKTYVd1CvHz/LWi8d16Mg==
+jest-util@^29.7.0:
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-29.7.0.tgz#23c2b62bfb22be82b44de98055802ff3710fc0bc"
+ integrity sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==
dependencies:
- "@jest/types" "^29.6.1"
+ "@jest/types" "^29.6.3"
"@types/node" "*"
chalk "^4.0.0"
ci-info "^3.2.0"
@@ -3005,12 +3038,12 @@ jest-worker@^27.4.5:
supports-color "^8.0.0"
jest-worker@^29.4.3:
- version "29.6.1"
- resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-29.6.1.tgz#64b015f0e985ef3a8ad049b61fe92b3db74a5319"
- integrity sha512-U+Wrbca7S8ZAxAe9L6nb6g8kPdia5hj32Puu5iOqBCMTMWFHXuK6dOV2IFrpedbTV8fjMFLdWNttQTBL6u2MRA==
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-29.7.0.tgz#acad073acbbaeb7262bd5389e1bcf43e10058d4a"
+ integrity sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==
dependencies:
"@types/node" "*"
- jest-util "^29.6.1"
+ jest-util "^29.7.0"
merge-stream "^2.0.0"
supports-color "^8.0.0"
@@ -3309,11 +3342,16 @@ multicast-dns@^7.2.5:
dns-packet "^5.2.2"
thunky "^1.0.2"
-nanoid@^3.3.4, nanoid@^3.3.6:
+nanoid@^3.3.4:
version "3.3.6"
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.6.tgz#443380c856d6e9f9824267d960b4236ad583ea4c"
integrity sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==
+nanoid@^3.3.6:
+ version "3.3.7"
+ resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.7.tgz#d0c301a691bc8d54efa0a2226ccf3fe2fd656bd8"
+ integrity sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==
+
negotiator@0.6.3:
version "0.6.3"
resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd"
@@ -3998,9 +4036,9 @@ postcss@^8.2.15, postcss@^8.2.9:
source-map-js "^1.0.2"
postcss@^8.4.21, postcss@^8.4.24:
- version "8.4.27"
- resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.27.tgz#234d7e4b72e34ba5a92c29636734349e0d9c3057"
- integrity sha512-gY/ACJtJPSmUFPDCHtX78+01fHa64FaU4zaaWfuh1MhGJISufJAH4cun6k/8fwsHYeK4UQmENQK+tRLCFJE8JQ==
+ version "8.4.31"
+ resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.31.tgz#92b451050a9f914da6755af352bdc0192508656d"
+ integrity sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==
dependencies:
nanoid "^3.3.6"
picocolors "^1.0.0"
@@ -4062,15 +4100,6 @@ raw-body@2.5.1:
iconv-lite "0.4.24"
unpipe "1.0.0"
-react-dom@^17.0.2:
- version "17.0.2"
- resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-17.0.2.tgz#ecffb6845e3ad8dbfcdc498f0d0a939736502c23"
- integrity sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==
- dependencies:
- loose-envify "^1.1.0"
- object-assign "^4.1.1"
- scheduler "^0.20.2"
-
react-dom@^18.2.0:
version "18.2.0"
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.2.0.tgz#22aaf38708db2674ed9ada224ca4aa708d821e3d"
@@ -4089,14 +4118,6 @@ react-refresh@^0.13.0:
resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.13.0.tgz#cbd01a4482a177a5da8d44c9755ebb1f26d5a1c1"
integrity sha512-XP8A9BT0CpRBD+NYLLeIhld/RqG9+gktUjW1FkE+Vm7OCinbG1SshcK5tb9ls4kzvjZr9mOQc7HYgBngEyPAXg==
-react@^17.0.2:
- version "17.0.2"
- resolved "https://registry.yarnpkg.com/react/-/react-17.0.2.tgz#d0b5cc516d29eb3eee383f75b62864cfb6800037"
- integrity sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==
- dependencies:
- loose-envify "^1.1.0"
- object-assign "^4.1.1"
-
react@^18.2.0:
version "18.2.0"
resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5"
@@ -4259,14 +4280,6 @@ safe-buffer@5.2.1, safe-buffer@>=5.1.0, safe-buffer@^5.1.0:
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
-scheduler@^0.20.2:
- version "0.20.2"
- resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.20.2.tgz#4baee39436e34aa93b4874bddcbf0fe8b8b50e91"
- integrity sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==
- dependencies:
- loose-envify "^1.1.0"
- object-assign "^4.1.1"
-
scheduler@^0.23.0:
version "0.23.0"
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.0.tgz#ba8041afc3d30eb206a487b6b384002e4e61fdfe"
@@ -4626,15 +4639,15 @@ svgo@^2.7.0:
stable "^0.1.8"
svgo@^3.0.2:
- version "3.0.2"
- resolved "https://registry.yarnpkg.com/svgo/-/svgo-3.0.2.tgz#5e99eeea42c68ee0dc46aa16da093838c262fe0a"
- integrity sha512-Z706C1U2pb1+JGP48fbazf3KxHrWOsLme6Rv7imFBn5EnuanDW1GPaA/P1/dvObE670JDePC3mnj0k0B7P0jjQ==
+ version "3.0.3"
+ resolved "https://registry.yarnpkg.com/svgo/-/svgo-3.0.3.tgz#8cdfece6d4a0dc1dc116766d806daf817c1798b8"
+ integrity sha512-X4UZvLhOglD5Xrp834HzGHf8RKUW0Ahigg/08yRO1no9t2NxffOkMiQ0WmaMIbaGlVTlSst2zWANsdhz5ybXgA==
dependencies:
"@trysound/sax" "0.2.0"
commander "^7.2.0"
css-select "^5.1.0"
css-tree "^2.2.1"
- csso "^5.0.5"
+ csso "5.0.5"
picocolors "^1.0.0"
tapable@^2.0, tapable@^2.1.1, tapable@^2.2.0:
diff --git a/test/react/rails/realtime_update_test.rb b/test/react/rails/realtime_update_test.rb
new file mode 100644
index 000000000..99d2c1967
--- /dev/null
+++ b/test/react/rails/realtime_update_test.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+
+require "test_helper"
+
+class RealtimeUpdateTest < ActiveSupport::TestCase
+ ShakapackerHelpers.when_shakapacker_available do
+ include Capybara::DSL
+
+ def assert_counter_count(page, timer_name, count)
+ assert page.has_content?("#{timer_name} - #{count}"), <<~MSG
+ #{page.body}
+ #{page.driver.browser.logs.get(:browser).inspect}
+ MSG
+ end
+
+ setup do
+ Capybara.current_driver = Capybara.javascript_driver
+ ShakapackerHelpers.compile
+ React::ServerRendering.reset_pool
+ end
+
+ teardown do
+ ShakapackerHelpers.clear_shakapacker_packs
+ end
+
+ test "doesn't re-mount the components trees when mountComponents is called" do
+ visit "/counters"
+
+ assert_counter_count(page, "Counter 1", 0)
+ page.click_button "Increment Counter 1"
+ assert_counter_count(page, "Counter 1", 1)
+
+ page.click_button "Add counter"
+ sleep 0.1
+ assert_counter_count(page, "Counter 1", 1)
+ assert_counter_count(page, "Counter 2", 0)
+ end
+ end
+end