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

feat(plugin-check-syntax): support infer es2016 to es2018 #1844

Merged
merged 1 commit into from
Mar 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions e2e/cases/check-syntax/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,45 @@ test('should throw error when using optional chaining and target is es6 browsers
).toBeTruthy();
});

test('should throw error when using optional chaining and target is fully supports es6-module', async () => {
const cwd = path.join(__dirname, 'fixtures/esnext');
const { logs, restore } = proxyConsole();

await expect(
build({
cwd,
plugins: [
pluginCheckSyntax({
targets: ['fully supports es6-module'],
}),
],
rsbuildConfig: getCommonBuildConfig(cwd),
}),
).rejects.toThrowError('[Syntax Checker]');

restore();

expect(logs.find((log) => log.includes('ERROR 1'))).toBeTruthy();
expect(
logs.find((log) => log.includes('source:') && log.includes('src/test.js')),
).toBeTruthy();
expect(
logs.find(
(log) =>
log.includes('output:') &&
normalizeToPosixPath(log).includes('/dist/static/js/index'),
),
).toBeTruthy();
expect(
logs.find(
(log) => log.includes('reason:') && log.includes('Unexpected token'),
),
).toBeTruthy();
expect(
logs.find((log) => log.includes('> 3 | console.log(arr, arr?.flat());')),
).toBeTruthy();
});

