Skip to content

Commit

Permalink
Fix incorrect function hoisting in some case statements (#16363)
Browse files Browse the repository at this point in the history
  • Loading branch information
luiscubal committed Mar 27, 2024
1 parent acf3d17 commit b8eb831
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 19 deletions.
47 changes: 29 additions & 18 deletions packages/babel-core/src/transformation/block-hoist-plugin.ts
Expand Up @@ -23,29 +23,40 @@ const blockHoistPlugin: PluginObject = {
visitor: {
Block: {
exit({ node }) {
const { body } = node;

// Largest SMI
let max = 2 ** 30 - 1;
let hasChange = false;
for (let i = 0; i < body.length; i++) {
const n = body[i];
const p = priority(n);
if (p > max) {
hasChange = true;
break;
}
max = p;
}
if (!hasChange) return;

// My kingdom for a stable sort!
node.body = stableSort(body.slice());
node.body = performHoisting(node.body);
},
},
SwitchCase: {
exit({ node }) {
// In case statements, hoisting is difficult to perform correctly due to
// functions that are declared and referenced in different blocks.
// Nevertheless, hoisting the statements *inside* of each case should at
// least mitigate the failure cases.
node.consequent = performHoisting(node.consequent);
},
},
},
};

function performHoisting(body: Statement[]): Statement[] {
// Largest SMI
let max = 2 ** 30 - 1;
let hasChange = false;
for (let i = 0; i < body.length; i++) {
const n = body[i];
const p = priority(n);
if (p > max) {
hasChange = true;
break;
}
max = p;
}
if (!hasChange) return body;

// My kingdom for a stable sort!
return stableSort(body.slice());
}

export default function loadBlockHoistPlugin(): Plugin {
if (!LOADED_PLUGIN) {
// cache the loaded blockHoist plugin plugin
Expand Down
@@ -0,0 +1,9 @@
{
switch (1) {
case 1:
expect(f()).toBe(1);
function f() {
return 1;
}
}
}
@@ -0,0 +1,3 @@
{
"plugins": ["transform-block-scoped-functions"]
}
@@ -0,0 +1,9 @@
{
switch (1) {
case 1:
let f = function () {
return 1;
};
expect(f()).toBe(1);
}
}
Expand Up @@ -19,6 +19,6 @@ switch (true) {
var _c = 4;
var _d = 5;
case false:
class _e {}
var _f = function () {};
class _e {}
}

0 comments on commit b8eb831

Please sign in to comment.