babel: Better parser error when using jsx

Was checking https://github.com/babel/babel/pull/11478 and testing out syntax and noticed we don’t error with the normal “use this plugin/preset” like we do for proposals with JSX itself. @nicolo-ribaudo mentioned it’s probably since jsx is implemented as a normal plugin so we didn’t have this.expectPlugin("recordAndTuple");

unknown: Unterminated regular expression (1:5)

> 1 | <a></a>
    |      ^
unknown: Support for the experimental syntax 'pipelineOperator' isn't currently enabled (1:3):

> 1 | a |> b
    |   ^

Add @babel/plugin-proposal-pipeline-operator (https://git.io/vb4SU) to the 'plugins' section of your Babel config to enable transformation.

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Comments: 15 (13 by maintainers)

Commits related to this issue

Most upvoted comments

This bug needs different steps in order to be fixed, but they can be done in the same PR.

  1. First, we should make @babel/parser throw a developer-friendly error. Consider these examples:

    require("@babel/parser").parse("<div></div>", {});
    require("@babel/parser").parse("a |> b", {});
    

    The first one throws SyntaxError: Unexpected token (1:0), while the second one throws a more actionable SyntaxError: This experimental syntax requires enabling the parser plugin: 'pipelineOperator' (1:2). Why this difference? If you search for the "pipelineOperator" string in packages/babel-parser/src, you’ll see that (as @hzoo mentioned above) we are calling the this.expectPlugin("pipelineOperator") function when we find the “pipeline” (|>) operator.

    We can do something similar for JSX, but it’s harder. The main problem is that checks for ECMAScript proposals (such as |>) are inlined in the parser code, while checks for JSX code are only enabled when the jsx plugin is enabled.

    However, we know that JSX elements are _atomic expressions (parsed by the parseExprAtom method) and that no other expression can start with <. That method contains a big switch statement, and (at the end) we throw this.unexpected() if we don’t find any valid token. We could add a new case and, if the token is <, call this.expectPlugin("jsx").

    Here are a few possible tests:

    • When the jsx plugin is not enabled, this code should throw the “nice” error:
      <div /></div>
      
    • This is valid JS code, and it should never throw:
      "use strict"
      <div
      
    • When the typescript plugin is enabled, this code shouldn’t throw because it’s a type parameter:
      <div>() => {}
      
  2. Then, we should make @babel/core handle the parser error and suggest the correct @babel/... plugin/preset. You can add the syntax plugin and the react preset at packages/babel-core/src/parser/util/missing-plugin-helper.js.


If it is the first time that you contribute to Babel, follow these steps: (you need to have make and yarn available on your machine)

  1. Write a comment there to let other possible contributors know that you are working on this bug.
  2. Fork the repo
  3. Run git clone https://github.com/<YOUR_USERNAME>/babel.git && cd babel
  4. Run yarn && make bootstrap
  5. Wait ⏳
  6. Run make watch (or make build whenever you change a file)
  7. Add some tests: packages/babel-parser/test/fixtures/jsx/errors/_no-plugin, packages/babel-parser/test/fixtures/jsx/errors/_no-plugin-no-jsx and packages/babel-parser/test/fixtures/jsx/errors/_no-plugin-ts-type-param. You can see an example at packages/babel-parser/test/fixtures/experimental/_no-plugin/import-meta.
  8. Update the code!
  9. yarn jest babel-parser to run the tests
    • If some test outputs don’t match but the new results are correct, you can delete the bad output.js files and run the tests again
    • If you prefer, you can run OVERWRITE=true yarn jest babel-parser and they will be automatically updated.
  10. If it is working, run make test to run all the tests
  11. Run git push and open a PR!

@karansapolia it’s yours! let us know (here or on slack) if you have any questions!

Awesome! Please feel free to reach out if you have any questions.

i want to try this.