diff --git a/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/async-function/actual.js b/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/async-function/actual.js
new file mode 100644
index 0000000000..b423432154
--- /dev/null
+++ b/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/async-function/actual.js
@@ -0,0 +1,9 @@
+export default {
+ async function(name) {
+ const uppercasedName = name.upperCase();
+
+ // awaits depending on uppercasedName go here
+
+ return ();
+ }
+};
diff --git a/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/async-function/expected.js b/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/async-function/expected.js
new file mode 100644
index 0000000000..28854cd24b
--- /dev/null
+++ b/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/async-function/expected.js
@@ -0,0 +1,13 @@
+function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } } function _next(value) { step("next", value); } function _throw(err) { step("throw", err); } _next(); }); }; }
+
+export default {
+ function(name) {
+ return _asyncToGenerator(function* () {
+ const uppercasedName = name.upperCase();
+
+ // awaits depending on uppercasedName go here
+
+ return ;
+ })();
+ }
+};
\ No newline at end of file
diff --git a/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/async-function/options.json b/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/async-function/options.json
new file mode 100644
index 0000000000..e85df790bc
--- /dev/null
+++ b/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/async-function/options.json
@@ -0,0 +1,3 @@
+{
+ "plugins": ["transform-async-to-generator", "transform-react-constant-elements", "syntax-jsx"]
+}
diff --git a/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/param-and-var/actual.js b/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/param-and-var/actual.js
new file mode 100644
index 0000000000..f8e03f8eff
--- /dev/null
+++ b/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/param-and-var/actual.js
@@ -0,0 +1,6 @@
+function fn(Component, obj) {
+
+ var data = obj.data;
+
+ return () => ;
+}
diff --git a/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/param-and-var/expected.js b/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/param-and-var/expected.js
new file mode 100644
index 0000000000..8b126b4cb2
--- /dev/null
+++ b/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/param-and-var/expected.js
@@ -0,0 +1,7 @@
+function fn(Component, obj) {
+
+ var data = obj.data,
+ _ref = ;
+
+ return () => _ref;
+}
diff --git a/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/var/actual.js b/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/var/actual.js
new file mode 100644
index 0000000000..da277f18bd
--- /dev/null
+++ b/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/var/actual.js
@@ -0,0 +1,6 @@
+function fn(Component) {
+
+ var data = "prop";
+
+ return () => ;
+}
diff --git a/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/var/expected.js b/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/var/expected.js
new file mode 100644
index 0000000000..a956d1d435
--- /dev/null
+++ b/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/var/expected.js
@@ -0,0 +1,7 @@
+function fn(Component) {
+
+ var data = "prop",
+ _ref = ;
+
+ return () => _ref;
+}
diff --git a/packages/babel-traverse/src/path/lib/hoister.js b/packages/babel-traverse/src/path/lib/hoister.js
index a493687c65..9fc433c1fb 100644
--- a/packages/babel-traverse/src/path/lib/hoister.js
+++ b/packages/babel-traverse/src/path/lib/hoister.js
@@ -99,11 +99,15 @@ export default class PathHoister {
const binding = this.bindings[name];
- // allow parameter references
- if (binding.kind === "param") continue;
+ // allow parameter references and expressions in params (like destructuring rest)
+ if (binding.kind === "param" || binding.path.parentKey === "params") continue;
- // if this binding appears after our attachment point, then we move after it.
- if (this.getAttachmentParentForPath(binding.path).key > path.key) {
+ // For each binding, get its attachment parent. This gives us an idea of where we might
+ // introduce conflicts.
+ const bindingParentPath = this.getAttachmentParentForPath(binding.path);
+
+ // If the binding's attachment appears at or after our attachment point, then we move after it.
+ if (bindingParentPath.key >= path.key) {
this.attachAfter = true;
path = binding.path;