test('should not throw error when using optional chaining and ecmaVersion is 2020', async () => {
const cwd = path.join(__dirname, 'fixtures/esnext');

Expand Down
18 changes: 11 additions & 7 deletions packages/document/docs/en/plugins/list/plugin-check-syntax.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,9 @@ If a syntax error is detected, you can handle it in the following ways:
- **Type:** `string[]`
- **Default:** `The browserslist configuration of the current project`

`targets` is the target browser range of the project. Its value is a standard browserslist array. If you are not familiar with the usage of browserslist, please refer to ["Browserslist"](/guide/advanced/browser-compatibility).
`targets` is the target browser range, its value is a standard browserslist. Check Syntax plugin will by default read the current project's browserslist configuration, so you usually don't need to manually configure the `targets` option.

Rsbuild will read the value of `targets` and automatically deduce the minimum ECMAScript syntax version that can be used in the build artifacts, such as `ES5` or `ES6`.
Rsbuild will read the value of `targets` and automatically deduce the minimum ECMAScript syntax version that can be used in the build artifacts, such as ES5 or ES2015.

- **Example:**

Expand All @@ -105,30 +105,34 @@ pluginCheckSyntax({
});
```

Rsbuild will deduce that the ECMAScript syntax version that can be used with `chrome >= 53` is `ES6`. When the build artifacts contain `ES2016` or higher syntax, it triggers syntax error prompts.
Rsbuild will deduce that the ECMAScript syntax version that can be used with `chrome >= 53` is ES2015. When the build artifacts contain `ES2016` or higher syntax, it triggers syntax error prompts.

:::tip
Please note that Rsbuild does not support automatic analysis of syntax versions above ES6 based on `targets`. If the syntax version compatible with your build artifacts exceeds ES6, please use `checkSyntax.ecmaVersion` to set it.
If you want to learn more about how to use browserslist, please refer to ["Setting Browser Range"](/guide/advanced/browser-compatibility).
:::

### ecmaVersion

- **Type:** `3 | 5 | 6 | 2015 | 2016 | 2017 | 2018 | 2019 | 2020 | 2021 | 2022 | 'latest'`
- **Default:** `Automatically analyzed based on targets`

`ecmaVersion` represents the minimum ECMAScript syntax version that can be used in the build artifact. The priority of `ecmaVersion` is higher than `targets`.
`ecmaVersion` represents the minimum ECMAScript syntax version that can be used in the build artifact.

:::tip
If `ecmaVersion` is not set, Check Syntax plugin will infer the ECMAScript version based on `targets`. Currently, the supported inference range is `es5` ~ `es2018`.
:::

- **Example:**

For example, if the minimum ECMAScript syntax version that can be used in the build artifacts is `ES2020`, you can add the following configuration:
For example, if the minimum ECMAScript syntax version that can be used in the build artifacts is ES2020, you can add the following configuration:

```ts
pluginCheckSyntax({
ecmaVersion: 2020,
});
```

At this time, the build artifacts can include all syntax supported by `ES2020`, such as optional chaining.
At this time, the build artifacts can include all syntax supported by ES2020, such as optional chaining.

### exclude

Expand Down
18 changes: 11 additions & 7 deletions packages/document/docs/zh/plugins/list/plugin-check-syntax.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,9 @@ export default {
- **类型:** `string[]`
- **默认值:** `当前项目的 browserslist 配置`

`targets` 表示项目的目标浏览器范围,它的值为标准的 browserslist 数组,如果你不了解 browserslist 的用法,请参考 [「设置浏览器范围」](/guide/advanced/browser-compatibility)
`targets` 表示目标浏览器范围,它的值为标准的 browserslist。Check Syntax 插件默认会读取当前项目的 browserslist 配置,通常你不需要手动配置 `targets` 属性

Rsbuild 会读取 `targets` 的值,并自动推导出构建产物中可以使用的最低 ECMAScript 语法版本,比如 `ES5``ES6`
Rsbuild 会读取 `targets` 的值,并自动推导出构建产物中可以使用的最低 ECMAScript 语法版本,比如 ES5 或 ES2015

- **示例:**

Expand All @@ -105,30 +105,34 @@ pluginCheckSyntax({
});
```

Rsbuild 会推导出 `chrome >= 53` 可以使用的 ECMAScript 语法版本为 `ES6`,当构建产物中包含 `es2016` 或更高的语法时,就会触发语法错误提示。
Rsbuild 会推导出 `chrome >= 53` 可以使用的 ECMAScript 语法版本为 ES2015,当构建产物中包含 ES2016 或更高的语法时,就会触发语法错误提示。

:::tip
请留意,Rsbuild 不支持基于 `targets` 来自动分析 ES6 以上的语法版本,如果你的构建产物兼容的语法版本超过 ES6,请通过 `checkSyntax.ecmaVersion` 进行设置
如果你想了解更多 browserslist 的用法,请参考 [「设置浏览器范围」](/guide/advanced/browser-compatibility)
:::

### ecmaVersion

- **类型:** `3 | 5 | 6 | 2015 | 2016 | 2017 | 2018 | 2019 | 2020 | 2021 | 2022 | 'latest'`
- **默认值:** `基于 targets 自动分析`

`ecmaVersion` 表示构建产物中可以使用的最低 ECMAScript 语法版本,`ecmaVersion` 的优先级高于 `targets`。
`ecmaVersion` 表示构建产物中可以使用的最低 ECMAScript 语法版本。

:::tip
在未设置 `ecmaVersion` 的情况下,Check Syntax 插件会基于 `targets` 来推导出对应的 ECMAScript 版本,目前支持的推导范围为 `es5` ~ `es2018`。
:::

- **示例:**

比如,构建产物中可以使用的最低 ECMAScript 语法版本为 `ES2020`,可以添加以下设置:
比如,构建产物中可以使用的最低 ECMAScript 语法版本为 ES2020,可以添加以下设置:

```ts
pluginCheckSyntax({
ecmaVersion: 2020,
});
```

此时,构建产物中可以包含 `ES2020` 支持的所有语法,比如 optional chaining。
此时,构建产物中可以包含 ES2020 支持的所有语法,比如 optional chaining。

### exclude

Expand Down
2 changes: 0 additions & 2 deletions packages/plugin-check-syntax/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,12 @@
"dependencies": {
"@rsbuild/shared": "workspace:*",
"acorn": "^8.10.0",
"caniuse-lite": "^1.0.30001583",
"htmlparser2": "9.1.0",
"source-map": "^0.7.4"
},
"devDependencies": {
"@rsbuild/core": "workspace:*",
"@scripts/test-helper": "workspace:*",
"@types/caniuse-lite": "^1.0.3",
"typescript": "^5.4.2"
},
"peerDependencies": {
Expand Down
11 changes: 8 additions & 3 deletions packages/plugin-check-syntax/src/CheckSyntaxPlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,15 @@ import { parse } from 'acorn';
import {
printErrors,
generateError,
getEcmaVersion,
generateHtmlScripts,
checkIsExcludeSource,
} from './helpers';
import { fse, JS_REGEX, HTML_REGEX } from '@rsbuild/shared';
import {
fse,
JS_REGEX,
HTML_REGEX,
browserslistToESVersion,
} from '@rsbuild/shared';
import type {
ECMASyntaxError,
EcmaVersion,
Expand Down Expand Up @@ -40,7 +44,8 @@ export class CheckSyntaxPlugin {
this.targets = options.targets;
this.exclude = options.exclude;
this.rootPath = options.rootPath;
this.ecmaVersion = options.ecmaVersion || getEcmaVersion(this.targets);
this.ecmaVersion =
options.ecmaVersion || browserslistToESVersion(this.targets);
}

apply(complier: Compiler) {
Expand Down
18 changes: 0 additions & 18 deletions packages/plugin-check-syntax/src/helpers/getEcmaVersion.ts

This file was deleted.

1 change: 0 additions & 1 deletion packages/plugin-check-syntax/src/helpers/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
export * from './generateError';
export * from './printErrors';
export * from './getEcmaVersion';
export * from './generateHtmlScripts';
export * from './utils';
16 changes: 0 additions & 16 deletions packages/plugin-check-syntax/tests/CheckSyntaxPlugin.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { getHtmlScripts } from '../src/helpers/generateHtmlScripts';
import { getEcmaVersion } from '../src/helpers/getEcmaVersion';
import { makeCodeFrame, displayCodePointer } from '../src/helpers';

describe('getHtmlScripts', () => {
Expand Down Expand Up @@ -57,21 +56,6 @@ describe('getHtmlScripts', () => {
});
});

describe('checkIsSupportBrowser', () => {
test('should get ecma version of single browser correctly', async () => {
expect(getEcmaVersion(['ie >= 11'])).toEqual(5);
expect(getEcmaVersion(['Chrome >= 33'])).toEqual(5);
expect(getEcmaVersion(['Edge >= 12'])).toEqual(5);
expect(getEcmaVersion(['Edge >= 15'])).toEqual(6);
expect(getEcmaVersion(['Chrome >= 53'])).toEqual(6);
});

test('should get ecma version of multiple browsers correctly', async () => {
expect(getEcmaVersion(['ie >= 11', 'Chrome >= 53'])).toEqual(5);
expect(getEcmaVersion(['Edge >= 15', 'Chrome >= 53'])).toEqual(6);
});
});

describe('makeCodeFrame', () => {
test('should make code frame correctly', () => {
const lines = [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ exports[`plugin-check-syntax > should add check-syntax plugin properly 1`] = `
{
"plugins": [
CheckSyntaxPlugin {
"ecmaVersion": 6,
"ecmaVersion": 2017,
"errors": [],
"exclude": undefined,
"rootPath": "<ROOT>/packages/plugin-check-syntax/tests",
Expand Down
10 changes: 0 additions & 10 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.