Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor transform-block-scoped-function #16398

Open
wants to merge 11 commits into
base: main
Choose a base branch
from

Conversation

liuxingbaoyu
Copy link
Member

Q                       A
Fixed Issues? Fixes #1, Fixes #2
Patch: Bug Fix?
Major: Breaking Change?
Minor: New Feature?
Tests Added + Pass? Yes
Documentation PR Link
Any Dependency Changes?
License MIT

This was introduced at #16363 and has not been released yet.
Although the behavior in that PR is more robust, _blockHoist is undocumented and we have removed some of its usage in the past.

@liuxingbaoyu liuxingbaoyu added the PR: Internal 🏠 A type of pull request used for our changelog categories label Mar 30, 2024
@babel-bot
Copy link
Collaborator

babel-bot commented Mar 30, 2024

Build successful! You can test your changes in the REPL here: https://babeljs.io/repl/build/56802

@liuxingbaoyu liuxingbaoyu marked this pull request as draft March 30, 2024 19:27
@liuxingbaoyu
Copy link
Member Author

liuxingbaoyu commented Mar 30, 2024

repl

We actually have the same behavior in @babel/plugin-transform-block-scoping.🤔

@liuxingbaoyu
Copy link
Member Author

It seems we can remove transform-block-scoped-functions.

  "transform-block-scoped-functions": {
    "chrome": "41",
    "opera": "28",
    "edge": "12",
    "firefox": "46",
    "safari": "10",
    "node": "4",
    "deno": "1",
    "ie": "11",
    "ios": "10",
    "samsung": "3.4",
    "opera_mobile": "28",
    "electron": "0.21"
  },
  "transform-block-scoping": {
    "chrome": "50",
    "opera": "37",
    "edge": "14",
    "firefox": "53",
    "safari": "11",
    "node": "6",
    "deno": "1",
    "ios": "11",
    "samsung": "5",
    "opera_mobile": "37",
    "electron": "1.1"
  },

@nicolo-ribaudo
Copy link
Member

@liuxingbaoyu Yeah we could consider doing it for Babel 8, if transform-block-scoping covers all its tests.

@@ -5,7 +5,41 @@ import type { NodePath } from "@babel/traverse";
export default declare(api => {
api.assertVersion(REQUIRED_VERSION(7));

function stableSort(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In Babel 8 we can use array.sort, right?

@liuxingbaoyu
Copy link
Member Author

It might be worth preparing a test262 CI for Babel 8. :)
Unfortunately transform-block-scoped-functions only had one test before that PR.
As I understand it, the difference between them is that transform-block-scoped-functions are not skipped in strict mode.
I just did some testing and this seems to make sense.

PS F:\git\babel-test262-runner\engine\node\bin> .\node.exe -v
v0.10.48
F:\git\babel-test262-runner\engine\node\bin\1.js:10
    function f() {
    ^^^^^^^^
SyntaxError: In strict mode code, functions can only be declared at top level or immediately within another function.
    at Module._compile (module.js:439:25)
    at Object.Module._extensions..js (module.js:474:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Function.Module.runMain (module.js:497:10)
    at startup (node.js:119:16)
    at node.js:945:3

https://github.com/compat-table/compat-table/blob/1a1ccdc02b8b2158ab39a6146d8a7308f43c830b/data-es6.js#L14285

console.log(a());
function a() {
  "use strict";
  if (f() !== 1) return false;
  function f() {
    return 1;
  }
  {
    if (f() !== 2) return false;
    function f() {
      return 2;
    }
    if (f() !== 2) return false;
  }
  if (f() !== 1) return false;
  return true;
}

@liuxingbaoyu
Copy link
Member Author

liuxingbaoyu commented Apr 2, 2024

It seems good from the test262 results.

The three new failures are eval related, because transform-block-scoped-function used to transform regardless of whether it was in strict mode or not, but now it only transforms in strict mode.
And strict mode is not passed into the eval transformation.

Another failure is because transform-async-generator-functions is transformed in Program.enter, the previous over-transformation of all functions unexpectedly made it succeed, now we only transform async function or function *, it Failed.
This should be fine in the real world as it just reduces throwing a ReferenceError.

But the current test failing on node 6 is weird and I need to keep investigating.

This seems to be a feature we didn't cover, it happens on node 6 but not node 8.

@liuxingbaoyu
Copy link
Member Author

liuxingbaoyu commented Apr 3, 2024

babel/babel-test262-runner@2973657
Oh, we have passed strict mode, I should look into it.

Update: Just parsing options. :)

@liuxingbaoyu liuxingbaoyu changed the title Avoid new _blockHoist usage Refactor transform-block-scoped-function Apr 5, 2024
@liuxingbaoyu
Copy link
Member Author

switch (0) {
  default:
    function x() {
      return _x.apply(this, arguments);
    }
}
x;
console.log("ok");

This succeeded on local node 6, which means that the CI failure may be caused by other reasons. (possibly older version of Jest)
In this case, it doesn't matter if we skip it on node 6.

@liuxingbaoyu liuxingbaoyu force-pushed the switch-hoist branch 2 times, most recently from 1a6deed to 392da90 Compare April 6, 2024 19:51
@liuxingbaoyu
Copy link
Member Author

liuxingbaoyu commented Apr 7, 2024

This PR is probably not suitable for landing Babel 7, it's complex and risky.
New bugs may be introduced and there may be compatibility issues between the two plugin versions.

For example
repl
The behavior of transform-block-scoped-function was buggy, and we avoided this bug in transform-block-scoping. 😅

@liuxingbaoyu liuxingbaoyu marked this pull request as ready for review April 7, 2024 19:13
Comment on lines +86 to +89
path.setData(
"babel-plugin-transform-async-generator-functions#async_generator_function",
true,
);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

visitor: {
Program(path, state) {
// We need to traverse the ast here (instead of just vising Function
// in the top level visitor) because for-await needs to run before the
// async-to-generator plugin. This is because for-await is transpiled
// using "await" expressions, which are then converted to "yield".
//
// This is bad for performance, but plugin ordering will allow as to
// directly visit Function in the top level visitor.
path.traverse(visitor, state);
},

This is because we converted the async generator function in Program.enter.

@liuxingbaoyu liuxingbaoyu added PR: Polish 💅 A type of pull request used for our changelog categories PR: Polish (next major) 💅 A type of pull request used for our changelog categories for next major release and removed PR: Internal 🏠 A type of pull request used for our changelog categories PR: Polish 💅 A type of pull request used for our changelog categories labels Apr 10, 2024
@liuxingbaoyu
Copy link
Member Author

liuxingbaoyu commented Apr 18, 2024

repl

Maybe it doesn't matter if we land on Babel 7.
Because it's broken in the default plugin order.
(Although I don't understand why there are no new test262 successes🤔)

@liuxingbaoyu liuxingbaoyu added PR: Bug Fix (next major) 🐛 A type of pull request used for our changelog categories for next major release and removed PR: Polish (next major) 💅 A type of pull request used for our changelog categories for next major release labels May 5, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
PR: Bug Fix (next major) 🐛 A type of pull request used for our changelog categories for next major release
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants