Compare commits
266 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
269325c04f | ||
|
|
829e8918a6 | ||
|
|
5644e81f27 | ||
|
|
208905257f | ||
|
|
891a6332e3 | ||
|
|
a4842c92ea | ||
|
|
ada8bbbd6a | ||
|
|
e9c3b27b4b | ||
|
|
b0446ff06a | ||
|
|
db7dfe0550 | ||
|
|
646835fb59 | ||
|
|
c2a1961747 | ||
|
|
6584a6eec4 | ||
|
|
86d5ac0882 | ||
|
|
476f53879e | ||
|
|
c69a5fc53a | ||
|
|
a35aaf704c | ||
|
|
3c3696d554 | ||
|
|
90b511ec7a | ||
|
|
02372952e4 | ||
|
|
9fde224a53 | ||
|
|
ca02c4bb40 | ||
|
|
c37d89827e | ||
|
|
6c6699f3d2 | ||
|
|
9320a0139d | ||
|
|
fbcda19a23 | ||
|
|
cd28a946d5 | ||
|
|
8243f3f063 | ||
|
|
df31952275 | ||
|
|
1a191701fe | ||
|
|
99563e9173 | ||
|
|
17d274dc12 | ||
|
|
6b5d9fd316 | ||
|
|
2c560374d6 | ||
|
|
2e385738a4 | ||
|
|
c4a3b92e09 | ||
|
|
6daef4e7c8 | ||
|
|
3e956805e8 | ||
|
|
1b6e3dd985 | ||
|
|
5398b71158 | ||
|
|
f3c956006a | ||
|
|
4eba294c69 | ||
|
|
5200721e5c | ||
|
|
e9d80d939e | ||
|
|
ef1103d3e9 | ||
|
|
67338703aa | ||
|
|
7939d92fcc | ||
|
|
d92e5713be | ||
|
|
93b61fc4ec | ||
|
|
77987e5ee3 | ||
|
|
0df46f01a9 | ||
|
|
f457d0b4c6 | ||
|
|
1c79cb82ab | ||
|
|
89a46a57df | ||
|
|
eb53139ee5 | ||
|
|
38a7600920 | ||
|
|
ed1264f077 | ||
|
|
ef06b54f8d | ||
|
|
1b77c3d7b9 | ||
|
|
5ccfcd17ff | ||
|
|
a8ab2bcb62 | ||
|
|
8646349aeb | ||
|
|
f31779a112 | ||
|
|
0e2402eb20 | ||
|
|
f695f95290 | ||
|
|
5de83dcc0f | ||
|
|
5135f98795 | ||
|
|
26bca0005c | ||
|
|
e0e98d9560 | ||
|
|
4ab827b869 | ||
|
|
3456b6634a | ||
|
|
75c979847f | ||
|
|
6aa8254bb7 | ||
|
|
ca8f91f6f6 | ||
|
|
2398554c60 | ||
|
|
0ca3deebcf | ||
|
|
99e1024051 | ||
|
|
696950aa69 | ||
|
|
a8c2bbdabf | ||
|
|
50ab2dde94 | ||
|
|
d331ba0411 | ||
|
|
00aa0043c7 | ||
|
|
cc680065c3 | ||
|
|
f9d78089c6 | ||
|
|
562f17efab | ||
|
|
9e9b54d7f6 | ||
|
|
029e8bd618 | ||
|
|
e81fcfe3f2 | ||
|
|
aac177c484 | ||
|
|
6b1ae49571 | ||
|
|
e03ac20f94 | ||
|
|
e9252bcdcc | ||
|
|
e0fe347967 | ||
|
|
d48c69246c | ||
|
|
443b7ff2a8 | ||
|
|
d4e24b349e | ||
|
|
bdce84a539 | ||
|
|
a1f157e9a9 | ||
|
|
605a880c8c | ||
|
|
2980f27779 | ||
|
|
eda36a1c75 | ||
|
|
ca12911d1f | ||
|
|
d55cc79bcf | ||
|
|
11ca4f6b69 | ||
|
|
56c7d1070a | ||
|
|
7e2ea902f8 | ||
|
|
3607f4838a | ||
|
|
5eb20b3007 | ||
|
|
4c9392b43e | ||
|
|
227e8414cc | ||
|
|
2df9622477 | ||
|
|
ebc22ef7e1 | ||
|
|
92e65ca68f | ||
|
|
403d4fb852 | ||
|
|
2e4db3344f | ||
|
|
d42a90cf4f | ||
|
|
58def9f2e6 | ||
|
|
dd9974bbb8 | ||
|
|
22e39ea72e | ||
|
|
2567726503 | ||
|
|
9dd378ff12 | ||
|
|
ad03c48a71 | ||
|
|
9b042f9d59 | ||
|
|
27ba5e8b1f | ||
|
|
662957cc73 | ||
|
|
88479c6fc3 | ||
|
|
70f1d766e8 | ||
|
|
885532c124 | ||
|
|
5f31228d7d | ||
|
|
fcb4e0f137 | ||
|
|
a84862dbdc | ||
|
|
86b1913474 | ||
|
|
a9575dcf62 | ||
|
|
19cc5af41e | ||
|
|
498514c04d | ||
|
|
a92acdb188 | ||
|
|
d99f8bba2e | ||
|
|
8a7b487e3b | ||
|
|
4632e36a4e | ||
|
|
eb1f77dedf | ||
|
|
be91130f18 | ||
|
|
5adf40208f | ||
|
|
037b25cfdc | ||
|
|
0d9834caeb | ||
|
|
e670e72fa0 | ||
|
|
a53da6abe1 | ||
|
|
32b0cad8f7 | ||
|
|
ed8b68dd17 | ||
|
|
c6a7e18636 | ||
|
|
cbbe8666a8 | ||
|
|
e0131f1eda | ||
|
|
5a78dd7cfe | ||
|
|
d814852baf | ||
|
|
f83903bfcc | ||
|
|
192555bb0e | ||
|
|
a69b80d07e | ||
|
|
2c5fd26c07 | ||
|
|
0461c0d8a4 | ||
|
|
899e3d1297 | ||
|
|
0a7dc1b1c7 | ||
|
|
cd90a4d8c0 | ||
|
|
3dd2c62770 | ||
|
|
93b58361d9 | ||
|
|
594ea533d3 | ||
|
|
062fb31155 | ||
|
|
7588b6b291 | ||
|
|
569c3b28ee | ||
|
|
bc78de3a52 | ||
|
|
989b0cccc2 | ||
|
|
76e44c2911 | ||
|
|
8759c5c8d6 | ||
|
|
44c3d3d665 | ||
|
|
ae3190c5e9 | ||
|
|
a0fdb63060 | ||
|
|
b48e739998 | ||
|
|
ff6283340a | ||
|
|
d85cf3e5ab | ||
|
|
32b411496b | ||
|
|
0605cd9f38 | ||
|
|
8bda71558c | ||
|
|
f82c662b8d | ||
|
|
0a82580bfc | ||
|
|
442150e0e2 | ||
|
|
10a4c88f58 | ||
|
|
a4b2d0d518 | ||
|
|
1f0b03ced0 | ||
|
|
152bfe3769 | ||
|
|
19ca800caa | ||
|
|
a657bc5dee | ||
|
|
9ff42a8798 | ||
|
|
87c03a0a13 | ||
|
|
221f3002ca | ||
|
|
55b54b0d63 | ||
|
|
4b3728f05e | ||
|
|
f02ba2fcc5 | ||
|
|
14f7c07271 | ||
|
|
2fe5b572bc | ||
|
|
bb9a24d9fc | ||
|
|
b2357ecd82 | ||
|
|
c492f97541 | ||
|
|
37906d4dfb | ||
|
|
d676c047b1 | ||
|
|
ddc26c9db1 | ||
|
|
dc44bca85b | ||
|
|
9eabb37338 | ||
|
|
a6ce56d9a9 | ||
|
|
5269823927 | ||
|
|
0f8a1e02ff | ||
|
|
b65afdd0c1 | ||
|
|
de1eaa2655 | ||
|
|
ae9017ceab | ||
|
|
a0b91fbd65 | ||
|
|
b83090fca2 | ||
|
|
deba48a727 | ||
|
|
b6b33bfb92 | ||
|
|
7c864c9834 | ||
|
|
19557443c8 | ||
|
|
e5a2062c80 | ||
|
|
9b62ee71f4 | ||
|
|
5f05181a8b | ||
|
|
b000019578 | ||
|
|
028c8e6cf5 | ||
|
|
18eaf51bd5 | ||
|
|
829401dc17 | ||
|
|
fd2d279984 | ||
|
|
b25bcd460f | ||
|
|
77656c557a | ||
|
|
7f3826e8e4 | ||
|
|
313c8c55de | ||
|
|
d46b04a27d | ||
|
|
5f38ef6719 | ||
|
|
61e713c1d3 | ||
|
|
1185f88d35 | ||
|
|
91add7bbdc | ||
|
|
5a274a37e0 | ||
|
|
60c797e744 | ||
|
|
af4987e19f | ||
|
|
35dcf02b04 | ||
|
|
e5fdd994bf | ||
|
|
4749dcb7c5 | ||
|
|
5b51a2b9e2 | ||
|
|
6093f1862a | ||
|
|
89dbd487fc | ||
|
|
87276ef1ef | ||
|
|
f13abbbb44 | ||
|
|
43d18bc2d3 | ||
|
|
b158439a5b | ||
|
|
059760548f | ||
|
|
886c5ad936 | ||
|
|
f0edf41e3e | ||
|
|
f9f17f6c8d | ||
|
|
453f505256 | ||
|
|
b3a95caf61 | ||
|
|
6099351c76 | ||
|
|
af8532f251 | ||
|
|
cabd8a0e70 | ||
|
|
540efebcc3 | ||
|
|
0bf1f39ec6 | ||
|
|
056073de4c | ||
|
|
d2a1b8854d | ||
|
|
f2813ee33d | ||
|
|
d634548243 | ||
|
|
54cfa95d3a | ||
|
|
d5f3c50f58 | ||
|
|
79dcc47191 | ||
|
|
d16fe4be5b |
36
.eslintrc.js
36
.eslintrc.js
@@ -336,11 +336,11 @@ module.exports = {
|
||||
'packages/react-devtools-extensions/**/*.js',
|
||||
'packages/react-devtools-timeline/**/*.js',
|
||||
'packages/react-native-renderer/**/*.js',
|
||||
'packages/eslint-plugin-react-hooks/**/*.js',
|
||||
'packages/jest-react/**/*.js',
|
||||
'packages/internal-test-utils/**/*.js',
|
||||
'packages/**/__tests__/*.js',
|
||||
'packages/**/npm/*.js',
|
||||
'compiler/packages/eslint-plugin-react-hooks/**/*.js',
|
||||
],
|
||||
rules: {
|
||||
'react-internal/prod-error-codes': OFF,
|
||||
@@ -446,10 +446,7 @@ module.exports = {
|
||||
},
|
||||
},
|
||||
{
|
||||
files: [
|
||||
'scripts/eslint-rules/*.js',
|
||||
'packages/eslint-plugin-react-hooks/src/*.js',
|
||||
],
|
||||
files: ['scripts/eslint-rules/*.js'],
|
||||
plugins: ['eslint-plugin'],
|
||||
rules: {
|
||||
'eslint-plugin/prefer-object-rule': ERROR,
|
||||
@@ -496,9 +493,11 @@ module.exports = {
|
||||
{
|
||||
files: [
|
||||
'packages/react-devtools-extensions/**/*.js',
|
||||
'packages/react-devtools-shared/src/devtools/views/**/*.js',
|
||||
'packages/react-devtools-shared/src/hook.js',
|
||||
'packages/react-devtools-shared/src/backend/console.js',
|
||||
'packages/react-devtools-shared/src/backend/shared/DevToolsComponentStackFrame.js',
|
||||
'packages/react-devtools-shared/src/frontend/utils/withPermissionsCheck.js',
|
||||
],
|
||||
globals: {
|
||||
__IS_CHROME__: 'readonly',
|
||||
@@ -506,6 +505,7 @@ module.exports = {
|
||||
__IS_EDGE__: 'readonly',
|
||||
__IS_NATIVE__: 'readonly',
|
||||
__IS_INTERNAL_VERSION__: 'readonly',
|
||||
chrome: 'readonly',
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -514,6 +514,26 @@ module.exports = {
|
||||
__IS_INTERNAL_VERSION__: 'readonly',
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['compiler/packages/eslint-plugin-react-hooks/src/**/*'],
|
||||
extends: ['plugin:@typescript-eslint/recommended'],
|
||||
parser: '@typescript-eslint/parser',
|
||||
plugins: ['@typescript-eslint', 'eslint-plugin'],
|
||||
rules: {
|
||||
'@typescript-eslint/no-explicit-any': OFF,
|
||||
'@typescript-eslint/no-non-null-assertion': OFF,
|
||||
'@typescript-eslint/array-type': [ERROR, {default: 'generic'}],
|
||||
|
||||
'es/no-optional-chaining': OFF,
|
||||
|
||||
'eslint-plugin/prefer-object-rule': ERROR,
|
||||
'eslint-plugin/require-meta-fixable': [
|
||||
ERROR,
|
||||
{catchNoFixerButFixableProperty: true},
|
||||
],
|
||||
'eslint-plugin/require-meta-has-suggestions': ERROR,
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
env: {
|
||||
@@ -589,6 +609,12 @@ module.exports = {
|
||||
WheelEventHandler: 'readonly',
|
||||
FinalizationRegistry: 'readonly',
|
||||
Omit: 'readonly',
|
||||
Keyframe: 'readonly',
|
||||
PropertyIndexedKeyframes: 'readonly',
|
||||
KeyframeAnimationOptions: 'readonly',
|
||||
GetAnimationsOptions: 'readonly',
|
||||
Animatable: 'readonly',
|
||||
ScrollTimeline: 'readonly',
|
||||
|
||||
spyOnDev: 'readonly',
|
||||
spyOnDevAndProd: 'readonly',
|
||||
|
||||
30
.github/workflows/compiler_discord_notify.yml
vendored
Normal file
30
.github/workflows/compiler_discord_notify.yml
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
name: (Compiler) Discord Notify
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types: [opened, ready_for_review]
|
||||
paths:
|
||||
- compiler/**
|
||||
- .github/workflows/compiler_**.yml
|
||||
|
||||
jobs:
|
||||
check_maintainer:
|
||||
uses: facebook/react/.github/workflows/shared_check_maintainer.yml@main
|
||||
with:
|
||||
actor: ${{ github.event.pull_request.user.login }}
|
||||
|
||||
notify:
|
||||
if: ${{ needs.check_maintainer.outputs.is_core_team == 'true' }}
|
||||
needs: check_maintainer
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Discord Webhook Action
|
||||
uses: tsickert/discord-webhook@86dc739f3f165f16dadc5666051c367efa1692f4
|
||||
with:
|
||||
webhook-url: ${{ secrets.COMPILER_DISCORD_WEBHOOK_URL }}
|
||||
embed-author-name: ${{ github.event.pull_request.user.login }}
|
||||
embed-author-url: ${{ github.event.pull_request.user.html_url }}
|
||||
embed-author-icon-url: ${{ github.event.pull_request.user.avatar_url }}
|
||||
embed-title: '#${{ github.event.number }} (+${{github.event.pull_request.additions}} -${{github.event.pull_request.deletions}}): ${{ github.event.pull_request.title }}'
|
||||
embed-description: ${{ github.event.pull_request.body }}
|
||||
embed-url: ${{ github.event.pull_request.html_url }}
|
||||
5
.github/workflows/compiler_playground.yml
vendored
5
.github/workflows/compiler_playground.yml
vendored
@@ -36,8 +36,9 @@ jobs:
|
||||
uses: actions/cache@v4
|
||||
id: node_modules
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: compiler-node_modules-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('compiler/**/yarn.lock') }}
|
||||
path: |
|
||||
**/node_modules
|
||||
key: compiler-node_modules-v6-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('compiler/**/yarn.lock') }}
|
||||
- run: yarn install --frozen-lockfile
|
||||
- run: npx playwright install --with-deps chromium
|
||||
- run: CI=true yarn test
|
||||
|
||||
5
.github/workflows/compiler_prereleases.yml
vendored
5
.github/workflows/compiler_prereleases.yml
vendored
@@ -46,8 +46,9 @@ jobs:
|
||||
uses: actions/cache@v4
|
||||
id: node_modules
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: compiler-node_modules-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('compiler/**/yarn.lock') }}
|
||||
path: |
|
||||
**/node_modules
|
||||
key: compiler-node_modules-v6-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('compiler/**/yarn.lock') }}
|
||||
- run: yarn install --frozen-lockfile
|
||||
- name: Publish packages to npm
|
||||
run: |
|
||||
|
||||
77
.github/workflows/compiler_rust.yml
vendored
77
.github/workflows/compiler_rust.yml
vendored
@@ -1,77 +0,0 @@
|
||||
name: (Compiler) Rust
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: ["main"]
|
||||
paths:
|
||||
- .github/workflows/**
|
||||
- compiler/crates/**
|
||||
- compiler/Cargo.*
|
||||
- compiler/*.toml
|
||||
pull_request:
|
||||
paths:
|
||||
- .github/workflows/**
|
||||
- compiler/crates/**
|
||||
- compiler/Cargo.*
|
||||
- compiler/*.toml
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref_name }}-${{ github.event.pull_request.number || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
RUSTFLAGS: -Dwarnings
|
||||
TZ: /usr/share/zoneinfo/America/Los_Angeles
|
||||
|
||||
defaults:
|
||||
run:
|
||||
working-directory: compiler
|
||||
|
||||
jobs:
|
||||
test:
|
||||
name: Rust Test (${{ matrix.target.os }})
|
||||
strategy:
|
||||
matrix:
|
||||
target:
|
||||
- target: ubuntu-latest
|
||||
os: ubuntu-latest
|
||||
# TODO: run on more platforms
|
||||
# - target: macos-latest
|
||||
# os: macos-latest
|
||||
# - target: windows-latest
|
||||
# os: windows-latest
|
||||
runs-on: ${{ matrix.target.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
- name: cargo test
|
||||
run: cargo test --manifest-path=Cargo.toml --locked ${{ matrix.target.features && '--features' }} ${{ matrix.target.features }}
|
||||
|
||||
lint:
|
||||
name: Rust Lint
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
# NOTE: use `rustup run <toolchain> <command>` in commands below
|
||||
# with this exact same toolchain value
|
||||
toolchain: nightly-2023-08-01
|
||||
override: true
|
||||
components: rustfmt, clippy
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
- name: rustfmt
|
||||
run: grep -r --include "*.rs" --files-without-match "@generated" crates | xargs rustup run nightly-2023-08-01 rustfmt --check --config="skip_children=true"
|
||||
# - name: cargo clippy
|
||||
# run: rustup run nightly-2023-08-01 cargo clippy -- -Dclippy::correctness
|
||||
|
||||
build:
|
||||
name: Rust Build
|
||||
runs-on: ubuntu-latest
|
||||
# TODO: build on more platforms, deploy, etc
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
- name: cargo build
|
||||
run: cargo build --release
|
||||
20
.github/workflows/compiler_typescript.yml
vendored
20
.github/workflows/compiler_typescript.yml
vendored
@@ -46,8 +46,9 @@ jobs:
|
||||
- name: Restore cached node_modules
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: compiler-node_modules-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('compiler/**/yarn.lock') }}
|
||||
path: |
|
||||
**/node_modules
|
||||
key: compiler-node_modules-v6-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('compiler/**/yarn.lock') }}
|
||||
- run: yarn install --frozen-lockfile
|
||||
- run: yarn workspace babel-plugin-react-compiler lint
|
||||
|
||||
@@ -66,8 +67,9 @@ jobs:
|
||||
uses: actions/cache@v4
|
||||
id: node_modules
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: compiler-node_modules-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('compiler/**/yarn.lock') }}
|
||||
path: |
|
||||
**/node_modules
|
||||
key: compiler-node_modules-v6-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('compiler/**/yarn.lock') }}
|
||||
- run: yarn install --frozen-lockfile
|
||||
- run: yarn workspace babel-plugin-react-compiler jest
|
||||
|
||||
@@ -75,8 +77,8 @@ jobs:
|
||||
name: Test ${{ matrix.workspace_name }}
|
||||
needs: discover_yarn_workspaces
|
||||
runs-on: ubuntu-latest
|
||||
continue-on-error: true
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
workspace_name: ${{ fromJSON(needs.discover_yarn_workspaces.outputs.matrix) }}
|
||||
steps:
|
||||
@@ -90,7 +92,11 @@ jobs:
|
||||
uses: actions/cache@v4
|
||||
id: node_modules
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: compiler-node_modules-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('compiler/**/yarn.lock') }}
|
||||
path: |
|
||||
**/node_modules
|
||||
key: compiler-node_modules-v6-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('compiler/**/yarn.lock') }}
|
||||
- run: yarn install --frozen-lockfile
|
||||
- run: xvfb-run -a yarn workspace ${{ matrix.workspace_name }} test
|
||||
if: runner.os == 'Linux' && matrix.workspace_name == 'react-forgive'
|
||||
- run: yarn workspace ${{ matrix.workspace_name }} test
|
||||
if: matrix.workspace_name != 'react-forgive'
|
||||
|
||||
27
.github/workflows/devtools_regression_tests.yml
vendored
27
.github/workflows/devtools_regression_tests.yml
vendored
@@ -29,13 +29,13 @@ jobs:
|
||||
uses: actions/cache@v4
|
||||
id: node_modules
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: runtime-release-node_modules-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock', 'scripts/release/yarn.lock') }}
|
||||
path: |
|
||||
**/node_modules
|
||||
key: runtime-release-node_modules-v6-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock', 'scripts/release/yarn.lock') }}
|
||||
- name: Ensure clean build directory
|
||||
run: rm -rf build
|
||||
- run: yarn install --frozen-lockfile
|
||||
- run: yarn install --frozen-lockfile
|
||||
working-directory: scripts/release
|
||||
- run: yarn --cwd scripts/release install --frozen-lockfile
|
||||
- name: Download react-devtools artifacts for base revision
|
||||
run: |
|
||||
git fetch origin main
|
||||
@@ -63,8 +63,9 @@ jobs:
|
||||
uses: actions/cache@v4
|
||||
id: node_modules
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: runtime-node_modules-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
|
||||
path: |
|
||||
**/node_modules
|
||||
key: runtime-node_modules-v6-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
|
||||
- name: Ensure clean build directory
|
||||
run: rm -rf build
|
||||
- run: yarn install --frozen-lockfile
|
||||
@@ -100,6 +101,7 @@ jobs:
|
||||
needs: build_devtools_and_process_artifacts
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
version:
|
||||
- "16.0"
|
||||
@@ -108,7 +110,6 @@ jobs:
|
||||
- "17.0"
|
||||
- "18.0"
|
||||
- "18.2" # compiler polyfill
|
||||
continue-on-error: true
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
@@ -120,8 +121,9 @@ jobs:
|
||||
uses: actions/cache@v4
|
||||
id: node_modules
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: runtime-node_modules-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
|
||||
path: |
|
||||
**/node_modules
|
||||
key: runtime-node_modules-v6-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
|
||||
- run: yarn install --frozen-lockfile
|
||||
- name: Restore all archived build artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
@@ -135,6 +137,7 @@ jobs:
|
||||
needs: build_devtools_and_process_artifacts
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
version:
|
||||
- "16.0"
|
||||
@@ -142,7 +145,6 @@ jobs:
|
||||
- "16.8" # hooks
|
||||
- "17.0"
|
||||
- "18.0"
|
||||
continue-on-error: true
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
@@ -154,8 +156,9 @@ jobs:
|
||||
uses: actions/cache@v4
|
||||
id: node_modules
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: runtime-node_modules-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
|
||||
path: |
|
||||
**/node_modules
|
||||
key: runtime-node_modules-v6-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
|
||||
- run: yarn install --frozen-lockfile
|
||||
- name: Restore all archived build artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
|
||||
322
.github/workflows/runtime_build_and_test.yml
vendored
322
.github/workflows/runtime_build_and_test.yml
vendored
@@ -17,6 +17,75 @@ env:
|
||||
SEGMENT_DOWNLOAD_TIMEOUT_MINS: 1
|
||||
|
||||
jobs:
|
||||
# ----- NODE_MODULES CACHE -----
|
||||
# Centralize the node_modules cache so it is saved once and each subsequent job only needs to
|
||||
# restore the cache. Prevents race conditions where multiple workflows try to write to the cache.
|
||||
runtime_node_modules_cache:
|
||||
name: Cache Runtime node_modules
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha || github.sha }}
|
||||
- name: Check cache hit
|
||||
uses: actions/cache/restore@v4
|
||||
id: node_modules
|
||||
with:
|
||||
path: |
|
||||
**/node_modules
|
||||
key: runtime-node_modules-v6-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
|
||||
lookup-only: true
|
||||
- uses: actions/setup-node@v4
|
||||
if: steps.node_modules.outputs.cache-hit != 'true'
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
cache: yarn
|
||||
cache-dependency-path: yarn.lock
|
||||
- run: yarn install --frozen-lockfile
|
||||
if: steps.node_modules.outputs.cache-hit != 'true'
|
||||
- name: Save cache
|
||||
if: steps.node_modules.outputs.cache-hit != 'true'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: |
|
||||
**/node_modules
|
||||
key: runtime-node_modules-v6-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
|
||||
|
||||
runtime_compiler_node_modules_cache:
|
||||
name: Cache Runtime, Compiler node_modules
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha || github.sha }}
|
||||
- name: Check cache hit
|
||||
uses: actions/cache/restore@v4
|
||||
id: node_modules
|
||||
with:
|
||||
path: |
|
||||
**/node_modules
|
||||
key: runtime-and-compiler-node_modules-v6-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock', 'compiler/yarn.lock') }}
|
||||
lookup-only: true
|
||||
- uses: actions/setup-node@v4
|
||||
if: steps.node_modules.outputs.cache-hit != 'true'
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
cache: yarn
|
||||
cache-dependency-path: |
|
||||
yarn.lock
|
||||
compiler/yarn.lock
|
||||
- run: yarn install --frozen-lockfile
|
||||
if: steps.node_modules.outputs.cache-hit != 'true'
|
||||
- run: yarn --cwd compiler install --frozen-lockfile
|
||||
if: steps.node_modules.outputs.cache-hit != 'true'
|
||||
- name: Save cache
|
||||
if: steps.node_modules.outputs.cache-hit != 'true'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: |
|
||||
**/node_modules
|
||||
key: runtime-and-compiler-node_modules-v6-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock', 'compiler/yarn.lock') }}
|
||||
|
||||
# ----- FLOW -----
|
||||
discover_flow_inline_configs:
|
||||
name: Discover flow inline configs
|
||||
@@ -36,10 +105,10 @@ jobs:
|
||||
|
||||
flow:
|
||||
name: Flow check ${{ matrix.flow_inline_config_shortname }}
|
||||
needs: discover_flow_inline_configs
|
||||
needs: [discover_flow_inline_configs, runtime_node_modules_cache]
|
||||
runs-on: ubuntu-latest
|
||||
continue-on-error: true
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
flow_inline_config_shortname: ${{ fromJSON(needs.discover_flow_inline_configs.outputs.matrix) }}
|
||||
steps:
|
||||
@@ -52,19 +121,22 @@ jobs:
|
||||
cache: yarn
|
||||
cache-dependency-path: yarn.lock
|
||||
- name: Restore cached node_modules
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache/restore@v4
|
||||
id: node_modules
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: runtime-node_modules-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
|
||||
path: |
|
||||
**/node_modules
|
||||
key: runtime-node_modules-v6-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
|
||||
- name: Ensure clean build directory
|
||||
run: rm -rf build
|
||||
- run: yarn install --frozen-lockfile
|
||||
if: steps.node_modules.outputs.cache-hit != 'true'
|
||||
- run: node ./scripts/tasks/flow-ci ${{ matrix.flow_inline_config_shortname }}
|
||||
|
||||
# ----- FIZZ -----
|
||||
check_generated_fizz_runtime:
|
||||
name: Confirm generated inline Fizz runtime is up to date
|
||||
needs: [runtime_node_modules_cache]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
@@ -76,14 +148,16 @@ jobs:
|
||||
cache: yarn
|
||||
cache-dependency-path: yarn.lock
|
||||
- name: Restore cached node_modules
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache/restore@v4
|
||||
id: node_modules
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: runtime-node_modules-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
|
||||
path: |
|
||||
**/node_modules
|
||||
key: runtime-node_modules-v6-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
|
||||
- name: Ensure clean build directory
|
||||
run: rm -rf build
|
||||
- run: yarn install --frozen-lockfile
|
||||
if: steps.node_modules.outputs.cache-hit != 'true'
|
||||
- run: |
|
||||
yarn generate-inline-fizz-runtime
|
||||
git diff --quiet || (echo "There was a change to the Fizz runtime. Run `yarn generate-inline-fizz-runtime` and check in the result." && false)
|
||||
@@ -91,6 +165,7 @@ jobs:
|
||||
# ----- FEATURE FLAGS -----
|
||||
flags:
|
||||
name: Check flags
|
||||
needs: [runtime_node_modules_cache]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
@@ -102,21 +177,25 @@ jobs:
|
||||
cache: yarn
|
||||
cache-dependency-path: yarn.lock
|
||||
- name: Restore cached node_modules
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache/restore@v4
|
||||
id: node_modules
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: runtime-node_modules-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
|
||||
path: |
|
||||
**/node_modules
|
||||
key: runtime-node_modules-v6-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
|
||||
- name: Ensure clean build directory
|
||||
run: rm -rf build
|
||||
- run: yarn install --frozen-lockfile
|
||||
if: steps.node_modules.outputs.cache-hit != 'true'
|
||||
- run: yarn flags
|
||||
|
||||
# ----- TESTS -----
|
||||
test:
|
||||
name: yarn test ${{ matrix.params }} (Shard ${{ matrix.shard }})
|
||||
needs: [runtime_compiler_node_modules_cache]
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
params:
|
||||
- "-r=stable --env=development"
|
||||
@@ -144,7 +223,6 @@ jobs:
|
||||
- 3/5
|
||||
- 4/5
|
||||
- 5/5
|
||||
continue-on-error: true
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
@@ -153,26 +231,34 @@ jobs:
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
cache: yarn
|
||||
cache-dependency-path: yarn.lock
|
||||
cache-dependency-path: |
|
||||
yarn.lock
|
||||
compiler/yarn.lock
|
||||
- name: Restore cached node_modules
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache/restore@v4
|
||||
id: node_modules
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: runtime-node_modules-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
|
||||
path: |
|
||||
**/node_modules
|
||||
key: runtime-and-compiler-node_modules-v6-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock', 'compiler/yarn.lock') }}
|
||||
- name: Ensure clean build directory
|
||||
run: rm -rf build
|
||||
- run: yarn install --frozen-lockfile
|
||||
if: steps.node_modules.outputs.cache-hit != 'true'
|
||||
- run: yarn --cwd compiler install --frozen-lockfile
|
||||
if: steps.node_modules.outputs.cache-hit != 'true'
|
||||
- run: yarn test ${{ matrix.params }} --ci --shard=${{ matrix.shard }}
|
||||
|
||||
# ----- BUILD -----
|
||||
build_and_lint:
|
||||
name: yarn build and lint
|
||||
needs: [runtime_compiler_node_modules_cache]
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
# yml is dumb. update the --total arg to yarn build if you change the number of workers
|
||||
worker_id: [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19]
|
||||
worker_id: [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24]
|
||||
release_channel: [stable, experimental]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
@@ -182,21 +268,27 @@ jobs:
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
cache: yarn
|
||||
cache-dependency-path: yarn.lock
|
||||
cache-dependency-path: |
|
||||
yarn.lock
|
||||
compiler/yarn.lock
|
||||
- uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: 11.0.22
|
||||
- name: Restore cached node_modules
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache/restore@v4
|
||||
id: node_modules
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: runtime-node_modules-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
|
||||
path: |
|
||||
**/node_modules
|
||||
key: runtime-and-compiler-node_modules-v6-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock', 'compiler/yarn.lock') }}
|
||||
- name: Ensure clean build directory
|
||||
run: rm -rf build
|
||||
- run: yarn install --frozen-lockfile
|
||||
- run: yarn build --index=${{ matrix.worker_id }} --total=20 --r=${{ matrix.release_channel }} --ci
|
||||
if: steps.node_modules.outputs.cache-hit != 'true'
|
||||
- run: yarn --cwd compiler install --frozen-lockfile
|
||||
if: steps.node_modules.outputs.cache-hit != 'true'
|
||||
- run: yarn build --index=${{ matrix.worker_id }} --total=25 --r=${{ matrix.release_channel }} --ci
|
||||
env:
|
||||
CI: github
|
||||
RELEASE_CHANNEL: ${{ matrix.release_channel }}
|
||||
@@ -213,8 +305,9 @@ jobs:
|
||||
|
||||
test_build:
|
||||
name: yarn test-build
|
||||
needs: build_and_lint
|
||||
needs: [build_and_lint, runtime_compiler_node_modules_cache]
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
test_params: [
|
||||
# Intentionally passing these as strings instead of creating a
|
||||
@@ -250,7 +343,6 @@ jobs:
|
||||
- 1/3
|
||||
- 2/3
|
||||
- 3/3
|
||||
continue-on-error: true
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
@@ -260,16 +352,22 @@ jobs:
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
cache: yarn
|
||||
cache-dependency-path: yarn.lock
|
||||
cache-dependency-path: |
|
||||
yarn.lock
|
||||
compiler/yarn.lock
|
||||
- name: Restore cached node_modules
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache/restore@v4
|
||||
id: node_modules
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: runtime-node_modules-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
|
||||
path: |
|
||||
**/node_modules
|
||||
key: runtime-and-compiler-node_modules-v6-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock', 'compiler/yarn.lock') }}
|
||||
- name: Ensure clean build directory
|
||||
run: rm -rf build
|
||||
- run: yarn install --frozen-lockfile
|
||||
if: steps.node_modules.outputs.cache-hit != 'true'
|
||||
- run: yarn --cwd compiler install --frozen-lockfile
|
||||
if: steps.node_modules.outputs.cache-hit != 'true'
|
||||
- name: Restore archived build
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
@@ -282,7 +380,7 @@ jobs:
|
||||
|
||||
process_artifacts_combined:
|
||||
name: Process artifacts combined
|
||||
needs: build_and_lint
|
||||
needs: [build_and_lint, runtime_node_modules_cache]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
@@ -294,14 +392,16 @@ jobs:
|
||||
cache: yarn
|
||||
cache-dependency-path: yarn.lock
|
||||
- name: Restore cached node_modules
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache/restore@v4
|
||||
id: node_modules
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: runtime-node_modules-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
|
||||
path: |
|
||||
**/node_modules
|
||||
key: runtime-node_modules-v6-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
|
||||
- name: Ensure clean build directory
|
||||
run: rm -rf build
|
||||
- run: yarn install --frozen-lockfile
|
||||
if: steps.node_modules.outputs.cache-hit != 'true'
|
||||
- name: Restore archived build
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
@@ -310,7 +410,7 @@ jobs:
|
||||
merge-multiple: true
|
||||
- name: Display structure of build
|
||||
run: ls -R build
|
||||
- run: echo ${{ github.sha }} >> build/COMMIT_SHA
|
||||
- run: echo ${{ github.event.pull_request.head.sha || github.sha }} >> build/COMMIT_SHA
|
||||
- name: Scrape warning messages
|
||||
run: |
|
||||
mkdir -p ./build/__test_utils__
|
||||
@@ -329,7 +429,7 @@ jobs:
|
||||
|
||||
check_error_codes:
|
||||
name: Search build artifacts for unminified errors
|
||||
needs: build_and_lint
|
||||
needs: [build_and_lint, runtime_node_modules_cache]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
@@ -341,14 +441,16 @@ jobs:
|
||||
cache: yarn
|
||||
cache-dependency-path: yarn.lock
|
||||
- name: Restore cached node_modules
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache/restore@v4
|
||||
id: node_modules
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: runtime-node_modules-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
|
||||
path: |
|
||||
**/node_modules
|
||||
key: runtime-node_modules-v6-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
|
||||
- name: Ensure clean build directory
|
||||
run: rm -rf build
|
||||
- run: yarn install --frozen-lockfile
|
||||
if: steps.node_modules.outputs.cache-hit != 'true'
|
||||
- name: Restore archived build
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
@@ -364,7 +466,7 @@ jobs:
|
||||
|
||||
check_release_dependencies:
|
||||
name: Check release dependencies
|
||||
needs: build_and_lint
|
||||
needs: [build_and_lint, runtime_node_modules_cache]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
@@ -376,14 +478,16 @@ jobs:
|
||||
cache: yarn
|
||||
cache-dependency-path: yarn.lock
|
||||
- name: Restore cached node_modules
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache/restore@v4
|
||||
id: node_modules
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: runtime-node_modules-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
|
||||
path: |
|
||||
**/node_modules
|
||||
key: runtime-node_modules-v6-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
|
||||
- name: Ensure clean build directory
|
||||
run: rm -rf build
|
||||
- run: yarn install --frozen-lockfile
|
||||
if: steps.node_modules.outputs.cache-hit != 'true'
|
||||
- name: Restore archived build
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
@@ -408,16 +512,16 @@ jobs:
|
||||
cache: yarn
|
||||
cache-dependency-path: yarn.lock
|
||||
- name: Restore cached node_modules
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache@v4 # note: this does not reuse centralized cache since it has unique cache key
|
||||
id: node_modules
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: fixtures_dom-node_modules-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
|
||||
path: |
|
||||
**/node_modules
|
||||
key: fixtures_dom-node_modules-v6-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
|
||||
- name: Ensure clean build directory
|
||||
run: rm -rf build
|
||||
- run: yarn install --frozen-lockfile
|
||||
- run: yarn install --frozen-lockfile --cache-folder ~/.cache/yarn
|
||||
working-directory: fixtures/dom
|
||||
- run: yarn --cwd fixtures/dom install --frozen-lockfile
|
||||
if: steps.node_modules.outputs.cache-hit != 'true'
|
||||
- name: Restore archived build
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
@@ -452,14 +556,16 @@ jobs:
|
||||
# That means dependencies of the built packages are not installed.
|
||||
# We need to install dependencies of the workroot to fulfill all dependency constraints
|
||||
- name: Restore cached node_modules
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache@v4 # note: this does not reuse centralized cache since it has unique cache key
|
||||
id: node_modules
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: fixtures_flight-node_modules-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
|
||||
path: |
|
||||
**/node_modules
|
||||
key: fixtures_flight-node_modules-v6-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
|
||||
- name: Ensure clean build directory
|
||||
run: rm -rf build
|
||||
- run: yarn install --frozen-lockfile
|
||||
if: steps.node_modules.outputs.cache-hit != 'true'
|
||||
- name: Restore archived build
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
@@ -477,9 +583,7 @@ jobs:
|
||||
fi
|
||||
- name: Playwright install deps
|
||||
working-directory: fixtures/flight
|
||||
run: |
|
||||
npx playwright install
|
||||
sudo npx playwright install-deps
|
||||
run: npx playwright install --with-deps chromium
|
||||
- name: Run tests
|
||||
working-directory: fixtures/flight
|
||||
run: yarn test
|
||||
@@ -500,8 +604,12 @@ jobs:
|
||||
# ----- DEVTOOLS -----
|
||||
build_devtools_and_process_artifacts:
|
||||
name: Build DevTools and process artifacts
|
||||
needs: build_and_lint
|
||||
needs: [build_and_lint, runtime_node_modules_cache]
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
browser: [chrome, firefox, edge]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
@@ -512,45 +620,48 @@ jobs:
|
||||
cache: yarn
|
||||
cache-dependency-path: yarn.lock
|
||||
- name: Restore cached node_modules
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache/restore@v4
|
||||
id: node_modules
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: runtime-node_modules-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
|
||||
path: |
|
||||
**/node_modules
|
||||
key: runtime-node_modules-v6-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
|
||||
- name: Ensure clean build directory
|
||||
run: rm -rf build
|
||||
- run: yarn install --frozen-lockfile
|
||||
if: steps.node_modules.outputs.cache-hit != 'true'
|
||||
- name: Restore archived build
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
pattern: _build_*
|
||||
path: build
|
||||
merge-multiple: true
|
||||
- run: ./scripts/ci/pack_and_store_devtools_artifacts.sh
|
||||
- run: ./scripts/ci/pack_and_store_devtools_artifacts.sh ${{ matrix.browser }}
|
||||
env:
|
||||
RELEASE_CHANNEL: experimental
|
||||
- name: Display structure of build
|
||||
run: ls -R build
|
||||
- name: Archive devtools build
|
||||
# Simplifies getting the extension for local testing
|
||||
- name: Archive ${{ matrix.browser }} extension
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: react-devtools-${{ matrix.browser }}-extension
|
||||
path: build/devtools/${{ matrix.browser }}-extension.zip
|
||||
|
||||
merge_devtools_artifacts:
|
||||
name: Merge DevTools artifacts
|
||||
needs: build_devtools_and_process_artifacts
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Merge artifacts
|
||||
uses: actions/upload-artifact/merge@v4
|
||||
with:
|
||||
name: react-devtools
|
||||
path: build/devtools.tgz
|
||||
# Simplifies getting the extension for local testing
|
||||
- name: Archive chrome extension
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: react-devtools-chrome-extension
|
||||
path: build/devtools/chrome-extension.zip
|
||||
- name: Archive firefox extension
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: react-devtools-firefox-extension
|
||||
path: build/devtools/firefox-extension.zip
|
||||
pattern: react-devtools-*-extension
|
||||
|
||||
run_devtools_e2e_tests:
|
||||
name: Run DevTools e2e tests
|
||||
needs: build_devtools_and_process_artifacts
|
||||
needs: [build_and_lint, runtime_node_modules_cache]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
@@ -562,14 +673,16 @@ jobs:
|
||||
cache: yarn
|
||||
cache-dependency-path: yarn.lock
|
||||
- name: Restore cached node_modules
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache/restore@v4
|
||||
id: node_modules
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: runtime-node_modules-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
|
||||
path: |
|
||||
**/node_modules
|
||||
key: runtime-node_modules-v6-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
|
||||
- name: Ensure clean build directory
|
||||
run: rm -rf build
|
||||
- run: yarn install --frozen-lockfile
|
||||
if: steps.node_modules.outputs.cache-hit != 'true'
|
||||
- name: Restore archived build
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
@@ -584,9 +697,10 @@ jobs:
|
||||
RELEASE_CHANNEL: experimental
|
||||
|
||||
# ----- SIZEBOT -----
|
||||
download_base_build_for_sizebot:
|
||||
if: ${{ github.event_name == 'pull_request' && github.ref_name != 'main' }}
|
||||
name: Download base build for sizebot
|
||||
sizebot:
|
||||
if: ${{ github.event_name == 'pull_request' && github.ref_name != 'main' && github.event.pull_request.base.ref == 'main' }}
|
||||
name: Run sizebot
|
||||
needs: [build_and_lint, runtime_node_modules_cache]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
@@ -598,20 +712,21 @@ jobs:
|
||||
cache: yarn
|
||||
cache-dependency-path: yarn.lock
|
||||
- name: Restore cached node_modules
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache/restore@v4
|
||||
id: node_modules
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: ${{ runner.arch }}-${{ runner.os }}-modules-${{ hashFiles('yarn.lock', 'scripts/release/yarn.lock') }}
|
||||
path: |
|
||||
**/node_modules
|
||||
key: runtime-release-node_modules-v6-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock', 'scripts/release/yarn.lock') }}
|
||||
- name: Ensure clean build directory
|
||||
run: rm -rf build
|
||||
- run: yarn install --frozen-lockfile
|
||||
- run: yarn install --frozen-lockfile
|
||||
working-directory: scripts/release
|
||||
if: steps.node_modules.outputs.cache-hit != 'true'
|
||||
- run: yarn --cwd scripts/release install --frozen-lockfile
|
||||
if: steps.node_modules.outputs.cache-hit != 'true'
|
||||
- name: Download artifacts for base revision
|
||||
run: |
|
||||
git fetch origin main
|
||||
GH_TOKEN=${{ github.token }} scripts/release/download-experimental-build.js --commit=$(git rev-parse origin/main)
|
||||
GH_TOKEN=${{ github.token }} scripts/release/download-experimental-build.js --commit=$(git rev-parse ${{ github.event.pull_request.base.sha }})
|
||||
mv ./build ./base-build
|
||||
# TODO: The `download-experimental-build` script copies the npm
|
||||
# packages into the `node_modules` directory. This is a historical
|
||||
@@ -619,36 +734,12 @@ jobs:
|
||||
# don't exist.
|
||||
- name: Delete extraneous files
|
||||
run: rm -rf ./base-build/node_modules
|
||||
- name: Display structure of base-build
|
||||
- name: Display structure of base-build from origin/main
|
||||
run: ls -R base-build
|
||||
- name: Archive base-build
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: base-build
|
||||
path: base-build
|
||||
|
||||
sizebot:
|
||||
name: Run sizebot
|
||||
needs: [build_and_lint, download_base_build_for_sizebot]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha || github.sha }}
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
cache: yarn
|
||||
cache-dependency-path: yarn.lock
|
||||
- name: Restore cached node_modules
|
||||
uses: actions/cache@v4
|
||||
id: node_modules
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: runtime-node_modules-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
|
||||
- name: Ensure clean build directory
|
||||
run: rm -rf build
|
||||
- run: yarn install --frozen-lockfile
|
||||
if: steps.node_modules.outputs.cache-hit != 'true'
|
||||
- name: Restore archived build for PR
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
@@ -661,14 +752,7 @@ jobs:
|
||||
node ./scripts/print-warnings/print-warnings.js > build/__test_utils__/ReactAllWarnings.js
|
||||
- name: Display structure of build for PR
|
||||
run: ls -R build
|
||||
- name: Restore archived base-build from origin/main
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: base-build
|
||||
path: base-build
|
||||
- name: Display structure of base-build from origin/main
|
||||
run: ls -R base-build
|
||||
- run: echo ${{ github.sha }} >> build/COMMIT_SHA
|
||||
- run: echo ${{ github.event.pull_request.head.sha || github.sha }} >> build/COMMIT_SHA
|
||||
- run: node ./scripts/tasks/danger
|
||||
- name: Archive sizebot results
|
||||
uses: actions/upload-artifact@v4
|
||||
|
||||
64
.github/workflows/runtime_commit_artifacts.yml
vendored
64
.github/workflows/runtime_commit_artifacts.yml
vendored
@@ -16,6 +16,11 @@ on:
|
||||
required: true
|
||||
default: false
|
||||
type: boolean
|
||||
dry_run:
|
||||
description: Perform a dry run (run everything except push)
|
||||
required: true
|
||||
default: false
|
||||
type: boolean
|
||||
|
||||
env:
|
||||
TZ: /usr/share/zoneinfo/America/Los_Angeles
|
||||
@@ -73,15 +78,13 @@ jobs:
|
||||
uses: actions/cache@v4
|
||||
id: node_modules
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: runtime-release-node_modules-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock', 'scripts/release/yarn.lock') }}
|
||||
path: |
|
||||
**/node_modules
|
||||
key: runtime-release-node_modules-v6-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock', 'scripts/release/yarn.lock') }}
|
||||
- name: Ensure clean build directory
|
||||
run: rm -rf build
|
||||
- run: yarn install --frozen-lockfile
|
||||
name: yarn install (react)
|
||||
- run: yarn install --frozen-lockfile
|
||||
name: yarn install (scripts/release)
|
||||
working-directory: scripts/release
|
||||
- run: yarn --cwd scripts/release install --frozen-lockfile
|
||||
- name: Download artifacts for base revision
|
||||
run: |
|
||||
GH_TOKEN=${{ github.token }} scripts/release/download-experimental-build.js --commit=${{ inputs.commit_sha || github.event.workflow_run.head_sha || github.sha }}
|
||||
@@ -107,9 +110,10 @@ jobs:
|
||||
mkdir ./compiled/facebook-www/__test_utils__
|
||||
mv build/__test_utils__/ReactAllWarnings.js ./compiled/facebook-www/__test_utils__/ReactAllWarnings.js
|
||||
|
||||
# Move eslint-plugin-react-hooks into facebook-www
|
||||
# Move eslint-plugin-react-hooks into eslint-plugin-react-hooks
|
||||
mkdir ./compiled/eslint-plugin-react-hooks
|
||||
mv build/oss-experimental/eslint-plugin-react-hooks/cjs/eslint-plugin-react-hooks.development.js \
|
||||
./compiled/facebook-www/eslint-plugin-react-hooks.js
|
||||
./compiled/eslint-plugin-react-hooks/index.js
|
||||
|
||||
# Move unstable_server-external-runtime.js into facebook-www
|
||||
mv build/oss-experimental/react-dom/unstable_server-external-runtime.js \
|
||||
@@ -242,18 +246,22 @@ jobs:
|
||||
run: |
|
||||
echo ":"
|
||||
git status -u
|
||||
- name: Check commit message
|
||||
if: inputs.dry_run
|
||||
run: |
|
||||
git fetch origin --quiet
|
||||
git show ${{ inputs.commit_sha || github.event.workflow_run.head_sha || github.sha }} --no-patch --pretty=format:"%B"
|
||||
- name: Commit changes to branch
|
||||
if: inputs.force == true || steps.check_should_commit.outputs.should_commit == 'true'
|
||||
uses: stefanzweifel/git-auto-commit-action@v5
|
||||
with:
|
||||
commit_message: |
|
||||
${{ github.event.workflow_run.head_commit.message || format('Manual build of {0}', github.event.workflow_run.head_sha || github.sha) }}
|
||||
run: |
|
||||
git config --global user.email "${{ format('{0}@users.noreply.github.com', github.triggering_actor) }}"
|
||||
git config --global user.name "${{ github.triggering_actor }}"
|
||||
|
||||
DiffTrain build for [${{ github.event.workflow_run.head_sha || github.sha }}](https://github.com/facebook/react/commit/${{ github.event.workflow_run.head_sha || github.sha }})
|
||||
branch: builds/facebook-www
|
||||
commit_user_name: ${{ github.triggering_actor }}
|
||||
commit_user_email: ${{ format('{0}@users.noreply.github.com', github.triggering_actor) }}
|
||||
create_branch: true
|
||||
git fetch origin --quiet
|
||||
git commit -m "$(git show ${{ inputs.commit_sha || github.event.workflow_run.head_sha || github.sha }} --no-patch --pretty=format:'%B%n%nDiffTrain build for [${{ inputs.commit_sha || github.event.workflow_run.head_sha || github.sha }}](https://github.com/facebook/react/commit/${{ inputs.commit_sha || github.event.workflow_run.head_sha || github.sha}})')" || echo "No changes to commit"
|
||||
- name: Push changes to branch
|
||||
if: inputs.dry_run == false && (inputs.force == true || steps.check_should_commit.outputs.should_commit == 'true')
|
||||
run: git push
|
||||
|
||||
commit_fbsource_artifacts:
|
||||
needs: download_artifacts
|
||||
@@ -409,15 +417,19 @@ jobs:
|
||||
run: |
|
||||
git add .
|
||||
git status
|
||||
- name: Check commit message
|
||||
if: inputs.dry_run
|
||||
run: |
|
||||
git fetch origin --quiet
|
||||
git show ${{ inputs.commit_sha || github.event.workflow_run.head_sha || github.sha }} --no-patch --pretty=format:"%B"
|
||||
- name: Commit changes to branch
|
||||
if: inputs.force == true || steps.check_should_commit.outputs.should_commit == 'true'
|
||||
uses: stefanzweifel/git-auto-commit-action@v5
|
||||
with:
|
||||
commit_message: |
|
||||
${{ github.event.workflow_run.head_commit.message || format('Manual build of {0}', github.event.workflow_run.head_sha || github.sha) }}
|
||||
run: |
|
||||
git config --global user.email "${{ format('{0}@users.noreply.github.com', github.triggering_actor) }}"
|
||||
git config --global user.name "${{ github.triggering_actor }}"
|
||||
|
||||
DiffTrain build for [${{ github.event.workflow_run.head_sha || github.sha }}](https://github.com/facebook/react/commit/${{ github.event.workflow_run.head_sha || github.sha }})
|
||||
branch: builds/facebook-fbsource
|
||||
commit_user_name: ${{ github.triggering_actor }}
|
||||
commit_user_email: ${{ format('{0}@users.noreply.github.com', github.triggering_actor) }}
|
||||
create_branch: true
|
||||
git fetch origin --quiet
|
||||
git commit -m "$(git show ${{ inputs.commit_sha || github.event.workflow_run.head_sha || github.sha }} --no-patch --pretty=format:'%B%n%nDiffTrain build for [${{ inputs.commit_sha || github.event.workflow_run.head_sha || github.sha }}](https://github.com/facebook/react/commit/${{ inputs.commit_sha || github.event.workflow_run.head_sha || github.sha}})')" || echo "No changes to commit"
|
||||
- name: Push changes to branch
|
||||
if: inputs.dry_run == false && (inputs.force == true || steps.check_should_commit.outputs.should_commit == 'true')
|
||||
run: git push
|
||||
|
||||
@@ -1,16 +1,25 @@
|
||||
name: (Shared) Discord Notify
|
||||
name: (Runtime) Discord Notify
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types: [labeled]
|
||||
types: [opened, ready_for_review]
|
||||
paths-ignore:
|
||||
- compiler/**
|
||||
- .github/workflows/compiler_**.yml
|
||||
|
||||
jobs:
|
||||
check_maintainer:
|
||||
uses: facebook/react/.github/workflows/shared_check_maintainer.yml@main
|
||||
with:
|
||||
actor: ${{ github.event.pull_request.user.login }}
|
||||
|
||||
notify:
|
||||
if: ${{ github.event.label.name == 'React Core Team' }}
|
||||
if: ${{ needs.check_maintainer.outputs.is_core_team == 'true' }}
|
||||
needs: check_maintainer
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Discord Webhook Action
|
||||
uses: tsickert/discord-webhook@v6.0.0
|
||||
uses: tsickert/discord-webhook@86dc739f3f165f16dadc5666051c367efa1692f4
|
||||
with:
|
||||
webhook-url: ${{ secrets.DISCORD_WEBHOOK_URL }}
|
||||
embed-author-name: ${{ github.event.pull_request.user.login }}
|
||||
60
.github/workflows/runtime_eslint_plugin_e2e.yml
vendored
Normal file
60
.github/workflows/runtime_eslint_plugin_e2e.yml
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
name: (Runtime) ESLint Plugin E2E
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- compiler/**
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref_name }}-${{ github.event.pull_request.number || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
TZ: /usr/share/zoneinfo/America/Los_Angeles
|
||||
|
||||
jobs:
|
||||
# ----- TESTS -----
|
||||
test:
|
||||
name: ESLint v${{ matrix.eslint_major }}
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
eslint_major:
|
||||
- "6"
|
||||
- "7"
|
||||
- "8"
|
||||
- "9"
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha || github.sha }}
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
cache: yarn
|
||||
cache-dependency-path: |
|
||||
yarn.lock
|
||||
compiler/yarn.lock
|
||||
- name: Restore cached node_modules
|
||||
uses: actions/cache@v4
|
||||
id: node_modules
|
||||
with:
|
||||
path: |
|
||||
**/node_modules
|
||||
key: runtime-and-compiler-eslint_e2e-node_modules-v6-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock', 'compiler/yarn.lock') }}
|
||||
- name: Ensure clean build directory
|
||||
run: rm -rf build
|
||||
- run: yarn install --frozen-lockfile
|
||||
- run: yarn --cwd compiler install --frozen-lockfile
|
||||
- name: Build plugin
|
||||
working-directory: fixtures/eslint-v${{ matrix.eslint_major }}
|
||||
run: node build.mjs
|
||||
- name: Install fixture dependencies
|
||||
working-directory: ./fixtures/eslint-v${{ matrix.eslint_major }}
|
||||
run: yarn --frozen-lockfile
|
||||
- name: Run lint test
|
||||
working-directory: ./fixtures/eslint-v${{ matrix.eslint_major }}
|
||||
run: yarn lint
|
||||
8
.github/workflows/runtime_prereleases.yml
vendored
8
.github/workflows/runtime_prereleases.yml
vendored
@@ -39,13 +39,13 @@ jobs:
|
||||
uses: actions/cache@v4
|
||||
id: node_modules
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: runtime-release-node_modules-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock', 'scripts/release/yarn.lock') }}
|
||||
path: |
|
||||
**/node_modules
|
||||
key: runtime-release-node_modules-v6-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock', 'scripts/release/yarn.lock') }}
|
||||
- name: Ensure clean build directory
|
||||
run: rm -rf build
|
||||
- run: yarn install --frozen-lockfile
|
||||
- run: yarn install --frozen-lockfile
|
||||
working-directory: scripts/release
|
||||
- run: yarn --cwd scripts/release install --frozen-lockfile
|
||||
- run: |
|
||||
scripts/release/prepare-release-from-ci.js --skipTests -r ${{ inputs.release_channel }} --commit=${{ inputs.commit_sha }}
|
||||
cp ./scripts/release/ci-npmrc ~/.npmrc
|
||||
|
||||
125
.github/workflows/runtime_releases_from_npm_manual.yml
vendored
Normal file
125
.github/workflows/runtime_releases_from_npm_manual.yml
vendored
Normal file
@@ -0,0 +1,125 @@
|
||||
name: (Runtime) Publish Releases from NPM Manual
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version_to_promote:
|
||||
required: true
|
||||
description: Current npm version (non-experimental) to promote
|
||||
type: string
|
||||
version_to_publish:
|
||||
required: true
|
||||
description: Version to publish for the specified packages
|
||||
type: string
|
||||
only_packages:
|
||||
description: Packages to publish (space separated)
|
||||
type: string
|
||||
skip_packages:
|
||||
description: Packages to NOT publish (space separated)
|
||||
type: string
|
||||
tags:
|
||||
description: NPM tags (space separated)
|
||||
type: string
|
||||
default: untagged
|
||||
dry:
|
||||
required: true
|
||||
description: Dry run instead of publish?
|
||||
type: boolean
|
||||
default: true
|
||||
force_notify:
|
||||
description: Force a Discord notification?
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
env:
|
||||
TZ: /usr/share/zoneinfo/America/Los_Angeles
|
||||
# https://github.com/actions/cache/blob/main/tips-and-workarounds.md#cache-segment-restore-timeout
|
||||
SEGMENT_DOWNLOAD_TIMEOUT_MINS: 1
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
|
||||
jobs:
|
||||
notify:
|
||||
if: ${{ inputs.force_notify || inputs.dry == false || inputs.dry == 'false' }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Discord Webhook Action
|
||||
uses: tsickert/discord-webhook@86dc739f3f165f16dadc5666051c367efa1692f4
|
||||
with:
|
||||
webhook-url: ${{ secrets.DISCORD_WEBHOOK_URL }}
|
||||
embed-author-name: ${{ github.event.sender.login }}
|
||||
embed-author-url: ${{ github.event.sender.html_url }}
|
||||
embed-author-icon-url: ${{ github.event.sender.avatar_url }}
|
||||
embed-title: "⚠️ Publishing release from NPM${{ (inputs.dry && ' (dry run)') || '' }}"
|
||||
embed-description: |
|
||||
```json
|
||||
${{ toJson(inputs) }}
|
||||
```
|
||||
embed-url: https://github.com/facebook/react/actions/runs/${{ github.run_id }}
|
||||
|
||||
publish:
|
||||
name: Publish releases
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
cache: yarn
|
||||
cache-dependency-path: yarn.lock
|
||||
- name: Restore cached node_modules
|
||||
uses: actions/cache@v4
|
||||
id: node_modules
|
||||
with:
|
||||
path: |
|
||||
**/node_modules
|
||||
key: runtime-release-node_modules-v6-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock', 'scripts/release/yarn.lock') }}
|
||||
- name: Ensure clean build directory
|
||||
run: rm -rf build
|
||||
- run: yarn install --frozen-lockfile
|
||||
- run: yarn --cwd scripts/release install --frozen-lockfile
|
||||
- run: cp ./scripts/release/ci-npmrc ~/.npmrc
|
||||
- if: '${{ inputs.only_packages }}'
|
||||
name: 'Prepare ${{ inputs.only_packages }} from NPM'
|
||||
run: |
|
||||
scripts/release/prepare-release-from-npm.js \
|
||||
--ci \
|
||||
--skipTests \
|
||||
--version=${{ inputs.version_to_promote }} \
|
||||
--publishVersion=${{ inputs.version_to_publish }} \
|
||||
--onlyPackages=${{ inputs.only_packages }}
|
||||
- if: '${{ inputs.skip_packages }}'
|
||||
name: 'Prepare all packages EXCEPT ${{ inputs.skip_packages }} from NPM'
|
||||
run: |
|
||||
scripts/release/prepare-release-from-npm.js \
|
||||
--ci \
|
||||
--skipTests \
|
||||
--version=${{ inputs.version_to_promote }} \
|
||||
--publishVersion=${{ inputs.version_to_publish }} \
|
||||
--skipPackages=${{ inputs.skip_packages }}
|
||||
- name: Check prepared files
|
||||
run: ls -R build/node_modules
|
||||
- if: '${{ inputs.only_packages }}'
|
||||
name: 'Publish ${{ inputs.only_packages }}'
|
||||
run: |
|
||||
scripts/release/publish.js \
|
||||
--ci \
|
||||
--tags=${{ inputs.tags }} \
|
||||
--publishVersion=${{ inputs.version_to_publish }} \
|
||||
--onlyPackages=${{ inputs.only_packages }} ${{ (inputs.dry && '') || '\'}}
|
||||
${{ inputs.dry && '--dry'}}
|
||||
- if: '${{ inputs.skip_packages }}'
|
||||
name: 'Publish all packages EXCEPT ${{ inputs.skip_packages }}'
|
||||
run: |
|
||||
scripts/release/publish.js \
|
||||
--ci \
|
||||
--tags=${{ inputs.tags }} \
|
||||
--publishVersion=${{ inputs.version_to_publish }} \
|
||||
--skipPackages=${{ inputs.skip_packages }} ${{ (inputs.dry && '') || '\'}}
|
||||
${{ inputs.dry && '--dry'}}
|
||||
- name: Archive released package for debugging
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: build
|
||||
path: |
|
||||
./build/node_modules
|
||||
71
.github/workflows/shared_check_maintainer.yml
vendored
Normal file
71
.github/workflows/shared_check_maintainer.yml
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
name: (Shared) Check maintainer
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
actor:
|
||||
required: true
|
||||
type: string
|
||||
is_remote:
|
||||
required: false
|
||||
type: boolean
|
||||
default: false
|
||||
outputs:
|
||||
is_core_team:
|
||||
value: ${{ jobs.check_maintainer.outputs.is_core_team }}
|
||||
|
||||
env:
|
||||
TZ: /usr/share/zoneinfo/America/Los_Angeles
|
||||
# https://github.com/actions/cache/blob/main/tips-and-workarounds.md#cache-segment-restore-timeout
|
||||
SEGMENT_DOWNLOAD_TIMEOUT_MINS: 1
|
||||
|
||||
jobs:
|
||||
check_maintainer:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
is_core_team: ${{ steps.check_if_actor_is_maintainer.outputs.result }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Check if actor is maintainer
|
||||
id: check_if_actor_is_maintainer
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const fs = require('fs');
|
||||
const actor = '${{ inputs.actor }}';
|
||||
let isRemote = ${{ inputs.is_remote }};
|
||||
if (typeof isRemote === 'string') {
|
||||
isRemote = isRemote === 'true';
|
||||
}
|
||||
if (typeof isRemote !== 'boolean') {
|
||||
throw new Error(`Invalid \`isRemote\` input. Expected a boolean, got: ${isRemote}`);
|
||||
}
|
||||
|
||||
let content = null;
|
||||
if (isRemote === true) {
|
||||
const res = await github.rest.repos.getContent({
|
||||
owner: 'facebook',
|
||||
repo: 'react',
|
||||
path: 'MAINTAINERS',
|
||||
ref: 'main',
|
||||
headers: { Accept: 'application/vnd.github+json' }
|
||||
});
|
||||
if (res.status !== 200) {
|
||||
console.error(res);
|
||||
throw new Error('Unable to fetch MAINTAINERS file');
|
||||
}
|
||||
content = Buffer.from(res.data.content, 'base64').toString();
|
||||
} else {
|
||||
content = await fs.readFileSync('./MAINTAINERS', { encoding: 'utf8' });
|
||||
}
|
||||
if (content === null) {
|
||||
throw new Error('Unable to retrieve local or http MAINTAINERS file');
|
||||
}
|
||||
|
||||
const maintainers = new Set(content.split('\n'));
|
||||
if (maintainers.has(actor)) {
|
||||
console.log(`🟢 ${actor} is a maintainer`);
|
||||
return true;
|
||||
}
|
||||
console.log(`🔴 ${actor} is NOT a maintainer`);
|
||||
return null;
|
||||
35
.github/workflows/shared_cleanup_branch_caches.yml
vendored
Normal file
35
.github/workflows/shared_cleanup_branch_caches.yml
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
# https://github.com/actions/cache/blob/main/tips-and-workarounds.md#force-deletion-of-caches-overriding-default-cache-eviction-policy
|
||||
|
||||
name: (Shared) Cleanup Branch Caches
|
||||
on:
|
||||
pull_request:
|
||||
types:
|
||||
- closed
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
cleanup:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
# `actions:write` permission is required to delete caches
|
||||
# See also: https://docs.github.com/en/rest/actions/cache?apiVersion=2022-11-28#delete-a-github-actions-cache-for-a-repository-using-a-cache-id
|
||||
actions: write
|
||||
contents: read
|
||||
steps:
|
||||
- name: Cleanup
|
||||
run: |
|
||||
echo "Fetching list of cache key"
|
||||
cacheKeysForPR=$(gh cache list --ref $BRANCH --limit 100 --json id --jq '.[].id')
|
||||
|
||||
## Setting this to not fail the workflow while deleting cache keys.
|
||||
set +e
|
||||
echo "Deleting caches..."
|
||||
for cacheKey in $cacheKeysForPR
|
||||
do
|
||||
gh cache delete $cacheKey
|
||||
done
|
||||
echo "Done"
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
GH_REPO: ${{ github.repository }}
|
||||
BRANCH: refs/pull/${{ github.event.pull_request.number }}/merge
|
||||
37
.github/workflows/shared_close_direct_sync_branch_prs.yml
vendored
Normal file
37
.github/workflows/shared_close_direct_sync_branch_prs.yml
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
name: (Shared) Close Direct Sync Branch PRs
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- 'builds/facebook-**'
|
||||
|
||||
env:
|
||||
TZ: /usr/share/zoneinfo/America/Los_Angeles
|
||||
# https://github.com/actions/cache/blob/main/tips-and-workarounds.md#cache-segment-restore-timeout
|
||||
SEGMENT_DOWNLOAD_TIMEOUT_MINS: 1
|
||||
|
||||
jobs:
|
||||
close_pr:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Close PR
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const owner = context.repo.owner;
|
||||
const repo = context.repo.repo;
|
||||
const pullNumber = ${{ github.event.number }};
|
||||
|
||||
await github.rest.pulls.createReview({
|
||||
owner,
|
||||
repo,
|
||||
pull_number: pullNumber,
|
||||
body: 'Do not land changes to `${{ github.event.pull_request.base.ref }}`. Please re-open your PR targeting `main` instead.',
|
||||
event: 'REQUEST_CHANGES'
|
||||
});
|
||||
await github.rest.pulls.update({
|
||||
owner,
|
||||
repo,
|
||||
pull_number: pullNumber,
|
||||
state: 'closed'
|
||||
});
|
||||
31
.github/workflows/shared_label_core_team_prs.yml
vendored
Normal file
31
.github/workflows/shared_label_core_team_prs.yml
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
name: (Shared) Label Core Team PRs
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
|
||||
env:
|
||||
TZ: /usr/share/zoneinfo/America/Los_Angeles
|
||||
# https://github.com/actions/cache/blob/main/tips-and-workarounds.md#cache-segment-restore-timeout
|
||||
SEGMENT_DOWNLOAD_TIMEOUT_MINS: 1
|
||||
|
||||
jobs:
|
||||
check_maintainer:
|
||||
uses: facebook/react/.github/workflows/shared_check_maintainer.yml@main
|
||||
with:
|
||||
actor: ${{ github.event.pull_request.user.login }}
|
||||
|
||||
label:
|
||||
if: ${{ needs.check_maintainer.outputs.is_core_team == 'true' }}
|
||||
runs-on: ubuntu-latest
|
||||
needs: check_maintainer
|
||||
steps:
|
||||
- name: Label PR as React Core Team
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
github.rest.issues.addLabels({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: ${{ github.event.number }},
|
||||
labels: ['React Core Team']
|
||||
});
|
||||
20
.github/workflows/shared_lint.yml
vendored
20
.github/workflows/shared_lint.yml
vendored
@@ -28,8 +28,9 @@ jobs:
|
||||
- name: Restore cached node_modules
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: shared-lint-node_modules-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('**/yarn.lock') }}
|
||||
path: |
|
||||
**/node_modules
|
||||
key: shared-lint-node_modules-v6-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('**/yarn.lock') }}
|
||||
- name: Ensure clean build directory
|
||||
run: rm -rf build
|
||||
- run: yarn install --frozen-lockfile
|
||||
@@ -48,8 +49,9 @@ jobs:
|
||||
- name: Restore cached node_modules
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: shared-lint-node_modules-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('**/yarn.lock') }}
|
||||
path: |
|
||||
**/node_modules
|
||||
key: shared-lint-node_modules-v6-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('**/yarn.lock') }}
|
||||
- name: Ensure clean build directory
|
||||
run: rm -rf build
|
||||
- run: yarn install --frozen-lockfile
|
||||
@@ -68,8 +70,9 @@ jobs:
|
||||
- name: Restore cached node_modules
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: shared-lint-node_modules-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('**/yarn.lock') }}
|
||||
path: |
|
||||
**/node_modules
|
||||
key: shared-lint-node_modules-v6-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('**/yarn.lock') }}
|
||||
- name: Ensure clean build directory
|
||||
run: rm -rf build
|
||||
- run: yarn install --frozen-lockfile
|
||||
@@ -88,8 +91,9 @@ jobs:
|
||||
- name: Restore cached node_modules
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: shared-lint-node_modules-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('**/yarn.lock') }}
|
||||
path: |
|
||||
**/node_modules
|
||||
key: shared-lint-node_modules-v6-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('**/yarn.lock') }}
|
||||
- name: Ensure clean build directory
|
||||
run: rm -rf build
|
||||
- run: yarn install --frozen-lockfile
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -37,3 +37,4 @@ packages/react-devtools-fusebox/dist
|
||||
packages/react-devtools-inline/dist
|
||||
packages/react-devtools-shell/dist
|
||||
packages/react-devtools-timeline/dist
|
||||
|
||||
|
||||
22
MAINTAINERS
Normal file
22
MAINTAINERS
Normal file
@@ -0,0 +1,22 @@
|
||||
acdlite
|
||||
eps1lon
|
||||
gaearon
|
||||
gnoff
|
||||
unstubbable
|
||||
hoxyq
|
||||
jackpope
|
||||
jbonta
|
||||
jbrown215
|
||||
josephsavona
|
||||
kassens
|
||||
mattcarrollcode
|
||||
mofeiZ
|
||||
mvitousek
|
||||
pieterv
|
||||
poteto
|
||||
rickhanlonii
|
||||
sebmarkbage
|
||||
sethwebster
|
||||
sophiebits
|
||||
elicwhite
|
||||
yuzhi
|
||||
@@ -33,7 +33,6 @@ const canaryChannelLabel = 'canary';
|
||||
const rcNumber = 0;
|
||||
|
||||
const stablePackages = {
|
||||
'eslint-plugin-react-hooks': '5.2.0',
|
||||
'jest-react': '0.17.0',
|
||||
react: ReactVersion,
|
||||
'react-art': ReactVersion,
|
||||
|
||||
17
babel.config-ts.js
Normal file
17
babel.config-ts.js
Normal file
@@ -0,0 +1,17 @@
|
||||
/**
|
||||
* This file is purely being used for local jest runs, and doesn't participate in the build process.
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
module.exports = {
|
||||
plugins: [
|
||||
'@babel/plugin-syntax-jsx',
|
||||
'@babel/plugin-transform-flow-strip-types',
|
||||
['@babel/plugin-transform-class-properties', {loose: true}],
|
||||
'@babel/plugin-transform-classes',
|
||||
],
|
||||
presets: [
|
||||
['@babel/preset-env', {targets: {node: 'current'}}],
|
||||
'@babel/preset-typescript',
|
||||
],
|
||||
};
|
||||
6
compiler/.gitignore
vendored
6
compiler/.gitignore
vendored
@@ -21,4 +21,8 @@ dist
|
||||
.spr.yml
|
||||
testfilter.txt
|
||||
|
||||
bundle-oss.sh
|
||||
bundle-oss.sh
|
||||
|
||||
# forgive
|
||||
*.vsix
|
||||
.vscode-test
|
||||
|
||||
1217
compiler/Cargo.lock
generated
1217
compiler/Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -1,61 +0,0 @@
|
||||
[workspace]
|
||||
resolver = "2"
|
||||
members = ["crates/*"]
|
||||
|
||||
[workspace.package]
|
||||
authors = ["The React Team https://react.dev/community/team"]
|
||||
description = "React Compiler"
|
||||
edition = "2021"
|
||||
homepage = "https://github.com/facebook/react"
|
||||
keywords = ["JavaScript", "TypeScript", "React", "React Compiler", "Compiler"]
|
||||
license = "MIT"
|
||||
repository = "https://github.com/facebook/react"
|
||||
|
||||
[workspace.dependencies]
|
||||
# workspace crates
|
||||
react_build_hir = { path = "crates/react_build_hir" }
|
||||
react_diagnostics = { path = "crates/react_diagnostics" }
|
||||
react_estree = { path = "crates/react_estree" }
|
||||
react_estree_codegen = { path = "crates/react_estree_codegen" }
|
||||
react_fixtures = { path = "crates/react_fixtures" }
|
||||
react_hermes_parser = { path = "crates/react_hermes_parser" }
|
||||
react_hir = { path = "crates/react_hir" }
|
||||
react_optimization = { path = "crates/react_optimization" }
|
||||
react_semantic_analysis = { path = "crates/react_semantic_analysis" }
|
||||
react_ssa = { path = "crates/react_ssa" }
|
||||
react_utils = { path = "crates/react_utils" }
|
||||
|
||||
# dependencies
|
||||
indexmap = { version = "2.0.0", features = ["serde"] }
|
||||
insta = { version = "1.30.0", features = ["glob"] }
|
||||
miette = { version = "5.9.0" }
|
||||
prettyplease = "0.2.10"
|
||||
quote = "1.0.29"
|
||||
serde = { version = "1.0.167", features = ["serde_derive"] }
|
||||
serde_json = "1.0.100"
|
||||
stacker = "0.1.15"
|
||||
static_assertions = "1.1.0"
|
||||
syn = "2.0.23"
|
||||
thiserror = "1.0.41"
|
||||
hermes = { git = "https://github.com/facebook/hermes.git" }
|
||||
juno_support = { git = "https://github.com/facebook/hermes.git" }
|
||||
|
||||
[profile.release]
|
||||
# configuration adapted from oxc
|
||||
# https://github.com/Boshen/oxc/blob/ea85ee9f2d64dd284c5b7410f491d81fb879abae/Cargo.toml#L89-L97
|
||||
opt-level = 3
|
||||
lto = "fat"
|
||||
codegen-units = 1
|
||||
strip = "symbols"
|
||||
debug = false
|
||||
panic = "abort" # Let it crash and force ourselves to write safe Rust.
|
||||
|
||||
# Make insta run faster by compiling with release mode optimizations
|
||||
# https://docs.rs/insta/latest/insta/#optional-faster-runs
|
||||
[profile.dev.package.insta]
|
||||
opt-level = 3
|
||||
|
||||
# Make insta diffing libary faster by compiling with release mode optimizations
|
||||
# https://docs.rs/insta/latest/insta/#optional-faster-runs
|
||||
[profile.dev.package.similar]
|
||||
opt-level = 3
|
||||
@@ -9,6 +9,13 @@ import {expect, test} from '@playwright/test';
|
||||
import {encodeStore, type Store} from '../../lib/stores';
|
||||
import {format} from 'prettier';
|
||||
|
||||
function isMonacoLoaded(): boolean {
|
||||
return (
|
||||
typeof window['MonacoEnvironment'] !== 'undefined' &&
|
||||
window['__MONACO_LOADED__'] === true
|
||||
);
|
||||
}
|
||||
|
||||
function formatPrint(data: Array<string>): Promise<string> {
|
||||
return format(data.join(''), {parser: 'babel'});
|
||||
}
|
||||
@@ -105,6 +112,7 @@ function nonReactFn() {
|
||||
|
||||
test('editor should open successfully', async ({page}) => {
|
||||
await page.goto(`/`, {waitUntil: 'networkidle'});
|
||||
await page.waitForFunction(isMonacoLoaded);
|
||||
await page.screenshot({
|
||||
fullPage: true,
|
||||
path: 'test-results/00-fresh-page.png',
|
||||
@@ -120,6 +128,7 @@ test('editor should compile from hash successfully', async ({page}) => {
|
||||
};
|
||||
const hash = encodeStore(store);
|
||||
await page.goto(`/#${hash}`, {waitUntil: 'networkidle'});
|
||||
await page.waitForFunction(isMonacoLoaded);
|
||||
|
||||
// User input from hash compiles
|
||||
await page.screenshot({
|
||||
@@ -143,6 +152,7 @@ test('reset button works', async ({page}) => {
|
||||
};
|
||||
const hash = encodeStore(store);
|
||||
await page.goto(`/#${hash}`, {waitUntil: 'networkidle'});
|
||||
await page.waitForFunction(isMonacoLoaded);
|
||||
|
||||
// Reset button works
|
||||
page.on('dialog', dialog => dialog.accept());
|
||||
@@ -166,6 +176,7 @@ TEST_CASE_INPUTS.forEach((t, idx) =>
|
||||
};
|
||||
const hash = encodeStore(store);
|
||||
await page.goto(`/#${hash}`, {waitUntil: 'networkidle'});
|
||||
await page.waitForFunction(isMonacoLoaded);
|
||||
await page.screenshot({
|
||||
fullPage: true,
|
||||
path: `test-results/03-0${idx}-${t.name}.png`,
|
||||
|
||||
@@ -89,6 +89,9 @@ export default function Input({errors, language}: Props): JSX.Element {
|
||||
_: editor.IStandaloneCodeEditor,
|
||||
monaco: Monaco,
|
||||
) => void = (_, monaco) => {
|
||||
if (typeof window !== 'undefined') {
|
||||
window['__MONACO_LOADED__'] = true;
|
||||
}
|
||||
setMonaco(monaco);
|
||||
|
||||
const tscOptions = {
|
||||
|
||||
@@ -6,11 +6,10 @@
|
||||
*/
|
||||
|
||||
import type {Dispatch, ReactNode} from 'react';
|
||||
import {useReducer} from 'react';
|
||||
import {useEffect, useReducer} from 'react';
|
||||
import createContext from '../lib/createContext';
|
||||
import {emptyStore} from '../lib/defaultStore';
|
||||
import type {Store} from '../lib/stores';
|
||||
import {saveStore} from '../lib/stores';
|
||||
import {saveStore, type Store} from '../lib/stores';
|
||||
|
||||
const StoreContext = createContext<Store>();
|
||||
|
||||
@@ -31,6 +30,11 @@ export const useStoreDispatch = StoreDispatchContext.useContext;
|
||||
*/
|
||||
export function StoreProvider({children}: {children: ReactNode}): JSX.Element {
|
||||
const [store, dispatch] = useReducer(storeReducer, emptyStore);
|
||||
useEffect(() => {
|
||||
if (store !== emptyStore) {
|
||||
saveStore(store);
|
||||
}
|
||||
}, [store]);
|
||||
|
||||
return (
|
||||
<StoreContext.Provider value={store}>
|
||||
@@ -59,19 +63,14 @@ function storeReducer(store: Store, action: ReducerAction): Store {
|
||||
switch (action.type) {
|
||||
case 'setStore': {
|
||||
const newStore = action.payload.store;
|
||||
|
||||
saveStore(newStore);
|
||||
return newStore;
|
||||
}
|
||||
case 'updateFile': {
|
||||
const {source} = action.payload;
|
||||
|
||||
const newStore = {
|
||||
...store,
|
||||
source,
|
||||
};
|
||||
|
||||
saveStore(newStore);
|
||||
return newStore;
|
||||
}
|
||||
}
|
||||
|
||||
2
compiler/apps/playground/next-env.d.ts
vendored
2
compiler/apps/playground/next-env.d.ts
vendored
@@ -2,4 +2,4 @@
|
||||
/// <reference types="next/image-types/global" />
|
||||
|
||||
// NOTE: This file should not be edited
|
||||
// see https://nextjs.org/docs/app/building-your-application/configuring/typescript for more information.
|
||||
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
"vercel-build": "yarn build",
|
||||
"start": "next start",
|
||||
"lint": "next lint",
|
||||
"test": "playwright test"
|
||||
"test": "playwright test --workers=4"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/core": "^7.18.9",
|
||||
@@ -22,9 +22,9 @@
|
||||
"@babel/plugin-transform-block-scoping": "^7.18.9",
|
||||
"@babel/plugin-transform-modules-commonjs": "^7.18.9",
|
||||
"@babel/preset-react": "^7.18.9",
|
||||
"@babel/preset-typescript": "^7.18.9",
|
||||
"@babel/preset-typescript": "^7.26.0",
|
||||
"@babel/traverse": "^7.18.9",
|
||||
"@babel/types": "7.18.9",
|
||||
"@babel/types": "7.26.3",
|
||||
"@heroicons/react": "^1.0.6",
|
||||
"@monaco-editor/react": "^4.4.6",
|
||||
"@playwright/test": "^1.42.1",
|
||||
@@ -34,18 +34,18 @@
|
||||
"invariant": "^2.2.4",
|
||||
"lz-string": "^1.5.0",
|
||||
"monaco-editor": "^0.52.0",
|
||||
"next": "^15.0.1",
|
||||
"next": "^15.2.0-canary.64",
|
||||
"notistack": "^3.0.0-alpha.7",
|
||||
"prettier": "^3.3.3",
|
||||
"pretty-format": "^29.3.1",
|
||||
"re-resizable": "^6.9.16",
|
||||
"react": "19.0.0-rc-77b637d6-20241016",
|
||||
"react-dom": "19.0.0-rc-77b637d6-20241016"
|
||||
"react": "^19.0.0",
|
||||
"react-dom": "^19.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "18.11.9",
|
||||
"@types/react": "npm:types-react@19.0.0-rc.1",
|
||||
"@types/react-dom": "npm:types-react-dom@19.0.0-rc.1",
|
||||
"@types/react": "^19.0.0",
|
||||
"@types/react-dom": "^19.0.0",
|
||||
"autoprefixer": "^10.4.13",
|
||||
"clsx": "^1.2.1",
|
||||
"concurrently": "^7.4.0",
|
||||
@@ -55,9 +55,5 @@
|
||||
"postcss": "^8.4.31",
|
||||
"tailwindcss": "^3.2.4",
|
||||
"wait-on": "^7.2.0"
|
||||
},
|
||||
"resolutions": {
|
||||
"@types/react": "npm:types-react@19.0.0-rc.1",
|
||||
"@types/react-dom": "npm:types-react-dom@19.0.0-rc.1"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ export default defineConfig({
|
||||
// Test directory
|
||||
testDir: path.join(__dirname, '__tests__/e2e'),
|
||||
// If a test fails, retry it additional 2 times
|
||||
retries: 2,
|
||||
retries: 3,
|
||||
// Artifacts folder where screenshots, videos, and traces are stored.
|
||||
outputDir: 'test-results/',
|
||||
// Note: we only use text snapshots, so its safe to omit the host environment name
|
||||
|
||||
@@ -23,6 +23,15 @@
|
||||
"@babel/highlight" "^7.24.7"
|
||||
picocolors "^1.0.0"
|
||||
|
||||
"@babel/code-frame@^7.26.2":
|
||||
version "7.26.2"
|
||||
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.26.2.tgz#4b5fab97d33338eff916235055f0ebc21e573a85"
|
||||
integrity sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==
|
||||
dependencies:
|
||||
"@babel/helper-validator-identifier" "^7.25.9"
|
||||
js-tokens "^4.0.0"
|
||||
picocolors "^1.0.0"
|
||||
|
||||
"@babel/compat-data@^7.25.2":
|
||||
version "7.25.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.25.4.tgz#7d2a80ce229890edcf4cc259d4d696cb4dae2fcb"
|
||||
@@ -59,6 +68,17 @@
|
||||
"@jridgewell/trace-mapping" "^0.3.25"
|
||||
jsesc "^2.5.1"
|
||||
|
||||
"@babel/generator@^7.26.10":
|
||||
version "7.26.10"
|
||||
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.26.10.tgz#a60d9de49caca16744e6340c3658dfef6138c3f7"
|
||||
integrity sha512-rRHT8siFIXQrAYOYqZQVsAr8vJ+cBNqcVAY6m5V8/4QqzaPl+zDBe6cLEPRDuNOUf3ww8RfJVlOyQMoSI+5Ang==
|
||||
dependencies:
|
||||
"@babel/parser" "^7.26.10"
|
||||
"@babel/types" "^7.26.10"
|
||||
"@jridgewell/gen-mapping" "^0.3.5"
|
||||
"@jridgewell/trace-mapping" "^0.3.25"
|
||||
jsesc "^3.0.2"
|
||||
|
||||
"@babel/helper-annotate-as-pure@^7.24.7":
|
||||
version "7.24.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.7.tgz#5373c7bc8366b12a033b4be1ac13a206c6656aab"
|
||||
@@ -66,6 +86,13 @@
|
||||
dependencies:
|
||||
"@babel/types" "^7.24.7"
|
||||
|
||||
"@babel/helper-annotate-as-pure@^7.25.9":
|
||||
version "7.25.9"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz#d8eac4d2dc0d7b6e11fa6e535332e0d3184f06b4"
|
||||
integrity sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==
|
||||
dependencies:
|
||||
"@babel/types" "^7.25.9"
|
||||
|
||||
"@babel/helper-compilation-targets@^7.25.2":
|
||||
version "7.25.2"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.2.tgz#e1d9410a90974a3a5a66e84ff55ef62e3c02d06c"
|
||||
@@ -77,26 +104,26 @@
|
||||
lru-cache "^5.1.1"
|
||||
semver "^6.3.1"
|
||||
|
||||
"@babel/helper-create-class-features-plugin@^7.25.0":
|
||||
version "7.25.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.25.4.tgz#57eaf1af38be4224a9d9dd01ddde05b741f50e14"
|
||||
integrity sha512-ro/bFs3/84MDgDmMwbcHgDa8/E6J3QKNTk4xJJnVeFtGE+tL0K26E3pNxhYz2b67fJpt7Aphw5XcploKXuCvCQ==
|
||||
"@babel/helper-create-class-features-plugin@^7.25.9":
|
||||
version "7.26.9"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.26.9.tgz#d6f83e3039547fbb39967e78043cd3c8b7820c71"
|
||||
integrity sha512-ubbUqCofvxPRurw5L8WTsCLSkQiVpov4Qx0WMA+jUN+nXBK8ADPlJO1grkFw5CWKC5+sZSOfuGMdX1aI1iT9Sg==
|
||||
dependencies:
|
||||
"@babel/helper-annotate-as-pure" "^7.24.7"
|
||||
"@babel/helper-member-expression-to-functions" "^7.24.8"
|
||||
"@babel/helper-optimise-call-expression" "^7.24.7"
|
||||
"@babel/helper-replace-supers" "^7.25.0"
|
||||
"@babel/helper-skip-transparent-expression-wrappers" "^7.24.7"
|
||||
"@babel/traverse" "^7.25.4"
|
||||
"@babel/helper-annotate-as-pure" "^7.25.9"
|
||||
"@babel/helper-member-expression-to-functions" "^7.25.9"
|
||||
"@babel/helper-optimise-call-expression" "^7.25.9"
|
||||
"@babel/helper-replace-supers" "^7.26.5"
|
||||
"@babel/helper-skip-transparent-expression-wrappers" "^7.25.9"
|
||||
"@babel/traverse" "^7.26.9"
|
||||
semver "^6.3.1"
|
||||
|
||||
"@babel/helper-member-expression-to-functions@^7.24.8":
|
||||
version "7.24.8"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.24.8.tgz#6155e079c913357d24a4c20480db7c712a5c3fb6"
|
||||
integrity sha512-LABppdt+Lp/RlBxqrh4qgf1oEH/WxdzQNDJIu5gC/W1GyvPVrOBiItmmM8wan2fm4oYqFuFfkXmlGpLQhPY8CA==
|
||||
"@babel/helper-member-expression-to-functions@^7.25.9":
|
||||
version "7.25.9"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.25.9.tgz#9dfffe46f727005a5ea29051ac835fb735e4c1a3"
|
||||
integrity sha512-wbfdZ9w5vk0C0oyHqAJbc62+vet5prjj01jjJ8sKn3j9h3MQQlflEdXYvuqRWjHnM12coDEqiC1IRCi0U/EKwQ==
|
||||
dependencies:
|
||||
"@babel/traverse" "^7.24.8"
|
||||
"@babel/types" "^7.24.8"
|
||||
"@babel/traverse" "^7.25.9"
|
||||
"@babel/types" "^7.25.9"
|
||||
|
||||
"@babel/helper-module-imports@^7.24.7":
|
||||
version "7.24.7"
|
||||
@@ -106,6 +133,14 @@
|
||||
"@babel/traverse" "^7.24.7"
|
||||
"@babel/types" "^7.24.7"
|
||||
|
||||
"@babel/helper-module-imports@^7.25.9":
|
||||
version "7.25.9"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz#e7f8d20602ebdbf9ebbea0a0751fb0f2a4141715"
|
||||
integrity sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==
|
||||
dependencies:
|
||||
"@babel/traverse" "^7.25.9"
|
||||
"@babel/types" "^7.25.9"
|
||||
|
||||
"@babel/helper-module-transforms@^7.24.8", "@babel/helper-module-transforms@^7.25.2":
|
||||
version "7.25.2"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.25.2.tgz#ee713c29768100f2776edf04d4eb23b8d27a66e6"
|
||||
@@ -116,26 +151,40 @@
|
||||
"@babel/helper-validator-identifier" "^7.24.7"
|
||||
"@babel/traverse" "^7.25.2"
|
||||
|
||||
"@babel/helper-optimise-call-expression@^7.24.7":
|
||||
version "7.24.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.24.7.tgz#8b0a0456c92f6b323d27cfd00d1d664e76692a0f"
|
||||
integrity sha512-jKiTsW2xmWwxT1ixIdfXUZp+P5yURx2suzLZr5Hi64rURpDYdMW0pv+Uf17EYk2Rd428Lx4tLsnjGJzYKDM/6A==
|
||||
"@babel/helper-module-transforms@^7.26.0":
|
||||
version "7.26.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz#8ce54ec9d592695e58d84cd884b7b5c6a2fdeeae"
|
||||
integrity sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==
|
||||
dependencies:
|
||||
"@babel/types" "^7.24.7"
|
||||
"@babel/helper-module-imports" "^7.25.9"
|
||||
"@babel/helper-validator-identifier" "^7.25.9"
|
||||
"@babel/traverse" "^7.25.9"
|
||||
|
||||
"@babel/helper-optimise-call-expression@^7.25.9":
|
||||
version "7.25.9"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.25.9.tgz#3324ae50bae7e2ab3c33f60c9a877b6a0146b54e"
|
||||
integrity sha512-FIpuNaz5ow8VyrYcnXQTDRGvV6tTjkNtCK/RYNDXGSLlUD6cBuQTSw43CShGxjvfBTfcUA/r6UhUCbtYqkhcuQ==
|
||||
dependencies:
|
||||
"@babel/types" "^7.25.9"
|
||||
|
||||
"@babel/helper-plugin-utils@^7.24.7", "@babel/helper-plugin-utils@^7.24.8":
|
||||
version "7.24.8"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.8.tgz#94ee67e8ec0e5d44ea7baeb51e571bd26af07878"
|
||||
integrity sha512-FFWx5142D8h2Mgr/iPVGH5G7w6jDn4jUSpZTyDnQO0Yn7Ks2Kuz6Pci8H6MPCoUJegd/UZQ3tAvfLCxQSnWWwg==
|
||||
|
||||
"@babel/helper-replace-supers@^7.25.0":
|
||||
version "7.25.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.25.0.tgz#ff44deac1c9f619523fe2ca1fd650773792000a9"
|
||||
integrity sha512-q688zIvQVYtZu+i2PsdIu/uWGRpfxzr5WESsfpShfZECkO+d2o+WROWezCi/Q6kJ0tfPa5+pUGUlfx2HhrA3Bg==
|
||||
"@babel/helper-plugin-utils@^7.25.9", "@babel/helper-plugin-utils@^7.26.5":
|
||||
version "7.26.5"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.26.5.tgz#18580d00c9934117ad719392c4f6585c9333cc35"
|
||||
integrity sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==
|
||||
|
||||
"@babel/helper-replace-supers@^7.26.5":
|
||||
version "7.26.5"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.26.5.tgz#6cb04e82ae291dae8e72335dfe438b0725f14c8d"
|
||||
integrity sha512-bJ6iIVdYX1YooY2X7w1q6VITt+LnUILtNk7zT78ykuwStx8BauCzxvFqFaHjOpW1bVnSUM1PN1f0p5P21wHxvg==
|
||||
dependencies:
|
||||
"@babel/helper-member-expression-to-functions" "^7.24.8"
|
||||
"@babel/helper-optimise-call-expression" "^7.24.7"
|
||||
"@babel/traverse" "^7.25.0"
|
||||
"@babel/helper-member-expression-to-functions" "^7.25.9"
|
||||
"@babel/helper-optimise-call-expression" "^7.25.9"
|
||||
"@babel/traverse" "^7.26.5"
|
||||
|
||||
"@babel/helper-simple-access@^7.24.7":
|
||||
version "7.24.7"
|
||||
@@ -145,29 +194,39 @@
|
||||
"@babel/traverse" "^7.24.7"
|
||||
"@babel/types" "^7.24.7"
|
||||
|
||||
"@babel/helper-skip-transparent-expression-wrappers@^7.24.7":
|
||||
version "7.24.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.24.7.tgz#5f8fa83b69ed5c27adc56044f8be2b3ea96669d9"
|
||||
integrity sha512-IO+DLT3LQUElMbpzlatRASEyQtfhSE0+m465v++3jyyXeBTBUjtVZg28/gHeV5mrTJqvEKhKroBGAvhW+qPHiQ==
|
||||
"@babel/helper-skip-transparent-expression-wrappers@^7.25.9":
|
||||
version "7.25.9"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.25.9.tgz#0b2e1b62d560d6b1954893fd2b705dc17c91f0c9"
|
||||
integrity sha512-K4Du3BFa3gvyhzgPcntrkDgZzQaq6uozzcpGbOO1OEJaI+EJdqWIMTLgFgQf6lrfiDFo5FU+BxKepI9RmZqahA==
|
||||
dependencies:
|
||||
"@babel/traverse" "^7.24.7"
|
||||
"@babel/types" "^7.24.7"
|
||||
"@babel/traverse" "^7.25.9"
|
||||
"@babel/types" "^7.25.9"
|
||||
|
||||
"@babel/helper-string-parser@^7.24.8":
|
||||
version "7.24.8"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz#5b3329c9a58803d5df425e5785865881a81ca48d"
|
||||
integrity sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==
|
||||
"@babel/helper-string-parser@^7.25.9":
|
||||
version "7.25.9"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz#1aabb72ee72ed35789b4bbcad3ca2862ce614e8c"
|
||||
integrity sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==
|
||||
|
||||
"@babel/helper-validator-identifier@^7.18.6", "@babel/helper-validator-identifier@^7.24.7":
|
||||
"@babel/helper-validator-identifier@^7.24.7":
|
||||
version "7.24.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz#75b889cfaf9e35c2aaf42cf0d72c8e91719251db"
|
||||
integrity sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==
|
||||
|
||||
"@babel/helper-validator-identifier@^7.25.9":
|
||||
version "7.25.9"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz#24b64e2c3ec7cd3b3c547729b8d16871f22cbdc7"
|
||||
integrity sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==
|
||||
|
||||
"@babel/helper-validator-option@^7.24.7", "@babel/helper-validator-option@^7.24.8":
|
||||
version "7.24.8"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.24.8.tgz#3725cdeea8b480e86d34df15304806a06975e33d"
|
||||
integrity sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q==
|
||||
|
||||
"@babel/helper-validator-option@^7.25.9":
|
||||
version "7.25.9"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz#86e45bd8a49ab7e03f276577f96179653d41da72"
|
||||
integrity sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==
|
||||
|
||||
"@babel/helpers@^7.25.0":
|
||||
version "7.25.6"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.25.6.tgz#57ee60141829ba2e102f30711ffe3afab357cc60"
|
||||
@@ -193,6 +252,13 @@
|
||||
dependencies:
|
||||
"@babel/types" "^7.25.6"
|
||||
|
||||
"@babel/parser@^7.26.10", "@babel/parser@^7.26.9":
|
||||
version "7.26.10"
|
||||
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.26.10.tgz#e9bdb82f14b97df6569b0b038edd436839c57749"
|
||||
integrity sha512-6aQR2zGE/QFi8JpDLjUZEPYOs7+mhKXm86VaKFiLP35JQwQb6bwUE+XbvkH0EptsYhbNBSUGaUBLKqxH1xSgsA==
|
||||
dependencies:
|
||||
"@babel/types" "^7.26.10"
|
||||
|
||||
"@babel/plugin-syntax-jsx@^7.24.7":
|
||||
version "7.24.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.7.tgz#39a1fa4a7e3d3d7f34e2acc6be585b718d30e02d"
|
||||
@@ -200,13 +266,27 @@
|
||||
dependencies:
|
||||
"@babel/helper-plugin-utils" "^7.24.7"
|
||||
|
||||
"@babel/plugin-syntax-typescript@^7.18.9", "@babel/plugin-syntax-typescript@^7.24.7":
|
||||
"@babel/plugin-syntax-jsx@^7.25.9":
|
||||
version "7.25.9"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.25.9.tgz#a34313a178ea56f1951599b929c1ceacee719290"
|
||||
integrity sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA==
|
||||
dependencies:
|
||||
"@babel/helper-plugin-utils" "^7.25.9"
|
||||
|
||||
"@babel/plugin-syntax-typescript@^7.18.9":
|
||||
version "7.25.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.4.tgz#04db9ce5a9043d9c635e75ae7969a2cd50ca97ff"
|
||||
integrity sha512-uMOCoHVU52BsSWxPOMVv5qKRdeSlPuImUCB2dlPuBSU+W2/ROE7/Zg8F2Kepbk+8yBa68LlRKxO+xgEVWorsDg==
|
||||
dependencies:
|
||||
"@babel/helper-plugin-utils" "^7.24.8"
|
||||
|
||||
"@babel/plugin-syntax-typescript@^7.25.9":
|
||||
version "7.25.9"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.9.tgz#67dda2b74da43727cf21d46cf9afef23f4365399"
|
||||
integrity sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ==
|
||||
dependencies:
|
||||
"@babel/helper-plugin-utils" "^7.25.9"
|
||||
|
||||
"@babel/plugin-transform-block-scoping@^7.18.9":
|
||||
version "7.25.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.25.0.tgz#23a6ed92e6b006d26b1869b1c91d1b917c2ea2ac"
|
||||
@@ -214,7 +294,7 @@
|
||||
dependencies:
|
||||
"@babel/helper-plugin-utils" "^7.24.8"
|
||||
|
||||
"@babel/plugin-transform-modules-commonjs@^7.18.9", "@babel/plugin-transform-modules-commonjs@^7.24.7":
|
||||
"@babel/plugin-transform-modules-commonjs@^7.18.9":
|
||||
version "7.24.8"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.8.tgz#ab6421e564b717cb475d6fff70ae7f103536ea3c"
|
||||
integrity sha512-WHsk9H8XxRs3JXKWFiqtQebdh9b/pTk4EgueygFzYlTKAg0Ud985mSevdNjdXdFBATSKVJGQXP1tv6aGbssLKA==
|
||||
@@ -223,6 +303,14 @@
|
||||
"@babel/helper-plugin-utils" "^7.24.8"
|
||||
"@babel/helper-simple-access" "^7.24.7"
|
||||
|
||||
"@babel/plugin-transform-modules-commonjs@^7.25.9":
|
||||
version "7.26.3"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.26.3.tgz#8f011d44b20d02c3de44d8850d971d8497f981fb"
|
||||
integrity sha512-MgR55l4q9KddUDITEzEFYn5ZsGDXMSsU9E+kh7fjRXTIC3RHqfCo8RPRbyReYJh44HQ/yomFkqbOFohXvDCiIQ==
|
||||
dependencies:
|
||||
"@babel/helper-module-transforms" "^7.26.0"
|
||||
"@babel/helper-plugin-utils" "^7.25.9"
|
||||
|
||||
"@babel/plugin-transform-react-display-name@^7.24.7":
|
||||
version "7.24.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.24.7.tgz#9caff79836803bc666bcfe210aeb6626230c293b"
|
||||
@@ -256,16 +344,16 @@
|
||||
"@babel/helper-annotate-as-pure" "^7.24.7"
|
||||
"@babel/helper-plugin-utils" "^7.24.7"
|
||||
|
||||
"@babel/plugin-transform-typescript@^7.24.7":
|
||||
version "7.25.2"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.25.2.tgz#237c5d10de6d493be31637c6b9fa30b6c5461add"
|
||||
integrity sha512-lBwRvjSmqiMYe/pS0+1gggjJleUJi7NzjvQ1Fkqtt69hBa/0t1YuW/MLQMAPixfwaQOHUXsd6jeU3Z+vdGv3+A==
|
||||
"@babel/plugin-transform-typescript@^7.25.9":
|
||||
version "7.26.8"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.26.8.tgz#2e9caa870aa102f50d7125240d9dbf91334b0950"
|
||||
integrity sha512-bME5J9AC8ChwA7aEPJ6zym3w7aObZULHhbNLU0bKUhKsAkylkzUdq+0kdymh9rzi8nlNFl2bmldFBCKNJBUpuw==
|
||||
dependencies:
|
||||
"@babel/helper-annotate-as-pure" "^7.24.7"
|
||||
"@babel/helper-create-class-features-plugin" "^7.25.0"
|
||||
"@babel/helper-plugin-utils" "^7.24.8"
|
||||
"@babel/helper-skip-transparent-expression-wrappers" "^7.24.7"
|
||||
"@babel/plugin-syntax-typescript" "^7.24.7"
|
||||
"@babel/helper-annotate-as-pure" "^7.25.9"
|
||||
"@babel/helper-create-class-features-plugin" "^7.25.9"
|
||||
"@babel/helper-plugin-utils" "^7.26.5"
|
||||
"@babel/helper-skip-transparent-expression-wrappers" "^7.25.9"
|
||||
"@babel/plugin-syntax-typescript" "^7.25.9"
|
||||
|
||||
"@babel/preset-react@^7.18.9":
|
||||
version "7.24.7"
|
||||
@@ -279,16 +367,16 @@
|
||||
"@babel/plugin-transform-react-jsx-development" "^7.24.7"
|
||||
"@babel/plugin-transform-react-pure-annotations" "^7.24.7"
|
||||
|
||||
"@babel/preset-typescript@^7.18.9":
|
||||
version "7.24.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.24.7.tgz#66cd86ea8f8c014855671d5ea9a737139cbbfef1"
|
||||
integrity sha512-SyXRe3OdWwIwalxDg5UtJnJQO+YPcTfwiIY2B0Xlddh9o7jpWLvv8X1RthIeDOxQ+O1ML5BLPCONToObyVQVuQ==
|
||||
"@babel/preset-typescript@^7.26.0":
|
||||
version "7.26.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.26.0.tgz#4a570f1b8d104a242d923957ffa1eaff142a106d"
|
||||
integrity sha512-NMk1IGZ5I/oHhoXEElcm+xUnL/szL6xflkFZmoEU9xj1qSJXpiS7rsspYo92B4DRCDvZn2erT5LdsCeXAKNCkg==
|
||||
dependencies:
|
||||
"@babel/helper-plugin-utils" "^7.24.7"
|
||||
"@babel/helper-validator-option" "^7.24.7"
|
||||
"@babel/plugin-syntax-jsx" "^7.24.7"
|
||||
"@babel/plugin-transform-modules-commonjs" "^7.24.7"
|
||||
"@babel/plugin-transform-typescript" "^7.24.7"
|
||||
"@babel/helper-plugin-utils" "^7.25.9"
|
||||
"@babel/helper-validator-option" "^7.25.9"
|
||||
"@babel/plugin-syntax-jsx" "^7.25.9"
|
||||
"@babel/plugin-transform-modules-commonjs" "^7.25.9"
|
||||
"@babel/plugin-transform-typescript" "^7.25.9"
|
||||
|
||||
"@babel/runtime@^7.21.0":
|
||||
version "7.25.6"
|
||||
@@ -306,7 +394,16 @@
|
||||
"@babel/parser" "^7.25.0"
|
||||
"@babel/types" "^7.25.0"
|
||||
|
||||
"@babel/traverse@^7.18.9", "@babel/traverse@^7.24.7", "@babel/traverse@^7.24.8", "@babel/traverse@^7.25.0", "@babel/traverse@^7.25.2", "@babel/traverse@^7.25.4":
|
||||
"@babel/template@^7.26.9":
|
||||
version "7.26.9"
|
||||
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.26.9.tgz#4577ad3ddf43d194528cff4e1fa6b232fa609bb2"
|
||||
integrity sha512-qyRplbeIpNZhmzOysF/wFMuP9sctmh2cFzRAZOn1YapxBsE1i9bJIY586R/WBLfLcmcBlM8ROBiQURnnNy+zfA==
|
||||
dependencies:
|
||||
"@babel/code-frame" "^7.26.2"
|
||||
"@babel/parser" "^7.26.9"
|
||||
"@babel/types" "^7.26.9"
|
||||
|
||||
"@babel/traverse@^7.18.9", "@babel/traverse@^7.24.7", "@babel/traverse@^7.25.2":
|
||||
version "7.25.6"
|
||||
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.25.6.tgz#04fad980e444f182ecf1520504941940a90fea41"
|
||||
integrity sha512-9Vrcx5ZW6UwK5tvqsj0nGpp/XzqthkT0dqIc9g1AdtygFToNtTF67XzYS//dm+SAK9cp3B9R4ZO/46p63SCjlQ==
|
||||
@@ -319,22 +416,34 @@
|
||||
debug "^4.3.1"
|
||||
globals "^11.1.0"
|
||||
|
||||
"@babel/types@7.18.9":
|
||||
version "7.18.9"
|
||||
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.18.9.tgz#7148d64ba133d8d73a41b3172ac4b83a1452205f"
|
||||
integrity sha512-WwMLAg2MvJmt/rKEVQBBhIVffMmnilX4oe0sRe7iPOHIGsqpruFHHdrfj4O1CMMtgMtCU4oPafZjDPCRgO57Wg==
|
||||
"@babel/traverse@^7.25.9", "@babel/traverse@^7.26.5", "@babel/traverse@^7.26.9":
|
||||
version "7.26.10"
|
||||
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.26.10.tgz#43cca33d76005dbaa93024fae536cc1946a4c380"
|
||||
integrity sha512-k8NuDrxr0WrPH5Aupqb2LCVURP/S0vBEn5mK6iH+GIYob66U5EtoZvcdudR2jQ4cmTwhEwW1DLB+Yyas9zjF6A==
|
||||
dependencies:
|
||||
"@babel/helper-validator-identifier" "^7.18.6"
|
||||
to-fast-properties "^2.0.0"
|
||||
"@babel/code-frame" "^7.26.2"
|
||||
"@babel/generator" "^7.26.10"
|
||||
"@babel/parser" "^7.26.10"
|
||||
"@babel/template" "^7.26.9"
|
||||
"@babel/types" "^7.26.10"
|
||||
debug "^4.3.1"
|
||||
globals "^11.1.0"
|
||||
|
||||
"@babel/types@^7.24.7", "@babel/types@^7.24.8", "@babel/types@^7.25.0", "@babel/types@^7.25.2", "@babel/types@^7.25.6":
|
||||
version "7.25.6"
|
||||
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.25.6.tgz#893942ddb858f32ae7a004ec9d3a76b3463ef8e6"
|
||||
integrity sha512-/l42B1qxpG6RdfYf343Uw1vmDjeNhneUXtzhojE7pDgfpEypmRhI6j1kr17XCVv4Cgl9HdAiQY2x0GwKm7rWCw==
|
||||
"@babel/types@7.26.3", "@babel/types@^7.24.7", "@babel/types@^7.25.0", "@babel/types@^7.25.2", "@babel/types@^7.25.6":
|
||||
version "7.26.3"
|
||||
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.26.3.tgz#37e79830f04c2b5687acc77db97fbc75fb81f3c0"
|
||||
integrity sha512-vN5p+1kl59GVKMvTHt55NzzmYVxprfJD+ql7U9NFIfKCBkYE55LYtS+WtPlaYOyzydrKI8Nezd+aZextrd+FMA==
|
||||
dependencies:
|
||||
"@babel/helper-string-parser" "^7.24.8"
|
||||
"@babel/helper-validator-identifier" "^7.24.7"
|
||||
to-fast-properties "^2.0.0"
|
||||
"@babel/helper-string-parser" "^7.25.9"
|
||||
"@babel/helper-validator-identifier" "^7.25.9"
|
||||
|
||||
"@babel/types@^7.25.9", "@babel/types@^7.26.10", "@babel/types@^7.26.9":
|
||||
version "7.26.10"
|
||||
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.26.10.tgz#396382f6335bd4feb65741eacfc808218f859259"
|
||||
integrity sha512-emqcG3vHrpxUKTrxcblR36dcrcoRDvKmnL/dCL6ZsHaShW80qxCAcNhzQZrpeM765VzEos+xOi4s+r4IXzTwdQ==
|
||||
dependencies:
|
||||
"@babel/helper-string-parser" "^7.25.9"
|
||||
"@babel/helper-validator-identifier" "^7.25.9"
|
||||
|
||||
"@emnapi/runtime@^1.2.0":
|
||||
version "1.3.1"
|
||||
@@ -589,10 +698,10 @@
|
||||
dependencies:
|
||||
"@monaco-editor/loader" "^1.4.0"
|
||||
|
||||
"@next/env@15.0.1":
|
||||
version "15.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@next/env/-/env-15.0.1.tgz#660fe9303e255cec112d3f4198d2897a24bc60b3"
|
||||
integrity sha512-lc4HeDUKO9gxxlM5G2knTRifqhsY6yYpwuHspBZdboZe0Gp+rZHBNNSIjmQKDJIdRXiXGyVnSD6gafrbQPvILQ==
|
||||
"@next/env@15.2.0-canary.66":
|
||||
version "15.2.0-canary.66"
|
||||
resolved "https://registry.yarnpkg.com/@next/env/-/env-15.2.0-canary.66.tgz#c4ca0d502ad099c68927643df9c9b5d75c7b7fbb"
|
||||
integrity sha512-/RxW1GJ7a6MJOQ7LOa2bcli7VTjqB7jPyzXwNJQflcYJH4gz1kP6uzg8+IptLJGFSRB58RBKHJk+q1cD8jongA==
|
||||
|
||||
"@next/eslint-plugin-next@15.0.1":
|
||||
version "15.0.1"
|
||||
@@ -601,45 +710,45 @@
|
||||
dependencies:
|
||||
fast-glob "3.3.1"
|
||||
|
||||
"@next/swc-darwin-arm64@15.0.1":
|
||||
version "15.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.0.1.tgz#b80a25f1569bd0ca03eca9473f7e93e64937e404"
|
||||
integrity sha512-C9k/Xv4sxkQRTA37Z6MzNq3Yb1BJMmSqjmwowoWEpbXTkAdfOwnoKOpAb71ItSzoA26yUTIo6ZhN8rKGu4ExQw==
|
||||
"@next/swc-darwin-arm64@15.2.0-canary.66":
|
||||
version "15.2.0-canary.66"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.2.0-canary.66.tgz#368438cf713c439b5b4c44d54b5c3b31ee5b772d"
|
||||
integrity sha512-sVzNJWTekcLOdqkDMistBGr84AVh9eSu4o5JQNEOdxHry4jiF8lqixpOg0+Twj2RRuv4bx32h5xaRVvCSUpITQ==
|
||||
|
||||
"@next/swc-darwin-x64@15.0.1":
|
||||
version "15.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-15.0.1.tgz#00dcf79ec7c638a85c3b9ff2e2de2bfb09c1c250"
|
||||
integrity sha512-uHl13HXOuq1G7ovWFxCACDJHTSDVbn/sbLv8V1p+7KIvTrYQ5HNoSmKBdYeEKRRCbEmd+OohOgg9YOp8Ux3MBg==
|
||||
"@next/swc-darwin-x64@15.2.0-canary.66":
|
||||
version "15.2.0-canary.66"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-15.2.0-canary.66.tgz#3ddc3f4f6e86e204727770e5984cabf52f852472"
|
||||
integrity sha512-Avv6Nf/0j0WVqY72Q0mK2glGhvN7LT7iVF31iBYUe/Cbf2cXBjgpXUVmksJjg+2Fi6uTEpaMoZWSVEpJyPkjVQ==
|
||||
|
||||
"@next/swc-linux-arm64-gnu@15.0.1":
|
||||
version "15.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.0.1.tgz#faab5f7ffcc6d1a15e8dea1cb9953966658b39bf"
|
||||
integrity sha512-LvyhvxHOihFTEIbb35KxOc3q8w8G4xAAAH/AQnsYDEnOvwawjL2eawsB59AX02ki6LJdgDaHoTEnC54Gw+82xw==
|
||||
"@next/swc-linux-arm64-gnu@15.2.0-canary.66":
|
||||
version "15.2.0-canary.66"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.2.0-canary.66.tgz#cd3683bf569c66444340b1e4d876913584e93aea"
|
||||
integrity sha512-kUPejaStjKpF79fz4525DKQKADtUuE+T6j7IvLQsZuWrSX3a5Mix+i52fdTzMJ+sFGg3v147wopZt6L6JMIxxA==
|
||||
|
||||
"@next/swc-linux-arm64-musl@15.0.1":
|
||||
version "15.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.0.1.tgz#97abada9a782ab5b3cb42cf0d4799cbc2e733351"
|
||||
integrity sha512-vFmCGUFNyk/A5/BYcQNhAQqPIw01RJaK6dRO+ZEhz0DncoW+hJW1kZ8aH2UvTX27zPq3m85zN5waMSbZEmANcQ==
|
||||
"@next/swc-linux-arm64-musl@15.2.0-canary.66":
|
||||
version "15.2.0-canary.66"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.2.0-canary.66.tgz#453836b11efdb50b91cf8a6cfbce8779f6778dd9"
|
||||
integrity sha512-U8l8jaZ+BAU5wn3bw7PRqq4vGTpObBt+7JbJLpbDqB1GfkZdCDc4nGtqAfLy3pY0O4lEfqal9jrsEVtUBCbfHg==
|
||||
|
||||
"@next/swc-linux-x64-gnu@15.0.1":
|
||||
version "15.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.0.1.tgz#548bd47c49fe6d819302139aff8766eb704322e2"
|
||||
integrity sha512-5by7IYq0NCF8rouz6Qg9T97jYU68kaClHPfGpQG2lCZpSYHtSPQF1kjnqBTd34RIqPKMbCa4DqCufirgr8HM5w==
|
||||
"@next/swc-linux-x64-gnu@15.2.0-canary.66":
|
||||
version "15.2.0-canary.66"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.2.0-canary.66.tgz#f02b295febaacf8d041f9f149c30c41aea16a81f"
|
||||
integrity sha512-c+AV8ZN1znGBHu5BACGym+9FhV8+213XVHFI7i2J7TSsJ6T+Eofhwn0tSn1Vy/XpVmpyoEdkwepL+djbdQAGhw==
|
||||
|
||||
"@next/swc-linux-x64-musl@15.0.1":
|
||||
version "15.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.0.1.tgz#84423fbd3a058dd6ae8322e530878f0ec7a1027a"
|
||||
integrity sha512-lmYr6H3JyDNBJLzklGXLfbehU3ay78a+b6UmBGlHls4xhDXBNZfgb0aI67sflrX+cGBnv1LgmWzFlYrAYxS1Qw==
|
||||
"@next/swc-linux-x64-musl@15.2.0-canary.66":
|
||||
version "15.2.0-canary.66"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.2.0-canary.66.tgz#f942c000ba3ffc0289520d25fa1067a75e72fa41"
|
||||
integrity sha512-4mTIv86qyXuo8NfjigSQ7rk2cDwM8/f8R/kf3hNh8NF1Aaat2RrEet9a/SbsuNpdhhNnPI5RcRwpIJx2JQSPcQ==
|
||||
|
||||
"@next/swc-win32-arm64-msvc@15.0.1":
|
||||
version "15.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.0.1.tgz#723c2ced12a998fb40dc901b8faea9170e788c2f"
|
||||
integrity sha512-DS8wQtl6diAj0eZTdH0sefykm4iXMbHT4MOvLwqZiIkeezKpkgPFcEdFlz3vKvXa2R/2UEgMh48z1nEpNhjeOQ==
|
||||
"@next/swc-win32-arm64-msvc@15.2.0-canary.66":
|
||||
version "15.2.0-canary.66"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.2.0-canary.66.tgz#0ffdcf5c74b5aa6214307f2ae4aa84f1526e6bf9"
|
||||
integrity sha512-NPnfsDQXk44h8VtncWq2AgLjHDbUMsc8Tpz7pcLe9qb8lZSxZ9jYbV7NwKzgd+qJbjy/58vgCWhL5PhyXDlWwQ==
|
||||
|
||||
"@next/swc-win32-x64-msvc@15.0.1":
|
||||
version "15.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.0.1.tgz#ec7e3befc0bcc47527537b1eda2b3745beb15a09"
|
||||
integrity sha512-4Ho2ggvDdMKlZ/0e9HNdZ9ngeaBwtc+2VS5oCeqrbXqOgutX6I4U2X/42VBw0o+M5evn4/7v3zKgGHo+9v/VjA==
|
||||
"@next/swc-win32-x64-msvc@15.2.0-canary.66":
|
||||
version "15.2.0-canary.66"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.2.0-canary.66.tgz#458245850cf407d2551155e4662785c109f58bda"
|
||||
integrity sha512-L/ef++GJqW+T3g2x6mrZ2vrBK+6QS9Ieam8EqK9dG7cFKv7Gqm9yrHvDuVse62hnNB11ZdxfDDKrs9vabuQLlw==
|
||||
|
||||
"@nodelib/fs.scandir@2.1.5":
|
||||
version "2.1.5"
|
||||
@@ -716,12 +825,12 @@
|
||||
resolved "https://registry.yarnpkg.com/@swc/counter/-/counter-0.1.3.tgz#cc7463bd02949611c6329596fccd2b0ec782b0e9"
|
||||
integrity sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==
|
||||
|
||||
"@swc/helpers@0.5.13":
|
||||
version "0.5.13"
|
||||
resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.5.13.tgz#33e63ff3cd0cade557672bd7888a39ce7d115a8c"
|
||||
integrity sha512-UoKGxQ3r5kYI9dALKJapMmuK+1zWM/H17Z1+iwnNmzcJRnfFuevZs375TA5rW31pu4BS4NoSy1fRsexDXfWn5w==
|
||||
"@swc/helpers@0.5.15":
|
||||
version "0.5.15"
|
||||
resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.5.15.tgz#79efab344c5819ecf83a43f3f9f811fc84b516d7"
|
||||
integrity sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==
|
||||
dependencies:
|
||||
tslib "^2.4.0"
|
||||
tslib "^2.8.0"
|
||||
|
||||
"@types/json5@^0.0.29":
|
||||
version "0.0.29"
|
||||
@@ -733,17 +842,15 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-18.11.9.tgz#02d013de7058cea16d36168ef2fc653464cfbad4"
|
||||
integrity sha512-CRpX21/kGdzjOpFsZSkcrXMGIBWMGNIHXXBVFSH+ggkftxg+XYP20TESbh+zFvFj3EQOl5byk0HTRn1IL6hbqg==
|
||||
|
||||
"@types/react-dom@npm:types-react-dom@19.0.0-rc.1":
|
||||
version "19.0.0-rc.1"
|
||||
resolved "https://registry.yarnpkg.com/types-react-dom/-/types-react-dom-19.0.0-rc.1.tgz#1d544d02c5df2a82d87c2eff979afa2e21a8317a"
|
||||
integrity sha512-VSLZJl8VXCD0fAWp7DUTFUDCcZ8DVXOQmjhJMD03odgeFmu14ZQJHCXeETm3BEAhJqfgJaFkLnGkQv88sRx0fQ==
|
||||
dependencies:
|
||||
"@types/react" "*"
|
||||
"@types/react-dom@^19.0.0":
|
||||
version "19.0.4"
|
||||
resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-19.0.4.tgz#bedba97f9346bd4c0fe5d39e689713804ec9ac89"
|
||||
integrity sha512-4fSQ8vWFkg+TGhePfUzVmat3eC14TXYSsiiDSLI0dVLsrm9gZFABjPy/Qu6TKgl1tq1Bu1yDsuQgY3A3DOjCcg==
|
||||
|
||||
"@types/react@*", "@types/react@npm:types-react@19.0.0-rc.1":
|
||||
version "19.0.0-rc.1"
|
||||
resolved "https://registry.yarnpkg.com/types-react/-/types-react-19.0.0-rc.1.tgz#576d1a702f6d0cc5b24813a293913e5cbfeaa647"
|
||||
integrity sha512-RshndUfqTW6K3STLPis8BtAYCGOkMbtvYsi90gmVNDZBXUyUc5juf2PE9LfS/JmOlUIRO8cWTS/1MTnmhjDqyQ==
|
||||
"@types/react@^19.0.0":
|
||||
version "19.0.10"
|
||||
resolved "https://registry.yarnpkg.com/@types/react/-/react-19.0.10.tgz#d0c66dafd862474190fe95ce11a68de69ed2b0eb"
|
||||
integrity sha512-JuRQ9KXLEjaUNjTWpzuR231Z2WpIwczOkBEIvbHNCzQefFIT0L8IqE6NV6ULLyC1SI/i234JnDoMkfg+RjQj2g==
|
||||
dependencies:
|
||||
csstype "^3.0.2"
|
||||
|
||||
@@ -2468,6 +2575,11 @@ jsesc@^2.5.1:
|
||||
resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4"
|
||||
integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==
|
||||
|
||||
jsesc@^3.0.2:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-3.1.0.tgz#74d335a234f67ed19907fdadfac7ccf9d409825d"
|
||||
integrity sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==
|
||||
|
||||
json-buffer@3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13"
|
||||
@@ -2682,27 +2794,27 @@ natural-compare@^1.4.0:
|
||||
resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
|
||||
integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==
|
||||
|
||||
next@^15.0.1:
|
||||
version "15.0.1"
|
||||
resolved "https://registry.yarnpkg.com/next/-/next-15.0.1.tgz#a0e8eda35d803cb7f8092b2a2eb9d072e22bf21d"
|
||||
integrity sha512-PSkFkr/w7UnFWm+EP8y/QpHrJXMqpZzAXpergB/EqLPOh4SGPJXv1wj4mslr2hUZBAS9pX7/9YLIdxTv6fwytw==
|
||||
next@^15.2.0-canary.64:
|
||||
version "15.2.0-canary.66"
|
||||
resolved "https://registry.yarnpkg.com/next/-/next-15.2.0-canary.66.tgz#cb5ee4453c88f247b6e74fe33fd181eca58e7c86"
|
||||
integrity sha512-S+gsEu8vxxejI7nKqtCLqZlTi9L40xelLRK/Fgtvm/XT8W8ziLp3KMtN4I9Si5nEMU5uv7bllIfd04kVX8+HIw==
|
||||
dependencies:
|
||||
"@next/env" "15.0.1"
|
||||
"@next/env" "15.2.0-canary.66"
|
||||
"@swc/counter" "0.1.3"
|
||||
"@swc/helpers" "0.5.13"
|
||||
"@swc/helpers" "0.5.15"
|
||||
busboy "1.6.0"
|
||||
caniuse-lite "^1.0.30001579"
|
||||
postcss "8.4.31"
|
||||
styled-jsx "5.1.6"
|
||||
optionalDependencies:
|
||||
"@next/swc-darwin-arm64" "15.0.1"
|
||||
"@next/swc-darwin-x64" "15.0.1"
|
||||
"@next/swc-linux-arm64-gnu" "15.0.1"
|
||||
"@next/swc-linux-arm64-musl" "15.0.1"
|
||||
"@next/swc-linux-x64-gnu" "15.0.1"
|
||||
"@next/swc-linux-x64-musl" "15.0.1"
|
||||
"@next/swc-win32-arm64-msvc" "15.0.1"
|
||||
"@next/swc-win32-x64-msvc" "15.0.1"
|
||||
"@next/swc-darwin-arm64" "15.2.0-canary.66"
|
||||
"@next/swc-darwin-x64" "15.2.0-canary.66"
|
||||
"@next/swc-linux-arm64-gnu" "15.2.0-canary.66"
|
||||
"@next/swc-linux-arm64-musl" "15.2.0-canary.66"
|
||||
"@next/swc-linux-x64-gnu" "15.2.0-canary.66"
|
||||
"@next/swc-linux-x64-musl" "15.2.0-canary.66"
|
||||
"@next/swc-win32-arm64-msvc" "15.2.0-canary.66"
|
||||
"@next/swc-win32-x64-msvc" "15.2.0-canary.66"
|
||||
sharp "^0.33.5"
|
||||
|
||||
node-releases@^2.0.18:
|
||||
@@ -3025,12 +3137,12 @@ re-resizable@^6.9.16:
|
||||
resolved "https://registry.yarnpkg.com/re-resizable/-/re-resizable-6.10.0.tgz#d684a096ab438f1a93f59ad3a580a206b0ce31ee"
|
||||
integrity sha512-hysSK0xmA5nz24HBVztlk4yCqCLCvS32E6ZpWxVKop9x3tqCa4yAj1++facrmkOf62JsJHjmjABdKxXofYioCw==
|
||||
|
||||
react-dom@19.0.0-rc-77b637d6-20241016:
|
||||
version "19.0.0-rc-77b637d6-20241016"
|
||||
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-19.0.0-rc-77b637d6-20241016.tgz#71afcba4abbd81a73e85086029202423cf85355e"
|
||||
integrity sha512-xp5LvY+O6uvg0fNbSMyMXe0kbgzw6qn0mbqrdXStm4LBpFeMswLZ+XSNr+eJ0HyIiWrCw0rrXaVdqOxc9wtdKA==
|
||||
react-dom@^19.0.0:
|
||||
version "19.0.0"
|
||||
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-19.0.0.tgz#43446f1f01c65a4cd7f7588083e686a6726cfb57"
|
||||
integrity sha512-4GV5sHFG0e/0AD4X+ySy6UJd3jVl1iNsNHdpad0qhABJ11twS3TTBnseqsKurKcsNqCEFeGL3uLpVChpIO3QfQ==
|
||||
dependencies:
|
||||
scheduler "0.25.0-rc-77b637d6-20241016"
|
||||
scheduler "^0.25.0"
|
||||
|
||||
react-is@^16.13.1:
|
||||
version "16.13.1"
|
||||
@@ -3042,10 +3154,10 @@ react-is@^18.0.0:
|
||||
resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.3.1.tgz#e83557dc12eae63a99e003a46388b1dcbb44db7e"
|
||||
integrity sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==
|
||||
|
||||
react@19.0.0-rc-77b637d6-20241016:
|
||||
version "19.0.0-rc-77b637d6-20241016"
|
||||
resolved "https://registry.yarnpkg.com/react/-/react-19.0.0-rc-77b637d6-20241016.tgz#9e20f116d0195979f192537e00a0fa1687680319"
|
||||
integrity sha512-9A+i+PGSH/P4MezU4w38K9cbJuy0pzsXoPjPWIv6TQGCFmc5qCzC+8yce8dzfSEF1KJgCF2CLc5qtq/ePfiVqg==
|
||||
react@^19.0.0:
|
||||
version "19.0.0"
|
||||
resolved "https://registry.yarnpkg.com/react/-/react-19.0.0.tgz#6e1969251b9f108870aa4bff37a0ce9ddfaaabdd"
|
||||
integrity sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ==
|
||||
|
||||
read-cache@^1.0.0:
|
||||
version "1.0.0"
|
||||
@@ -3167,10 +3279,10 @@ safe-regex-test@^1.0.3:
|
||||
es-errors "^1.3.0"
|
||||
is-regex "^1.1.4"
|
||||
|
||||
scheduler@0.25.0-rc-77b637d6-20241016:
|
||||
version "0.25.0-rc-77b637d6-20241016"
|
||||
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.25.0-rc-77b637d6-20241016.tgz#ab8f8d1cccc9668946caaa1103acdcdb5c871122"
|
||||
integrity sha512-R5NTrZXJaW4Dj2jHmad2MTehpFq4yUQOxRKDNV7clP1q4Pz6RtUIcofdPnGUWM0krlJAw8DHd/4jT41pFK4iEg==
|
||||
scheduler@^0.25.0:
|
||||
version "0.25.0"
|
||||
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.25.0.tgz#336cd9768e8cceebf52d3c80e3dcf5de23e7e015"
|
||||
integrity sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA==
|
||||
|
||||
semver@^6.3.1:
|
||||
version "6.3.1"
|
||||
@@ -3517,11 +3629,6 @@ thenify-all@^1.0.0:
|
||||
dependencies:
|
||||
any-promise "^1.0.0"
|
||||
|
||||
to-fast-properties@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e"
|
||||
integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==
|
||||
|
||||
to-regex-range@^5.0.1:
|
||||
version "5.0.1"
|
||||
resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4"
|
||||
@@ -3559,6 +3666,11 @@ tslib@^2.1.0, tslib@^2.4.0:
|
||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.7.0.tgz#d9b40c5c40ab59e8738f297df3087bf1a2690c01"
|
||||
integrity sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==
|
||||
|
||||
tslib@^2.8.0:
|
||||
version "2.8.1"
|
||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f"
|
||||
integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==
|
||||
|
||||
type-check@^0.4.0, type-check@~0.4.0:
|
||||
version "0.4.0"
|
||||
resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1"
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
[package]
|
||||
name = "react_build_hir"
|
||||
version = "0.1.0"
|
||||
publish = false
|
||||
authors.workspace = true
|
||||
description.workspace = true
|
||||
edition.workspace = true
|
||||
homepage.workspace = true
|
||||
keywords.workspace = true
|
||||
license.workspace = true
|
||||
repository.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
react_hir = { workspace = true }
|
||||
react_estree = { workspace = true}
|
||||
indexmap = { workspace = true }
|
||||
react_diagnostics = { workspace = true }
|
||||
react_semantic_analysis = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
@@ -1,3 +0,0 @@
|
||||
# Build-HIR
|
||||
|
||||
This crate converts from `react_estree` into React Compiler's HIR format as the first phase of compilation.
|
||||
@@ -1,746 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
use std::collections::HashSet;
|
||||
|
||||
use react_diagnostics::Diagnostic;
|
||||
use react_estree::{
|
||||
AssignmentPropertyOrRestElement, AssignmentTarget, BlockStatement, Expression,
|
||||
ExpressionOrSpread, ExpressionOrSuper, ForInit, Function, IntoFunction, JsValue, Pattern,
|
||||
Statement, VariableDeclaration, VariableDeclarationKind,
|
||||
};
|
||||
use react_hir::{
|
||||
ArrayDestructureItem, BlockKind, BranchTerminal, Destructure, DestructurePattern, Environment,
|
||||
ForTerminal, GotoKind, Identifier, IdentifierOperand, InstructionKind, InstructionValue,
|
||||
JSXAttribute, JSXElement, LValue, LoadGlobal, LoadLocal, ObjectDestructureItem,
|
||||
ObjectDestructureProperty, PlaceOrSpread, TerminalValue,
|
||||
};
|
||||
|
||||
use crate::builder::{Builder, LoopScope};
|
||||
use crate::context::get_context_identifiers;
|
||||
use crate::error::BuildHIRError;
|
||||
|
||||
/// Converts a React function in ESTree format into HIR. Returns the HIR
|
||||
/// if it was constructed sucessfully, otherwise a list of diagnostics
|
||||
/// if the input could be not be converted to HIR.
|
||||
///
|
||||
/// Failures generally include nonsensical input (`delete 1`) or syntax
|
||||
/// that is not yet supported.
|
||||
pub fn build(env: &Environment, fun: &Function) -> Result<Box<react_hir::Function>, Diagnostic> {
|
||||
let mut builder = Builder::new(env);
|
||||
|
||||
let mut params = Vec::with_capacity(fun.params.len());
|
||||
for param in &fun.params {
|
||||
match param {
|
||||
Pattern::Identifier(param) => {
|
||||
let identifier = lower_identifier_for_assignment(
|
||||
env,
|
||||
&mut builder,
|
||||
InstructionKind::Let,
|
||||
param,
|
||||
)?;
|
||||
params.push(identifier);
|
||||
}
|
||||
_ => {
|
||||
return Err(Diagnostic::todo(
|
||||
"Support non-identifier params",
|
||||
param.range(),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
match &fun.body {
|
||||
Some(react_estree::FunctionBody::BlockStatement(body)) => {
|
||||
lower_block_statement(env, &mut builder, body)?
|
||||
}
|
||||
Some(react_estree::FunctionBody::Expression(body)) => {
|
||||
lower_expression(env, &mut builder, body)?;
|
||||
}
|
||||
None => {
|
||||
return Err(Diagnostic::invalid_syntax(
|
||||
BuildHIRError::EmptyFunction,
|
||||
fun.range,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
// In case the function did not explicitly return, terminate the final
|
||||
// block with an explicit `return undefined`. If the function *did* return,
|
||||
// this will be unreachable and get pruned later.
|
||||
let implicit_return_value = builder.push(InstructionValue::Primitive(react_hir::Primitive {
|
||||
value: JsValue::Undefined,
|
||||
}));
|
||||
builder.terminate(
|
||||
TerminalValue::Return(react_hir::ReturnTerminal {
|
||||
value: implicit_return_value,
|
||||
}),
|
||||
react_hir::BlockKind::Block,
|
||||
);
|
||||
|
||||
let body = builder.build()?;
|
||||
Ok(Box::new(react_hir::Function {
|
||||
id: fun.id.as_ref().map(|id| id.name.clone()),
|
||||
body,
|
||||
params,
|
||||
// TODO: populate context!
|
||||
context: Default::default(),
|
||||
is_async: fun.is_async,
|
||||
is_generator: fun.is_generator,
|
||||
}))
|
||||
}
|
||||
|
||||
fn lower_block_statement(
|
||||
env: &Environment,
|
||||
builder: &mut Builder,
|
||||
stmt: &BlockStatement,
|
||||
) -> Result<(), Diagnostic> {
|
||||
for stmt in &stmt.body {
|
||||
lower_statement(env, builder, stmt, None)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Convert a statement to HIR. This will often result in multiple instructions and blocks
|
||||
/// being created as statements often describe control flow.
|
||||
fn lower_statement(
|
||||
env: &Environment,
|
||||
builder: &mut Builder,
|
||||
stmt: &Statement,
|
||||
label: Option<String>,
|
||||
) -> Result<(), Diagnostic> {
|
||||
match stmt {
|
||||
Statement::BlockStatement(stmt) => {
|
||||
lower_block_statement(env, builder, stmt)?;
|
||||
}
|
||||
Statement::BreakStatement(stmt) => {
|
||||
let block = builder.resolve_break(stmt.label.as_ref())?;
|
||||
builder.terminate(
|
||||
TerminalValue::Goto(react_hir::GotoTerminal {
|
||||
block,
|
||||
kind: GotoKind::Break,
|
||||
}),
|
||||
BlockKind::Block,
|
||||
);
|
||||
}
|
||||
Statement::ContinueStatement(stmt) => {
|
||||
let block = builder.resolve_continue(stmt.label.as_ref())?;
|
||||
builder.terminate(
|
||||
TerminalValue::Goto(react_hir::GotoTerminal {
|
||||
block,
|
||||
kind: GotoKind::Continue,
|
||||
}),
|
||||
BlockKind::Block,
|
||||
);
|
||||
}
|
||||
Statement::ReturnStatement(stmt) => {
|
||||
let value = match &stmt.argument {
|
||||
Some(argument) => lower_expression(env, builder, argument)?,
|
||||
None => builder.push(InstructionValue::Primitive(react_hir::Primitive {
|
||||
value: JsValue::Undefined,
|
||||
})),
|
||||
};
|
||||
builder.terminate(
|
||||
TerminalValue::Return(react_hir::ReturnTerminal { value }),
|
||||
BlockKind::Block,
|
||||
);
|
||||
}
|
||||
Statement::ExpressionStatement(stmt) => {
|
||||
lower_expression(env, builder, &stmt.expression)?;
|
||||
}
|
||||
Statement::EmptyStatement(_) => {
|
||||
// no-op
|
||||
}
|
||||
Statement::VariableDeclaration(stmt) => {
|
||||
lower_variable_declaration(env, builder, stmt)?;
|
||||
}
|
||||
Statement::IfStatement(stmt) => {
|
||||
// block for what follows the if statement, though this may
|
||||
// not be reachable
|
||||
let fallthrough_block = builder.reserve(BlockKind::Block);
|
||||
|
||||
let consequent_block = builder.enter(BlockKind::Block, |builder| {
|
||||
lower_statement(env, builder, &stmt.consequent, None)?;
|
||||
Ok(TerminalValue::Goto(react_hir::GotoTerminal {
|
||||
block: fallthrough_block.id,
|
||||
kind: GotoKind::Break,
|
||||
}))
|
||||
})?;
|
||||
|
||||
let alternate_block = builder.enter(BlockKind::Block, |builder| {
|
||||
if let Some(alternate) = &stmt.alternate {
|
||||
lower_statement(env, builder, alternate, None)?;
|
||||
}
|
||||
Ok(TerminalValue::Goto(react_hir::GotoTerminal {
|
||||
block: fallthrough_block.id,
|
||||
kind: GotoKind::Break,
|
||||
}))
|
||||
})?;
|
||||
|
||||
let test = lower_expression(env, builder, &stmt.test)?;
|
||||
let terminal = TerminalValue::If(react_hir::IfTerminal {
|
||||
test,
|
||||
consequent: consequent_block,
|
||||
alternate: alternate_block,
|
||||
fallthrough: Some(fallthrough_block.id),
|
||||
});
|
||||
builder.terminate_with_fallthrough(terminal, fallthrough_block);
|
||||
}
|
||||
Statement::ForStatement(stmt) => {
|
||||
// Block for the loop's test condition
|
||||
let test_block = builder.reserve(BlockKind::Loop);
|
||||
|
||||
// Block for code following the loop
|
||||
let fallthrough_block = builder.reserve(BlockKind::Block);
|
||||
|
||||
let init_block = builder.enter(BlockKind::Loop, |builder| {
|
||||
if let Some(ForInit::VariableDeclaration(decl)) = &stmt.init {
|
||||
lower_variable_declaration(env, builder, decl)?;
|
||||
Ok(TerminalValue::Goto(react_hir::GotoTerminal {
|
||||
block: test_block.id,
|
||||
kind: GotoKind::Break,
|
||||
}))
|
||||
} else {
|
||||
Err(Diagnostic::todo(
|
||||
BuildHIRError::ForStatementIsMissingInitializer,
|
||||
None,
|
||||
))
|
||||
}
|
||||
})?;
|
||||
|
||||
let update_block = stmt
|
||||
.update
|
||||
.as_ref()
|
||||
.map(|update| {
|
||||
builder.enter(BlockKind::Loop, |builder| {
|
||||
lower_expression(env, builder, update)?;
|
||||
Ok(TerminalValue::Goto(react_hir::GotoTerminal {
|
||||
block: test_block.id,
|
||||
kind: GotoKind::Break,
|
||||
}))
|
||||
})
|
||||
})
|
||||
.transpose()?;
|
||||
|
||||
let body_block = builder.enter(BlockKind::Block, |builder| {
|
||||
let loop_ = LoopScope {
|
||||
label,
|
||||
continue_block: update_block.unwrap_or(test_block.id),
|
||||
break_block: fallthrough_block.id,
|
||||
};
|
||||
builder.enter_loop(loop_, |builder| {
|
||||
lower_statement(env, builder, &stmt.body, None)?;
|
||||
Ok(TerminalValue::Goto(react_hir::GotoTerminal {
|
||||
block: update_block.unwrap_or(test_block.id),
|
||||
kind: GotoKind::Continue,
|
||||
}))
|
||||
})
|
||||
})?;
|
||||
|
||||
let terminal = TerminalValue::For(ForTerminal {
|
||||
body: body_block,
|
||||
init: init_block,
|
||||
test: test_block.id,
|
||||
fallthrough: fallthrough_block.id,
|
||||
update: update_block,
|
||||
});
|
||||
builder.terminate_with_fallthrough(terminal, test_block);
|
||||
|
||||
if let Some(test) = &stmt.test {
|
||||
let test_value = lower_expression(env, builder, test)?;
|
||||
let terminal = TerminalValue::Branch(BranchTerminal {
|
||||
test: test_value,
|
||||
consequent: body_block,
|
||||
alternate: fallthrough_block.id,
|
||||
});
|
||||
builder.terminate_with_fallthrough(terminal, fallthrough_block);
|
||||
} else {
|
||||
return Err(Diagnostic::todo(
|
||||
BuildHIRError::ForStatementIsMissingTest,
|
||||
stmt.range,
|
||||
));
|
||||
}
|
||||
}
|
||||
_ => todo!("Lower {stmt:#?}"),
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn lower_variable_declaration(
|
||||
env: &Environment,
|
||||
builder: &mut Builder,
|
||||
stmt: &VariableDeclaration,
|
||||
) -> Result<(), Diagnostic> {
|
||||
let kind = match stmt.kind {
|
||||
VariableDeclarationKind::Const => InstructionKind::Const,
|
||||
VariableDeclarationKind::Let => InstructionKind::Let,
|
||||
VariableDeclarationKind::Var => {
|
||||
return Err(Diagnostic::unsupported(
|
||||
BuildHIRError::VariableDeclarationKindIsVar,
|
||||
stmt.range,
|
||||
));
|
||||
}
|
||||
};
|
||||
for declaration in &stmt.declarations {
|
||||
if let Some(init) = &declaration.init {
|
||||
let value = lower_expression(env, builder, init)?;
|
||||
lower_assignment_pattern(env, builder, kind, &declaration.id, value)?;
|
||||
} else {
|
||||
match &declaration.id {
|
||||
Pattern::Identifier(id) => {
|
||||
let identifier = env.resolve_variable_declaration(id.as_ref(), &id.name);
|
||||
if let Some(identifier) = identifier {
|
||||
builder.push(InstructionValue::DeclareLocal(react_hir::DeclareLocal {
|
||||
lvalue: LValue {
|
||||
identifier: IdentifierOperand {
|
||||
identifier,
|
||||
effect: None,
|
||||
},
|
||||
kind,
|
||||
},
|
||||
}));
|
||||
} else {
|
||||
return Err(Diagnostic::invariant(
|
||||
BuildHIRError::VariableDeclarationBindingIsNonLocal,
|
||||
id.range,
|
||||
));
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return Err(Diagnostic::invalid_syntax(
|
||||
"Expected an identifier for variable declaration without an intializer. Destructuring requires an initial value",
|
||||
declaration.range,
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Converts an ESTree Expression into an HIR InstructionValue. Note that while only a single
|
||||
/// InstructionValue is returned, this function is recursive and may cause multiple instructions
|
||||
/// to be emitted, possibly across multiple basic blocks (in the case of expressions with control
|
||||
/// flow semenatics such as logical, conditional, and optional expressions).
|
||||
fn lower_expression(
|
||||
env: &Environment,
|
||||
builder: &mut Builder,
|
||||
expr: &Expression,
|
||||
) -> Result<IdentifierOperand, Diagnostic> {
|
||||
let value = match expr {
|
||||
Expression::Identifier(expr) => {
|
||||
let identifier = env.resolve_variable_reference(expr.as_ref());
|
||||
if let Some(identifier) = identifier {
|
||||
let place = IdentifierOperand {
|
||||
effect: None,
|
||||
identifier,
|
||||
};
|
||||
InstructionValue::LoadLocal(LoadLocal { place })
|
||||
} else {
|
||||
InstructionValue::LoadGlobal(LoadGlobal {
|
||||
name: expr.name.clone(),
|
||||
})
|
||||
}
|
||||
}
|
||||
Expression::Literal(expr) => InstructionValue::Primitive(react_hir::Primitive {
|
||||
value: expr.value.clone(),
|
||||
}),
|
||||
Expression::NumericLiteral(expr) => InstructionValue::Primitive(react_hir::Primitive {
|
||||
value: JsValue::Number(expr.value),
|
||||
}),
|
||||
Expression::BooleanLiteral(expr) => InstructionValue::Primitive(react_hir::Primitive {
|
||||
value: JsValue::Boolean(expr.value),
|
||||
}),
|
||||
Expression::StringLiteral(expr) => InstructionValue::Primitive(react_hir::Primitive {
|
||||
value: JsValue::String(expr.value.clone()),
|
||||
}),
|
||||
Expression::NullLiteral(_expr) => InstructionValue::Primitive(react_hir::Primitive {
|
||||
value: JsValue::Null,
|
||||
}),
|
||||
Expression::ArrayExpression(expr) => {
|
||||
let mut elements = Vec::with_capacity(expr.elements.len());
|
||||
for expr in &expr.elements {
|
||||
let element = match expr {
|
||||
Some(react_estree::ExpressionOrSpread::SpreadElement(expr)) => Some(
|
||||
PlaceOrSpread::Spread(lower_expression(env, builder, &expr.argument)?),
|
||||
),
|
||||
Some(react_estree::ExpressionOrSpread::Expression(expr)) => {
|
||||
Some(PlaceOrSpread::Place(lower_expression(env, builder, expr)?))
|
||||
}
|
||||
None => None,
|
||||
};
|
||||
elements.push(element);
|
||||
}
|
||||
InstructionValue::Array(react_hir::Array { elements })
|
||||
}
|
||||
|
||||
Expression::AssignmentExpression(expr) => match expr.operator {
|
||||
react_estree::AssignmentOperator::Equals => {
|
||||
let right = lower_expression(env, builder, &expr.right)?;
|
||||
return lower_assignment(
|
||||
env,
|
||||
builder,
|
||||
InstructionKind::Reassign,
|
||||
&expr.left,
|
||||
right,
|
||||
);
|
||||
}
|
||||
_ => todo!("lower assignment expr {:#?}", expr),
|
||||
},
|
||||
|
||||
Expression::BinaryExpression(expr) => {
|
||||
let left = lower_expression(env, builder, &expr.left)?;
|
||||
let right = lower_expression(env, builder, &expr.right)?;
|
||||
InstructionValue::Binary(react_hir::Binary {
|
||||
left,
|
||||
operator: expr.operator,
|
||||
right,
|
||||
})
|
||||
}
|
||||
|
||||
Expression::FunctionExpression(expr) => {
|
||||
InstructionValue::Function(lower_function(env, builder, expr.as_ref())?)
|
||||
}
|
||||
|
||||
Expression::ArrowFunctionExpression(expr) => {
|
||||
InstructionValue::Function(lower_function(env, builder, expr.as_ref())?)
|
||||
}
|
||||
|
||||
Expression::CallExpression(expr) => {
|
||||
let callee_expr = match &expr.callee {
|
||||
ExpressionOrSuper::Super(callee) => {
|
||||
return Err(Diagnostic::unsupported(
|
||||
BuildHIRError::UnsupportedSuperExpression,
|
||||
callee.range,
|
||||
));
|
||||
}
|
||||
ExpressionOrSuper::Expression(callee) => callee,
|
||||
};
|
||||
|
||||
if matches!(&callee_expr, Expression::MemberExpression(_)) {
|
||||
return Err(Diagnostic::todo("Support method calls", expr.range));
|
||||
}
|
||||
|
||||
let callee = lower_expression(env, builder, callee_expr)?;
|
||||
let arguments = lower_arguments(env, builder, &expr.arguments)?;
|
||||
InstructionValue::Call(react_hir::Call { callee, arguments })
|
||||
}
|
||||
|
||||
Expression::JSXElement(expr) => {
|
||||
InstructionValue::JSXElement(lower_jsx_element(env, builder, expr)?)
|
||||
}
|
||||
|
||||
_ => todo!("Lower expr {expr:#?}"),
|
||||
};
|
||||
Ok(builder.push(value))
|
||||
}
|
||||
|
||||
fn lower_arguments(
|
||||
env: &Environment,
|
||||
builder: &mut Builder,
|
||||
args: &[ExpressionOrSpread],
|
||||
) -> Result<Vec<PlaceOrSpread>, Diagnostic> {
|
||||
let mut arguments = Vec::with_capacity(args.len());
|
||||
for arg in args {
|
||||
let element = match arg {
|
||||
react_estree::ExpressionOrSpread::SpreadElement(arg) => {
|
||||
PlaceOrSpread::Spread(lower_expression(env, builder, &arg.argument)?)
|
||||
}
|
||||
react_estree::ExpressionOrSpread::Expression(arg) => {
|
||||
PlaceOrSpread::Place(lower_expression(env, builder, arg)?)
|
||||
}
|
||||
};
|
||||
arguments.push(element);
|
||||
}
|
||||
Ok(arguments)
|
||||
}
|
||||
|
||||
fn lower_function<T: IntoFunction>(
|
||||
env: &Environment,
|
||||
_builder: &mut Builder,
|
||||
function: &T,
|
||||
) -> Result<react_hir::FunctionExpression, Diagnostic> {
|
||||
let context_identifiers = get_context_identifiers(env, function);
|
||||
let mut context = Vec::new();
|
||||
let mut seen = HashSet::new();
|
||||
for declaration_id in context_identifiers {
|
||||
if let Some(identifier) = env.resolve_declaration_id(declaration_id) {
|
||||
if !seen.insert(identifier.id) {
|
||||
continue;
|
||||
}
|
||||
context.push(IdentifierOperand {
|
||||
effect: None,
|
||||
identifier,
|
||||
});
|
||||
}
|
||||
}
|
||||
let mut fun = build(env, function.function())?;
|
||||
fun.context = context;
|
||||
Ok(react_hir::FunctionExpression {
|
||||
// TODO: collect dependencies!
|
||||
dependencies: Default::default(),
|
||||
lowered_function: fun,
|
||||
})
|
||||
}
|
||||
|
||||
fn lower_jsx_element(
|
||||
env: &Environment,
|
||||
builder: &mut Builder,
|
||||
expr: &react_estree::JSXElement,
|
||||
) -> Result<JSXElement, Diagnostic> {
|
||||
let props: Result<Vec<JSXAttribute>, Diagnostic> = expr
|
||||
.opening_element
|
||||
.attributes
|
||||
.iter()
|
||||
.map(|attr| lower_jsx_attribute(env, builder, attr))
|
||||
.collect();
|
||||
let _props = props?;
|
||||
let children: Result<Vec<IdentifierOperand>, Diagnostic> = expr
|
||||
.children
|
||||
.iter()
|
||||
.map(|child| {
|
||||
let child = lower_jsx_child(env, builder, child)?;
|
||||
Ok(child)
|
||||
})
|
||||
.collect();
|
||||
let _children = children?;
|
||||
todo!("lower jsx element");
|
||||
// Ok(JSXElement {
|
||||
// tag: todo!(),
|
||||
// props,
|
||||
// children: if children.is_empty() {
|
||||
// None
|
||||
// } else {
|
||||
// Some(children)
|
||||
// },
|
||||
// })
|
||||
}
|
||||
|
||||
fn lower_jsx_attribute(
|
||||
_env: &Environment,
|
||||
_builder: &mut Builder,
|
||||
_attr: &react_estree::JSXAttributeOrSpread,
|
||||
) -> Result<JSXAttribute, Diagnostic> {
|
||||
todo!("lower jsx attribute")
|
||||
}
|
||||
|
||||
fn lower_jsx_child(
|
||||
_env: &Environment,
|
||||
_builder: &mut Builder,
|
||||
_child: &react_estree::JSXChildItem,
|
||||
) -> Result<IdentifierOperand, Diagnostic> {
|
||||
todo!("lower jsx child")
|
||||
}
|
||||
|
||||
fn lower_assignment(
|
||||
env: &Environment,
|
||||
builder: &mut Builder,
|
||||
kind: InstructionKind,
|
||||
lvalue: &AssignmentTarget,
|
||||
value: IdentifierOperand,
|
||||
) -> Result<IdentifierOperand, Diagnostic> {
|
||||
Ok(match lvalue {
|
||||
AssignmentTarget::Pattern(lvalue) => {
|
||||
lower_assignment_pattern(env, builder, kind, lvalue, value)?
|
||||
}
|
||||
_ => todo!("lower assignment for {:#?}", lvalue),
|
||||
})
|
||||
}
|
||||
|
||||
// TODO: change the success type to void, no caller uses it
|
||||
fn lower_assignment_pattern(
|
||||
env: &Environment,
|
||||
builder: &mut Builder,
|
||||
kind: InstructionKind,
|
||||
lvalue: &Pattern,
|
||||
value: IdentifierOperand,
|
||||
) -> Result<IdentifierOperand, Diagnostic> {
|
||||
Ok(match lvalue {
|
||||
Pattern::Identifier(lvalue) => {
|
||||
let identifier = lower_identifier_for_assignment(env, builder, kind, lvalue)?;
|
||||
builder.push(InstructionValue::StoreLocal(react_hir::StoreLocal {
|
||||
lvalue: LValue { identifier, kind },
|
||||
value,
|
||||
}))
|
||||
}
|
||||
Pattern::ArrayPattern(lvalue) => {
|
||||
let mut items = Vec::with_capacity(lvalue.elements.len());
|
||||
let mut followups: Vec<(Identifier, &Pattern)> = Vec::new();
|
||||
for element in &lvalue.elements {
|
||||
match element {
|
||||
None => items.push(ArrayDestructureItem::Hole),
|
||||
Some(Pattern::Identifier(element)) => {
|
||||
let identifier =
|
||||
lower_identifier_for_assignment(env, builder, kind, element)?;
|
||||
items.push(ArrayDestructureItem::Value(identifier));
|
||||
}
|
||||
Some(Pattern::RestElement(element)) => {
|
||||
if let Pattern::Identifier(element) = &element.argument {
|
||||
let identifier = lower_identifier_for_assignment(
|
||||
env,
|
||||
builder,
|
||||
kind,
|
||||
element.as_ref(),
|
||||
)?;
|
||||
items.push(ArrayDestructureItem::Spread(identifier));
|
||||
} else {
|
||||
let temporary = env.new_temporary();
|
||||
items.push(ArrayDestructureItem::Spread(IdentifierOperand {
|
||||
identifier: temporary.clone(),
|
||||
effect: None,
|
||||
}));
|
||||
followups.push((temporary, &element.argument));
|
||||
}
|
||||
}
|
||||
Some(element) => {
|
||||
let temporary = env.new_temporary();
|
||||
items.push(ArrayDestructureItem::Value(IdentifierOperand {
|
||||
identifier: temporary.clone(),
|
||||
effect: None,
|
||||
}));
|
||||
followups.push((temporary, element));
|
||||
}
|
||||
}
|
||||
}
|
||||
let temporary = builder.push(InstructionValue::Destructure(Destructure {
|
||||
kind,
|
||||
pattern: DestructurePattern::Array(items),
|
||||
value,
|
||||
}));
|
||||
for (temporary, pattern) in followups {
|
||||
lower_assignment_pattern(
|
||||
env,
|
||||
builder,
|
||||
kind,
|
||||
pattern,
|
||||
IdentifierOperand {
|
||||
identifier: temporary,
|
||||
effect: None,
|
||||
},
|
||||
)?;
|
||||
}
|
||||
temporary
|
||||
}
|
||||
Pattern::ObjectPattern(lvalue) => {
|
||||
let mut properties = Vec::with_capacity(lvalue.properties.len());
|
||||
let mut followups: Vec<(Identifier, &Pattern)> = Vec::new();
|
||||
|
||||
for property in &lvalue.properties {
|
||||
match property {
|
||||
AssignmentPropertyOrRestElement::RestElement(property) => {
|
||||
if let Pattern::Identifier(element) = &property.argument {
|
||||
let identifier = lower_identifier_for_assignment(
|
||||
env,
|
||||
builder,
|
||||
kind,
|
||||
element.as_ref(),
|
||||
)?;
|
||||
properties.push(ObjectDestructureItem::Spread(identifier));
|
||||
} else {
|
||||
let temporary = env.new_temporary();
|
||||
properties.push(ObjectDestructureItem::Spread(IdentifierOperand {
|
||||
identifier: temporary.clone(),
|
||||
effect: None,
|
||||
}));
|
||||
followups.push((temporary, &property.argument));
|
||||
}
|
||||
}
|
||||
AssignmentPropertyOrRestElement::AssignmentProperty(property) => {
|
||||
if property.is_computed {
|
||||
return Err(Diagnostic::todo(
|
||||
"Handle computed properties in ObjectPattern",
|
||||
property.range,
|
||||
));
|
||||
}
|
||||
let key = if let Expression::Identifier(key) = &property.key {
|
||||
key.name.as_str()
|
||||
} else {
|
||||
return Err(Diagnostic::todo(
|
||||
"Support non-identifier object keys in non-computed ObjectPattern",
|
||||
property.range,
|
||||
));
|
||||
};
|
||||
if let Pattern::Identifier(value) = &property.value {
|
||||
let value = lower_identifier_for_assignment(env, builder, kind, value)?;
|
||||
properties.push(ObjectDestructureItem::Property(
|
||||
ObjectDestructureProperty {
|
||||
name: key.to_string(),
|
||||
value,
|
||||
},
|
||||
));
|
||||
} else {
|
||||
let temporary = env.new_temporary();
|
||||
properties.push(ObjectDestructureItem::Property(
|
||||
ObjectDestructureProperty {
|
||||
name: key.to_string(),
|
||||
value: IdentifierOperand {
|
||||
identifier: temporary.clone(),
|
||||
effect: None,
|
||||
},
|
||||
},
|
||||
));
|
||||
followups.push((temporary, &property.value));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let temporary = builder.push(InstructionValue::Destructure(Destructure {
|
||||
kind,
|
||||
pattern: DestructurePattern::Object(properties),
|
||||
value,
|
||||
}));
|
||||
for (temporary, pattern) in followups {
|
||||
lower_assignment_pattern(
|
||||
env,
|
||||
builder,
|
||||
kind,
|
||||
pattern,
|
||||
IdentifierOperand {
|
||||
identifier: temporary,
|
||||
effect: None,
|
||||
},
|
||||
)?;
|
||||
}
|
||||
temporary
|
||||
}
|
||||
_ => todo!("lower assignment pattern for {:#?}", lvalue),
|
||||
})
|
||||
}
|
||||
|
||||
fn lower_identifier_for_assignment(
|
||||
env: &Environment,
|
||||
_builder: &mut Builder,
|
||||
kind: InstructionKind,
|
||||
node: &react_estree::Identifier,
|
||||
) -> Result<IdentifierOperand, Diagnostic> {
|
||||
match kind {
|
||||
InstructionKind::Reassign => {
|
||||
let identifier = env.resolve_variable_reference(node);
|
||||
if let Some(identifier) = identifier {
|
||||
Ok(IdentifierOperand {
|
||||
identifier,
|
||||
effect: None,
|
||||
})
|
||||
} else {
|
||||
// Reassigning a global
|
||||
Err(
|
||||
Diagnostic::invalid_react(BuildHIRError::ReassignedGlobal, node.range)
|
||||
.annotate(format!("Cannot reassign `{}`", &node.name), node.range),
|
||||
)
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
// Declaration
|
||||
let identifier = env.resolve_variable_declaration(node, &node.name).unwrap();
|
||||
Ok(IdentifierOperand {
|
||||
identifier,
|
||||
effect: None,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,322 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
|
||||
use react_diagnostics::Diagnostic;
|
||||
use react_hir::{
|
||||
initialize_hir, BasicBlock, BlockId, BlockKind, Blocks, Environment, GotoKind, IdentifierData,
|
||||
IdentifierOperand, InstrIx, Instruction, InstructionIdGenerator, InstructionValue, Terminal,
|
||||
TerminalValue, Type, HIR,
|
||||
};
|
||||
|
||||
use crate::BuildHIRError;
|
||||
|
||||
/// Helper struct used when converting from ESTree to HIR. Includes:
|
||||
/// - Variable resolution
|
||||
/// - Label resolution (for labeled statements and break/continue)
|
||||
/// - Access to the environment
|
||||
///
|
||||
/// As well as representing the incomplete form of the HIR. Usage
|
||||
/// generally involves driving calls to enter/exit blocks, resolve
|
||||
/// labels and variables, and then calling `build()` when the HIR
|
||||
/// is complete.
|
||||
pub(crate) struct Builder<'e> {
|
||||
#[allow(dead_code)]
|
||||
environment: &'e Environment,
|
||||
|
||||
completed: Blocks,
|
||||
|
||||
instructions: Vec<Instruction>,
|
||||
|
||||
entry: BlockId,
|
||||
|
||||
wip: WipBlock,
|
||||
|
||||
id_gen: InstructionIdGenerator,
|
||||
|
||||
scopes: Vec<ControlFlowScope>,
|
||||
}
|
||||
|
||||
pub(crate) struct WipBlock {
|
||||
pub id: BlockId,
|
||||
pub kind: BlockKind,
|
||||
pub instructions: Vec<InstrIx>,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||
enum ControlFlowScope {
|
||||
Loop(LoopScope),
|
||||
|
||||
// Switch(SwitchScope),
|
||||
#[allow(dead_code)]
|
||||
Label(LabelScope),
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||
pub(crate) struct LoopScope {
|
||||
pub label: Option<String>,
|
||||
pub continue_block: BlockId,
|
||||
pub break_block: BlockId,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||
pub(crate) struct LabelScope {
|
||||
pub label: String,
|
||||
pub block: BlockId,
|
||||
}
|
||||
|
||||
impl ControlFlowScope {
|
||||
fn label(&self) -> Option<&String> {
|
||||
match self {
|
||||
Self::Loop(scope) => scope.label.as_ref(),
|
||||
Self::Label(scope) => Some(&scope.label),
|
||||
}
|
||||
}
|
||||
|
||||
fn break_block(&self) -> BlockId {
|
||||
match self {
|
||||
Self::Loop(scope) => scope.break_block,
|
||||
Self::Label(scope) => scope.block,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'e> Builder<'e> {
|
||||
pub(crate) fn new(environment: &'e Environment) -> Self {
|
||||
let entry = environment.next_block_id();
|
||||
let current = WipBlock {
|
||||
id: entry,
|
||||
kind: BlockKind::Block,
|
||||
instructions: Default::default(),
|
||||
};
|
||||
Self {
|
||||
environment,
|
||||
completed: Default::default(),
|
||||
instructions: Default::default(),
|
||||
entry,
|
||||
wip: current,
|
||||
id_gen: InstructionIdGenerator::new(),
|
||||
scopes: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Completes the builder and returns the HIR if it was valid,
|
||||
/// or a Diagnostic if a validation error occured.
|
||||
///
|
||||
/// TODO: refine the type, only invariants should be possible here,
|
||||
/// not other types of errors
|
||||
pub(crate) fn build(self) -> Result<HIR, Diagnostic> {
|
||||
let mut hir = HIR {
|
||||
entry: self.entry,
|
||||
blocks: self.completed,
|
||||
instructions: self.instructions,
|
||||
};
|
||||
// Run all the initialization passes
|
||||
initialize_hir(&mut hir)?;
|
||||
Ok(hir)
|
||||
}
|
||||
|
||||
/// Adds a new instruction to the end of the work in progress block
|
||||
pub(crate) fn push(&mut self, value: InstructionValue) -> IdentifierOperand {
|
||||
let lvalue = IdentifierOperand {
|
||||
identifier: self.environment.new_temporary(),
|
||||
effect: None,
|
||||
};
|
||||
let instr = Instruction {
|
||||
id: self.id_gen.next(),
|
||||
lvalue: lvalue.clone(),
|
||||
value,
|
||||
};
|
||||
let ix = InstrIx::new(self.instructions.len() as u32);
|
||||
self.instructions.push(instr);
|
||||
self.wip.instructions.push(ix);
|
||||
lvalue
|
||||
}
|
||||
|
||||
/// Terminates the work in progress block with the given terminal, and starts a new
|
||||
/// work in progress block with the given kind
|
||||
pub(crate) fn terminate(&mut self, terminal: TerminalValue, next_kind: BlockKind) {
|
||||
let next_wip = WipBlock {
|
||||
id: self.environment.next_block_id(),
|
||||
kind: next_kind,
|
||||
instructions: Default::default(),
|
||||
};
|
||||
self.terminate_with_fallthrough(terminal, next_wip)
|
||||
}
|
||||
|
||||
pub(crate) fn terminate_with_fallthrough(
|
||||
&mut self,
|
||||
terminal: TerminalValue,
|
||||
fallthrough: WipBlock,
|
||||
) {
|
||||
let prev_wip = std::mem::replace(&mut self.wip, fallthrough);
|
||||
self.completed.insert(Box::new(BasicBlock {
|
||||
id: prev_wip.id,
|
||||
kind: prev_wip.kind,
|
||||
instructions: prev_wip.instructions,
|
||||
terminal: Terminal {
|
||||
id: self.id_gen.next(),
|
||||
value: terminal,
|
||||
},
|
||||
predecessors: Default::default(),
|
||||
phis: Default::default(),
|
||||
}));
|
||||
}
|
||||
|
||||
pub(crate) fn reserve(&mut self, kind: BlockKind) -> WipBlock {
|
||||
WipBlock {
|
||||
id: self.environment.next_block_id(),
|
||||
kind,
|
||||
instructions: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn enter<F>(&mut self, kind: BlockKind, f: F) -> Result<BlockId, Diagnostic>
|
||||
where
|
||||
F: FnOnce(&mut Self) -> Result<TerminalValue, Diagnostic>,
|
||||
{
|
||||
let wip = self.reserve(kind);
|
||||
let id = wip.id;
|
||||
self.enter_reserved(wip, f)?;
|
||||
Ok(id)
|
||||
}
|
||||
|
||||
fn enter_reserved<F>(&mut self, wip: WipBlock, f: F) -> Result<(), Diagnostic>
|
||||
where
|
||||
F: FnOnce(&mut Self) -> Result<TerminalValue, Diagnostic>,
|
||||
{
|
||||
let current = std::mem::replace(&mut self.wip, wip);
|
||||
|
||||
let (result, terminal) = match f(self) {
|
||||
Ok(terminal) => (Ok(()), terminal),
|
||||
Err(error) => (
|
||||
Err(error),
|
||||
// TODO: add a `Terminal::Error` variant
|
||||
TerminalValue::Goto(react_hir::GotoTerminal {
|
||||
block: current.id,
|
||||
kind: GotoKind::Break,
|
||||
}),
|
||||
),
|
||||
};
|
||||
|
||||
let completed = std::mem::replace(&mut self.wip, current);
|
||||
self.completed.insert(Box::new(BasicBlock {
|
||||
id: completed.id,
|
||||
kind: completed.kind,
|
||||
instructions: completed.instructions,
|
||||
terminal: Terminal {
|
||||
id: self.id_gen.next(),
|
||||
value: terminal,
|
||||
},
|
||||
predecessors: Default::default(),
|
||||
phis: Default::default(),
|
||||
}));
|
||||
result
|
||||
}
|
||||
|
||||
pub(crate) fn enter_loop<F>(
|
||||
&mut self,
|
||||
scope: LoopScope,
|
||||
f: F,
|
||||
) -> Result<TerminalValue, Diagnostic>
|
||||
where
|
||||
F: FnOnce(&mut Self) -> Result<TerminalValue, Diagnostic>,
|
||||
{
|
||||
self.scopes.push(ControlFlowScope::Loop(scope.clone()));
|
||||
let terminal = f(self);
|
||||
let last = self.scopes.pop().unwrap();
|
||||
assert_eq!(last, ControlFlowScope::Loop(scope));
|
||||
terminal
|
||||
}
|
||||
|
||||
/// Returns a new temporary identifier
|
||||
/// This may be necessary for destructuring with default values. there
|
||||
/// we synthesize a temporary identifier to store the possibly-missing value
|
||||
/// into, and emit a later StoreLocal for the original identifier
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn make_temporary(&self) -> react_hir::Identifier {
|
||||
react_hir::Identifier {
|
||||
id: self.environment.next_identifier_id(),
|
||||
name: None,
|
||||
data: Rc::new(RefCell::new(IdentifierData {
|
||||
mutable_range: Default::default(),
|
||||
scope: None,
|
||||
type_: Type::Var(self.environment.next_type_var_id()),
|
||||
})),
|
||||
}
|
||||
}
|
||||
|
||||
/// Resolves the target for the given break label (if present), or returns the default
|
||||
/// break target given the current context. Returns a diagnostic if the label is
|
||||
/// provided but cannot be resolved.
|
||||
pub(crate) fn resolve_break(
|
||||
&self,
|
||||
label: Option<&react_estree::Identifier>,
|
||||
) -> Result<BlockId, Diagnostic> {
|
||||
for scope in self.scopes.iter().rev() {
|
||||
match (label, scope.label()) {
|
||||
// If this is an unlabeled break, return the most recent break target
|
||||
(None, _) => return Ok(scope.break_block()),
|
||||
// If the break is labeled and matches the current scope, return its break target
|
||||
(Some(label), Some(scope_label)) if &label.name == scope_label => {
|
||||
return Ok(scope.break_block());
|
||||
}
|
||||
// Otherwise keep searching
|
||||
_ => continue,
|
||||
}
|
||||
}
|
||||
Err(Diagnostic::invalid_syntax(
|
||||
BuildHIRError::UnresolvedBreakTarget,
|
||||
None,
|
||||
))
|
||||
}
|
||||
|
||||
/// Resolves the target for the given continue label (if present), or returns the default
|
||||
/// continue target given the current context. Returns a diagnostic if the label is
|
||||
/// provided but cannot be resolved.
|
||||
pub(crate) fn resolve_continue(
|
||||
&self,
|
||||
label: Option<&react_estree::Identifier>,
|
||||
) -> Result<BlockId, Diagnostic> {
|
||||
for scope in self.scopes.iter().rev() {
|
||||
match scope {
|
||||
ControlFlowScope::Loop(scope) => {
|
||||
match (label, &scope.label) {
|
||||
// If this is an unlabeled continue, return the first matching loop
|
||||
(None, _) => return Ok(scope.continue_block),
|
||||
// If the continue is labeled and matches the current scope, return its continue target
|
||||
(Some(label), Some(scope_label))
|
||||
if label.name.as_str() == scope_label.as_str() =>
|
||||
{
|
||||
return Ok(scope.continue_block);
|
||||
}
|
||||
// Otherwise keep searching
|
||||
_ => continue,
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
match (label, scope.label()) {
|
||||
(Some(label), Some(scope_label)) if label.name.as_str() == scope_label => {
|
||||
// Error, the continue referred to a label that is not a loop
|
||||
return Err(Diagnostic::invalid_syntax(
|
||||
BuildHIRError::ContinueTargetIsNotALoop,
|
||||
None,
|
||||
));
|
||||
}
|
||||
_ => continue,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(Diagnostic::invalid_syntax(
|
||||
BuildHIRError::UnresolvedContinueTarget,
|
||||
None,
|
||||
))
|
||||
}
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
use std::collections::HashSet;
|
||||
|
||||
use react_estree::IntoFunction;
|
||||
use react_hir::Environment;
|
||||
use react_semantic_analysis::{DeclarationId, ScopeView};
|
||||
|
||||
pub(crate) fn get_context_identifiers<T: IntoFunction>(
|
||||
env: &Environment,
|
||||
node: &T,
|
||||
) -> Vec<DeclarationId> {
|
||||
let function_scope = env.scope(node.function()).unwrap();
|
||||
let mut free = FreeVariables::default();
|
||||
let mut seen = HashSet::new();
|
||||
populate_free_variable_references(&mut free, &mut seen, function_scope);
|
||||
free
|
||||
}
|
||||
|
||||
type FreeVariables = Vec<DeclarationId>;
|
||||
|
||||
fn populate_free_variable_references(
|
||||
free: &mut FreeVariables,
|
||||
seen: &mut HashSet<DeclarationId>,
|
||||
scope: ScopeView<'_>,
|
||||
) {
|
||||
for reference in scope.references() {
|
||||
if !seen.insert(reference.declaration().id()) {
|
||||
continue;
|
||||
}
|
||||
let declaration_scope = reference.declaration().scope();
|
||||
if !declaration_scope.is_descendant_of(scope) {
|
||||
free.push(reference.declaration().id())
|
||||
}
|
||||
}
|
||||
for child in scope.children() {
|
||||
populate_free_variable_references(free, seen, child);
|
||||
}
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
use thiserror::Error;
|
||||
|
||||
/// Errors which can occur during HIR construction
|
||||
#[derive(Error, Debug)]
|
||||
pub enum BuildHIRError {
|
||||
/// ErrorSeverity::Unsupported
|
||||
#[error(
|
||||
"Variable declarations must be `let` or `const`, `var` declarations are not supported"
|
||||
)]
|
||||
VariableDeclarationKindIsVar,
|
||||
|
||||
/// ErrorSeverity::Invariant
|
||||
#[error("Invariant: Expected variable declaration to declare a fresh binding")]
|
||||
VariableDeclarationBindingIsNonLocal,
|
||||
|
||||
/// ErrorSeverity::Todo
|
||||
#[error("`for` statements must have an initializer, eg `for (**let i = 0**; ...)`")]
|
||||
ForStatementIsMissingInitializer,
|
||||
|
||||
/// ErrorSeverity::Todo
|
||||
#[error(
|
||||
"`for` statements must have a test condition, eg `for (let i = 0; **i < count**; ...)`"
|
||||
)]
|
||||
ForStatementIsMissingTest,
|
||||
|
||||
/// ErrorSeverity::Invariant
|
||||
#[error("Invariant: Expected an expression node")]
|
||||
NonExpressionInExpressionPosition,
|
||||
|
||||
/// ErrorSeverity::InvalidReact
|
||||
#[error("React functions may not reassign variables defined outside of the component or hook")]
|
||||
ReassignedGlobal,
|
||||
|
||||
/// ErrorSeverity::InvalidSyntax
|
||||
#[error("Could not resolve a target for `break` statement")]
|
||||
UnresolvedBreakTarget,
|
||||
|
||||
/// ErrorSeverity::InvalidSyntax
|
||||
#[error("Could not resolve a target for `continue` statement")]
|
||||
UnresolvedContinueTarget,
|
||||
|
||||
/// ErrorSeverity::InvalidSyntax
|
||||
#[error("Labeled `continue` statements must use the label of a loop statement")]
|
||||
ContinueTargetIsNotALoop,
|
||||
|
||||
/// ErrorSeverity::Invariant
|
||||
#[error("Invariant: Identifier was not resolved (did name resolution run successfully?)")]
|
||||
UnknownIdentifier,
|
||||
|
||||
/// ErrorSeverity::InvalidSyntax
|
||||
#[error("Expected function to have a body")]
|
||||
EmptyFunction,
|
||||
|
||||
#[error("`super` is not suppported")]
|
||||
UnsupportedSuperExpression,
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
mod build;
|
||||
mod builder;
|
||||
mod context;
|
||||
mod error;
|
||||
|
||||
pub use build::build;
|
||||
pub use error::*;
|
||||
@@ -1,23 +0,0 @@
|
||||
[package]
|
||||
name = "react_diagnostics"
|
||||
version = "0.1.0"
|
||||
publish = false
|
||||
authors.workspace = true
|
||||
description.workspace = true
|
||||
edition.workspace = true
|
||||
homepage.workspace = true
|
||||
keywords.workspace = true
|
||||
license.workspace = true
|
||||
repository.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
# TODO: extract SourceRange into a separate crate so that
|
||||
# we don't depend on full estree here
|
||||
react_estree = { workspace = true }
|
||||
# TODO: consider extracting a separate react_miette crate which does
|
||||
# the translation from react_diagnostics::Diagnostic to miette::Diagnostic
|
||||
miette = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
static_assertions = { workspace = true }
|
||||
@@ -1,10 +0,0 @@
|
||||
# react_diagnostics
|
||||
|
||||
Types for representing compiler diagnostics. Includes a general-purpose representation
|
||||
of diagnostics with related information which can be converted into `miette::Diagnostic` to exploit miette's pretty printing of errors.
|
||||
|
||||
Unlike miette, lsp_types, and other diagnostic libraries, the error severities match
|
||||
React Compiler's semantics. The intent is that a given diagnostic may be displayed as
|
||||
an error, warning, or not displayed at all depending on the context in which the
|
||||
compiler is being used. For example, an ESLint plugin powered by React Compiler may ignore
|
||||
InvalidSyntax diagnostics, whereas the regular compiler may report them as errors.
|
||||
@@ -1,285 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
use std::error::Error;
|
||||
use std::fmt::{Debug, Display, Write};
|
||||
|
||||
use miette::SourceSpan;
|
||||
use react_estree::SourceRange;
|
||||
use static_assertions::assert_impl_all;
|
||||
use thiserror::Error;
|
||||
|
||||
pub type Diagnostics = Vec<Diagnostic>;
|
||||
pub type DiagnosticsResult<T> = Result<T, Diagnostics>;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct WithDiagnostics<T> {
|
||||
pub item: T,
|
||||
pub diagnostics: Vec<Diagnostic>,
|
||||
}
|
||||
|
||||
impl<T> From<WithDiagnostics<T>> for Result<T, Diagnostics> {
|
||||
fn from(s: WithDiagnostics<T>) -> Result<T, Diagnostics> {
|
||||
if s.diagnostics.is_empty() {
|
||||
Ok(s.item)
|
||||
} else {
|
||||
Err(s.diagnostics)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn diagnostics_result<T>(result: T, diagnostics: Diagnostics) -> DiagnosticsResult<T> {
|
||||
if diagnostics.is_empty() {
|
||||
Ok(result)
|
||||
} else {
|
||||
Err(diagnostics)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Error)]
|
||||
pub enum DiagnosticSeverity {
|
||||
/// A feature that is intended to work but not yet implemented
|
||||
#[error("Not implemented")]
|
||||
Todo,
|
||||
|
||||
/// Syntax that is valid but intentionally not supported
|
||||
#[error("Unsupported")]
|
||||
Unsupported,
|
||||
|
||||
/// Invalid syntax
|
||||
#[error("Invalid JavaScript")]
|
||||
InvalidSyntax,
|
||||
|
||||
/// Valid syntax, but invalid React
|
||||
#[error("Invalid React")]
|
||||
InvalidReact,
|
||||
|
||||
/// Internal compiler error (ICE)
|
||||
#[error("Internal error")]
|
||||
Invariant,
|
||||
}
|
||||
|
||||
/// A diagnostic message as a result of validating some code. This struct is
|
||||
/// modeled after the LSP Diagnostic type:
|
||||
/// https://microsoft.github.io/language-server-protocol/specification#diagnostic
|
||||
///
|
||||
/// Changes from LSP:
|
||||
/// - `location` is different from LSP in that it's a file + span instead of
|
||||
/// just a span.
|
||||
/// - Unused fields are omitted.
|
||||
/// - Severity is a custom enum that represents React-specific categories of error.
|
||||
/// The translation to an LSP error/warning/etc depends on compiler settings and
|
||||
/// invocation context.
|
||||
#[derive(Debug)]
|
||||
pub struct Diagnostic(Box<DiagnosticData>);
|
||||
|
||||
impl Diagnostic {
|
||||
fn with_severity<T: 'static + DiagnosticDisplay>(
|
||||
severity: DiagnosticSeverity,
|
||||
message: T,
|
||||
range: Option<SourceRange>,
|
||||
) -> Self {
|
||||
Self(Box::new(DiagnosticData {
|
||||
message: Box::new(message),
|
||||
span: range.map(source_span_from_range),
|
||||
related_information: Vec::new(),
|
||||
severity,
|
||||
data: Vec::new(),
|
||||
}))
|
||||
}
|
||||
|
||||
/// Creates a new Todo Diagnostic.
|
||||
/// Additional locations can be added with the `.annotate()` function.
|
||||
pub fn todo<T: 'static + DiagnosticDisplay>(message: T, range: Option<SourceRange>) -> Self {
|
||||
Diagnostic::with_severity(DiagnosticSeverity::Todo, message, range)
|
||||
}
|
||||
|
||||
/// Creates a new Unsupported Diagnostic.
|
||||
/// Additional locations can be added with the `.annotate()` function.
|
||||
pub fn unsupported<T: 'static + DiagnosticDisplay>(
|
||||
message: T,
|
||||
range: Option<SourceRange>,
|
||||
) -> Self {
|
||||
Diagnostic::with_severity(DiagnosticSeverity::Unsupported, message, range)
|
||||
}
|
||||
|
||||
/// Creates a new InvalidSyntax Diagnostic.
|
||||
/// Additional locations can be added with the `.annotate()` function.
|
||||
pub fn invalid_syntax<T: 'static + DiagnosticDisplay>(
|
||||
message: T,
|
||||
range: Option<SourceRange>,
|
||||
) -> Self {
|
||||
Diagnostic::with_severity(DiagnosticSeverity::InvalidSyntax, message, range)
|
||||
}
|
||||
|
||||
/// Creates a new InvalidReact Diagnostic.
|
||||
/// Additional locations can be added with the `.annotate()` function.
|
||||
pub fn invalid_react<T: 'static + DiagnosticDisplay>(
|
||||
message: T,
|
||||
range: Option<SourceRange>,
|
||||
) -> Self {
|
||||
Diagnostic::with_severity(DiagnosticSeverity::InvalidReact, message, range)
|
||||
}
|
||||
|
||||
/// Creates a new InvalidReact Diagnostic.
|
||||
/// Additional locations can be added with the `.annotate()` function.
|
||||
pub fn invariant<T: 'static + DiagnosticDisplay>(
|
||||
message: T,
|
||||
range: Option<SourceRange>,
|
||||
) -> Self {
|
||||
Diagnostic::with_severity(DiagnosticSeverity::Invariant, message, range)
|
||||
}
|
||||
|
||||
/// Annotates this error with an additional location and associated message.
|
||||
pub fn annotate<T: 'static + DiagnosticDisplay>(
|
||||
mut self,
|
||||
message: T,
|
||||
range: Option<SourceRange>,
|
||||
) -> Self {
|
||||
self.0
|
||||
.related_information
|
||||
.push(DiagnosticRelatedInformation {
|
||||
message: Box::new(message),
|
||||
span: range.map(source_span_from_range),
|
||||
});
|
||||
self
|
||||
}
|
||||
|
||||
pub fn message(&self) -> &impl DiagnosticDisplay {
|
||||
&self.0.message
|
||||
}
|
||||
|
||||
pub fn span(&self) -> Option<SourceSpan> {
|
||||
self.0.span
|
||||
}
|
||||
|
||||
pub fn get_data(&self) -> &[impl DiagnosticDisplay] {
|
||||
&self.0.data
|
||||
}
|
||||
|
||||
pub fn severity(&self) -> DiagnosticSeverity {
|
||||
self.0.severity
|
||||
}
|
||||
|
||||
pub fn related_information(&self) -> &[DiagnosticRelatedInformation] {
|
||||
&self.0.related_information
|
||||
}
|
||||
|
||||
pub fn print_without_source(&self) -> String {
|
||||
let mut result = String::new();
|
||||
writeln!(
|
||||
result,
|
||||
"{message}:{span:?}",
|
||||
message = &self.0.message,
|
||||
span = self.0.span
|
||||
)
|
||||
.unwrap();
|
||||
if !self.0.related_information.is_empty() {
|
||||
for (ix, related) in self.0.related_information.iter().enumerate() {
|
||||
writeln!(
|
||||
result,
|
||||
"[related {ix}] {message}:{span:?}",
|
||||
ix = ix + 1,
|
||||
message = related.message,
|
||||
span = related.span
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
};
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Diagnostic {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{}", self.0.message)
|
||||
}
|
||||
}
|
||||
|
||||
impl Error for Diagnostic {}
|
||||
|
||||
impl miette::Diagnostic for Diagnostic {
|
||||
fn help<'a>(&'a self) -> Option<Box<dyn Display + 'a>> {
|
||||
Some(Box::new(self.0.message.to_string()))
|
||||
}
|
||||
|
||||
fn labels(&self) -> Option<Box<dyn Iterator<Item = miette::LabeledSpan> + '_>> {
|
||||
let related_items = &self.0.related_information;
|
||||
let mut spans: Vec<miette::LabeledSpan> = Vec::new();
|
||||
for related in related_items {
|
||||
if let Some(span) = related.span {
|
||||
spans.push(miette::LabeledSpan::new_with_span(
|
||||
Some(related.message.to_string()),
|
||||
span,
|
||||
))
|
||||
}
|
||||
}
|
||||
if spans.is_empty() {
|
||||
if let Some(span) = self.0.span {
|
||||
spans.push(miette::LabeledSpan::new_with_span(
|
||||
Some(self.0.message.to_string()),
|
||||
span,
|
||||
))
|
||||
}
|
||||
}
|
||||
Some(Box::new(spans.into_iter()))
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure Diagnostic is thread-safe
|
||||
assert_impl_all!(Diagnostic: Send, Sync);
|
||||
|
||||
#[derive(Debug)]
|
||||
struct DiagnosticData {
|
||||
/// Human readable error message.
|
||||
message: Box<dyn DiagnosticDisplay>,
|
||||
|
||||
/// The primary location of this diagnostic.
|
||||
span: Option<SourceSpan>,
|
||||
|
||||
/// Related diagnostic information, such as other definitions in the case of
|
||||
/// a duplicate definition error.
|
||||
related_information: Vec<DiagnosticRelatedInformation>,
|
||||
|
||||
severity: DiagnosticSeverity,
|
||||
|
||||
/// A list with data that can be passed to the code actions
|
||||
/// `data` is used in the LSP protocol:
|
||||
/// @see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#diagnostic
|
||||
data: Vec<Box<dyn DiagnosticDisplay>>,
|
||||
}
|
||||
|
||||
/// Secondary locations attached to a diagnostic.
|
||||
#[derive(Debug)]
|
||||
pub struct DiagnosticRelatedInformation {
|
||||
/// The message of this related diagnostic information.
|
||||
pub message: Box<dyn DiagnosticDisplay>,
|
||||
|
||||
/// The location of this related diagnostic information.
|
||||
pub span: Option<SourceSpan>,
|
||||
}
|
||||
|
||||
/// Trait for diagnostic messages to allow structs that capture
|
||||
/// some data and can lazily convert it to a message.
|
||||
pub trait DiagnosticDisplay: Debug + Display + Send + Sync {}
|
||||
|
||||
/// Automatically implement the trait if constraints are met, so that
|
||||
/// implementors don't need to.
|
||||
impl<T> DiagnosticDisplay for T where T: Debug + Display + Send + Sync {}
|
||||
|
||||
impl From<Diagnostic> for Diagnostics {
|
||||
fn from(diagnostic: Diagnostic) -> Self {
|
||||
vec![diagnostic]
|
||||
}
|
||||
}
|
||||
|
||||
fn source_span_from_range(range: SourceRange) -> SourceSpan {
|
||||
SourceSpan::new(
|
||||
(range.start as usize).into(),
|
||||
((u32::from(range.end) - range.start) as usize).into(),
|
||||
)
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
mod diagnostic;
|
||||
|
||||
pub use diagnostic::*;
|
||||
|
||||
/// Returns Ok(()) if the condition is true, otherwise returns Err()
|
||||
/// with the diagnostic produced by the provided callback
|
||||
pub fn invariant<F>(cond: bool, f: F) -> Result<(), Diagnostic>
|
||||
where
|
||||
F: Fn() -> Diagnostic,
|
||||
{
|
||||
if cond { Ok(()) } else { Err(f()) }
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
[package]
|
||||
name = "react_estree"
|
||||
version = "0.1.0"
|
||||
publish = false
|
||||
authors.workspace = true
|
||||
description.workspace = true
|
||||
edition.workspace = true
|
||||
homepage.workspace = true
|
||||
keywords.workspace = true
|
||||
license.workspace = true
|
||||
repository.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
insta = { workspace = true }
|
||||
serde = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
static_assertions = { workspace = true }
|
||||
|
||||
[build-dependencies]
|
||||
react_estree_codegen = { workspace = true }
|
||||
@@ -1,17 +0,0 @@
|
||||
# react_estree
|
||||
|
||||
This crate is a Rust representation of the [ESTree format](https://github.com/estree/estree/tree/master) and
|
||||
popular extenions including JSX and (eventually) Flow and TypeScript.
|
||||
|
||||
This crate is intended as the main interchange format with outside code. A typical integration with React Compiler
|
||||
will look as follows:
|
||||
|
||||
1. Host Compiler parses into the host AST format.
|
||||
2. Host Compiler converts into `react_estree`.
|
||||
3. Host Compiler invokes React Compiler to compile the input, which (conceptually)
|
||||
returns the resulting code in `react_estree` format.
|
||||
4. Host Compiler convert back from `react_estree` to its host AST format.
|
||||
|
||||
Because React Compiler is intended to support JavaScript-based toolchains, `react_estree` is designed to support
|
||||
accurate serialization to/from estree-compatible JSON. We may also support the Babel AST format
|
||||
(a variant of ESTree) as well, depending on demand.
|
||||
@@ -1,31 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
use react_estree_codegen::estree;
|
||||
|
||||
// Example custom build script.
|
||||
fn main() {
|
||||
// Re-run if the codegen files change
|
||||
println!("cargo:rerun-if-changed=../react_estree_codegen/src/codegen.rs");
|
||||
println!("cargo:rerun-if-changed=../react_estree_codegen/src/lib.rs");
|
||||
println!("cargo:rerun-if-changed=../react_estree_codegen/src/ecmascript.json");
|
||||
println!("cargo:rerun-if-changed=../react_estree_codegen");
|
||||
|
||||
let src = estree();
|
||||
let copyright = "
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
"
|
||||
.to_string();
|
||||
let trimmed_copyright = copyright.trim();
|
||||
let contents = format!("{trimmed_copyright}\n{src}");
|
||||
std::fs::write("src/generated.rs", contents).unwrap();
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Serialize, Deserialize, Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub enum Binding {
|
||||
Global,
|
||||
Module(BindingId),
|
||||
Local(BindingId),
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct BindingId(u32);
|
||||
|
||||
impl BindingId {
|
||||
pub fn new(value: u32) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<BindingId> for u32 {
|
||||
fn from(value: BindingId) -> Self {
|
||||
value.0
|
||||
}
|
||||
}
|
||||
@@ -1,528 +0,0 @@
|
||||
{
|
||||
"type": "Program",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 7,
|
||||
"column": 1
|
||||
}
|
||||
},
|
||||
"body": [
|
||||
{
|
||||
"type": "FunctionDeclaration",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 7,
|
||||
"column": 1
|
||||
}
|
||||
},
|
||||
"id": {
|
||||
"type": "Identifier",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 9
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 18
|
||||
}
|
||||
},
|
||||
"name": "Component",
|
||||
"typeAnnotation": null,
|
||||
"optional": false,
|
||||
"range": [
|
||||
9,
|
||||
18
|
||||
]
|
||||
},
|
||||
"params": [
|
||||
{
|
||||
"type": "Identifier",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 19
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 24
|
||||
}
|
||||
},
|
||||
"name": "props",
|
||||
"typeAnnotation": null,
|
||||
"optional": false,
|
||||
"range": [
|
||||
19,
|
||||
24
|
||||
]
|
||||
}
|
||||
],
|
||||
"body": {
|
||||
"type": "BlockStatement",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 26
|
||||
},
|
||||
"end": {
|
||||
"line": 7,
|
||||
"column": 1
|
||||
}
|
||||
},
|
||||
"body": [
|
||||
{
|
||||
"type": "VariableDeclaration",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 2,
|
||||
"column": 2
|
||||
},
|
||||
"end": {
|
||||
"line": 2,
|
||||
"column": 12
|
||||
}
|
||||
},
|
||||
"kind": "let",
|
||||
"declarations": [
|
||||
{
|
||||
"type": "VariableDeclarator",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 2,
|
||||
"column": 6
|
||||
},
|
||||
"end": {
|
||||
"line": 2,
|
||||
"column": 11
|
||||
}
|
||||
},
|
||||
"init": {
|
||||
"type": "Literal",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 2,
|
||||
"column": 10
|
||||
},
|
||||
"end": {
|
||||
"line": 2,
|
||||
"column": 11
|
||||
}
|
||||
},
|
||||
"value": 0,
|
||||
"range": [
|
||||
38,
|
||||
39
|
||||
],
|
||||
"raw": "0"
|
||||
},
|
||||
"id": {
|
||||
"type": "Identifier",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 2,
|
||||
"column": 6
|
||||
},
|
||||
"end": {
|
||||
"line": 2,
|
||||
"column": 7
|
||||
}
|
||||
},
|
||||
"name": "x",
|
||||
"typeAnnotation": null,
|
||||
"optional": false,
|
||||
"range": [
|
||||
34,
|
||||
35
|
||||
]
|
||||
},
|
||||
"range": [
|
||||
34,
|
||||
39
|
||||
]
|
||||
}
|
||||
],
|
||||
"range": [
|
||||
30,
|
||||
40
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "ForStatement",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 3,
|
||||
"column": 2
|
||||
},
|
||||
"end": {
|
||||
"line": 5,
|
||||
"column": 3
|
||||
}
|
||||
},
|
||||
"init": {
|
||||
"type": "VariableDeclaration",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 3,
|
||||
"column": 7
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 16
|
||||
}
|
||||
},
|
||||
"kind": "let",
|
||||
"declarations": [
|
||||
{
|
||||
"type": "VariableDeclarator",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 3,
|
||||
"column": 11
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 16
|
||||
}
|
||||
},
|
||||
"init": {
|
||||
"type": "Literal",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 3,
|
||||
"column": 15
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 16
|
||||
}
|
||||
},
|
||||
"value": 0,
|
||||
"range": [
|
||||
56,
|
||||
57
|
||||
],
|
||||
"raw": "0"
|
||||
},
|
||||
"id": {
|
||||
"type": "Identifier",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 3,
|
||||
"column": 11
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 12
|
||||
}
|
||||
},
|
||||
"name": "i",
|
||||
"typeAnnotation": null,
|
||||
"optional": false,
|
||||
"range": [
|
||||
52,
|
||||
53
|
||||
]
|
||||
},
|
||||
"range": [
|
||||
52,
|
||||
57
|
||||
]
|
||||
}
|
||||
],
|
||||
"range": [
|
||||
48,
|
||||
57
|
||||
]
|
||||
},
|
||||
"test": {
|
||||
"type": "BinaryExpression",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 3,
|
||||
"column": 18
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 24
|
||||
}
|
||||
},
|
||||
"left": {
|
||||
"type": "Identifier",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 3,
|
||||
"column": 18
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 19
|
||||
}
|
||||
},
|
||||
"name": "i",
|
||||
"typeAnnotation": null,
|
||||
"optional": false,
|
||||
"range": [
|
||||
59,
|
||||
60
|
||||
]
|
||||
},
|
||||
"right": {
|
||||
"type": "Literal",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 3,
|
||||
"column": 22
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 24
|
||||
}
|
||||
},
|
||||
"value": 10,
|
||||
"range": [
|
||||
63,
|
||||
65
|
||||
],
|
||||
"raw": "10"
|
||||
},
|
||||
"operator": "<",
|
||||
"range": [
|
||||
59,
|
||||
65
|
||||
]
|
||||
},
|
||||
"update": {
|
||||
"type": "UpdateExpression",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 3,
|
||||
"column": 26
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 29
|
||||
}
|
||||
},
|
||||
"operator": "++",
|
||||
"argument": {
|
||||
"type": "Identifier",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 3,
|
||||
"column": 26
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 27
|
||||
}
|
||||
},
|
||||
"name": "i",
|
||||
"typeAnnotation": null,
|
||||
"optional": false,
|
||||
"range": [
|
||||
67,
|
||||
68
|
||||
]
|
||||
},
|
||||
"prefix": false,
|
||||
"range": [
|
||||
67,
|
||||
70
|
||||
]
|
||||
},
|
||||
"body": {
|
||||
"type": "BlockStatement",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 3,
|
||||
"column": 31
|
||||
},
|
||||
"end": {
|
||||
"line": 5,
|
||||
"column": 3
|
||||
}
|
||||
},
|
||||
"body": [
|
||||
{
|
||||
"type": "ExpressionStatement",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 4,
|
||||
"column": 4
|
||||
},
|
||||
"end": {
|
||||
"line": 4,
|
||||
"column": 11
|
||||
}
|
||||
},
|
||||
"expression": {
|
||||
"type": "AssignmentExpression",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 4,
|
||||
"column": 4
|
||||
},
|
||||
"end": {
|
||||
"line": 4,
|
||||
"column": 10
|
||||
}
|
||||
},
|
||||
"operator": "+=",
|
||||
"left": {
|
||||
"type": "Identifier",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 4,
|
||||
"column": 4
|
||||
},
|
||||
"end": {
|
||||
"line": 4,
|
||||
"column": 5
|
||||
}
|
||||
},
|
||||
"name": "x",
|
||||
"typeAnnotation": null,
|
||||
"optional": false,
|
||||
"range": [
|
||||
78,
|
||||
79
|
||||
]
|
||||
},
|
||||
"right": {
|
||||
"type": "Identifier",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 4,
|
||||
"column": 9
|
||||
},
|
||||
"end": {
|
||||
"line": 4,
|
||||
"column": 10
|
||||
}
|
||||
},
|
||||
"name": "i",
|
||||
"typeAnnotation": null,
|
||||
"optional": false,
|
||||
"range": [
|
||||
83,
|
||||
84
|
||||
]
|
||||
},
|
||||
"range": [
|
||||
78,
|
||||
84
|
||||
]
|
||||
},
|
||||
"directive": null,
|
||||
"range": [
|
||||
78,
|
||||
85
|
||||
]
|
||||
}
|
||||
],
|
||||
"range": [
|
||||
72,
|
||||
89
|
||||
]
|
||||
},
|
||||
"range": [
|
||||
43,
|
||||
89
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "ReturnStatement",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 6,
|
||||
"column": 2
|
||||
},
|
||||
"end": {
|
||||
"line": 6,
|
||||
"column": 11
|
||||
}
|
||||
},
|
||||
"argument": {
|
||||
"type": "Identifier",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 6,
|
||||
"column": 9
|
||||
},
|
||||
"end": {
|
||||
"line": 6,
|
||||
"column": 10
|
||||
}
|
||||
},
|
||||
"name": "x",
|
||||
"typeAnnotation": null,
|
||||
"optional": false,
|
||||
"range": [
|
||||
99,
|
||||
100
|
||||
]
|
||||
},
|
||||
"range": [
|
||||
92,
|
||||
101
|
||||
]
|
||||
}
|
||||
],
|
||||
"range": [
|
||||
26,
|
||||
103
|
||||
]
|
||||
},
|
||||
"typeParameters": null,
|
||||
"returnType": null,
|
||||
"predicate": null,
|
||||
"generator": false,
|
||||
"async": false,
|
||||
"range": [
|
||||
0,
|
||||
103
|
||||
]
|
||||
}
|
||||
],
|
||||
"comments": [],
|
||||
"interpreter": null,
|
||||
"range": [
|
||||
0,
|
||||
103
|
||||
],
|
||||
"sourceType": "script"
|
||||
}
|
||||
@@ -1,104 +0,0 @@
|
||||
{
|
||||
"type": "Program",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 26
|
||||
}
|
||||
},
|
||||
"body": [
|
||||
{
|
||||
"type": "ImportDeclaration",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 26
|
||||
}
|
||||
},
|
||||
"specifiers": [
|
||||
{
|
||||
"type": "ImportDefaultSpecifier",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 7
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 12
|
||||
}
|
||||
},
|
||||
"local": {
|
||||
"type": "Identifier",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 7
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 12
|
||||
}
|
||||
},
|
||||
"name": "React",
|
||||
"typeAnnotation": null,
|
||||
"optional": false,
|
||||
"range": [
|
||||
7,
|
||||
12
|
||||
]
|
||||
},
|
||||
"range": [
|
||||
7,
|
||||
12
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": {
|
||||
"type": "Literal",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 18
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 25
|
||||
}
|
||||
},
|
||||
"value": "react",
|
||||
"range": [
|
||||
18,
|
||||
25
|
||||
],
|
||||
"raw": "'react'"
|
||||
},
|
||||
"attributes": [],
|
||||
"importKind": "value",
|
||||
"range": [
|
||||
0,
|
||||
26
|
||||
]
|
||||
}
|
||||
],
|
||||
"comments": [],
|
||||
"interpreter": null,
|
||||
"range": [
|
||||
0,
|
||||
26
|
||||
],
|
||||
"sourceType": "module"
|
||||
}
|
||||
@@ -1,189 +0,0 @@
|
||||
{
|
||||
"type": "Program",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 1
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
0,
|
||||
51
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"type": "FunctionDeclaration",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 1
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
0,
|
||||
51
|
||||
],
|
||||
"id": {
|
||||
"type": "Identifier",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 9
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 18
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
9,
|
||||
18
|
||||
],
|
||||
"name": "Component",
|
||||
"typeAnnotation": null,
|
||||
"optional": false
|
||||
},
|
||||
"params": [
|
||||
{
|
||||
"type": "Identifier",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 19
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 24
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
19,
|
||||
24
|
||||
],
|
||||
"name": "props",
|
||||
"typeAnnotation": null,
|
||||
"optional": false
|
||||
}
|
||||
],
|
||||
"body": {
|
||||
"type": "BlockStatement",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 26
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 1
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
26,
|
||||
51
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"type": "ReturnStatement",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 2,
|
||||
"column": 2
|
||||
},
|
||||
"end": {
|
||||
"line": 2,
|
||||
"column": 21
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
30,
|
||||
49
|
||||
],
|
||||
"argument": {
|
||||
"type": "MemberExpression",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 2,
|
||||
"column": 9
|
||||
},
|
||||
"end": {
|
||||
"line": 2,
|
||||
"column": 20
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
37,
|
||||
48
|
||||
],
|
||||
"object": {
|
||||
"type": "Identifier",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 2,
|
||||
"column": 9
|
||||
},
|
||||
"end": {
|
||||
"line": 2,
|
||||
"column": 14
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
37,
|
||||
42
|
||||
],
|
||||
"name": "props",
|
||||
"typeAnnotation": null,
|
||||
"optional": false
|
||||
},
|
||||
"property": {
|
||||
"type": "Identifier",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 2,
|
||||
"column": 15
|
||||
},
|
||||
"end": {
|
||||
"line": 2,
|
||||
"column": 20
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
43,
|
||||
48
|
||||
],
|
||||
"name": "value",
|
||||
"typeAnnotation": null,
|
||||
"optional": false
|
||||
},
|
||||
"computed": false
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"async": false,
|
||||
"generator": false,
|
||||
"predicate": null,
|
||||
"expression": false,
|
||||
"returnType": null,
|
||||
"typeParameters": null
|
||||
}
|
||||
],
|
||||
"comments": [],
|
||||
"errors": []
|
||||
}
|
||||
@@ -1,351 +0,0 @@
|
||||
{
|
||||
"type": "Program",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 2,
|
||||
"column": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 4,
|
||||
"column": 1
|
||||
}
|
||||
},
|
||||
"body": [
|
||||
{
|
||||
"type": "FunctionDeclaration",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 2,
|
||||
"column": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 4,
|
||||
"column": 1
|
||||
}
|
||||
},
|
||||
"id": {
|
||||
"type": "Identifier",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 2,
|
||||
"column": 9
|
||||
},
|
||||
"end": {
|
||||
"line": 2,
|
||||
"column": 12
|
||||
}
|
||||
},
|
||||
"name": "foo",
|
||||
"typeAnnotation": null,
|
||||
"optional": false,
|
||||
"range": [
|
||||
10,
|
||||
13
|
||||
]
|
||||
},
|
||||
"params": [],
|
||||
"body": {
|
||||
"type": "BlockStatement",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 2,
|
||||
"column": 15
|
||||
},
|
||||
"end": {
|
||||
"line": 4,
|
||||
"column": 1
|
||||
}
|
||||
},
|
||||
"body": [
|
||||
{
|
||||
"type": "ReturnStatement",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 3,
|
||||
"column": 2
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 36
|
||||
}
|
||||
},
|
||||
"argument": {
|
||||
"type": "JSXElement",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 3,
|
||||
"column": 9
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 36
|
||||
}
|
||||
},
|
||||
"openingElement": {
|
||||
"type": "JSXOpeningElement",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 3,
|
||||
"column": 9
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 26
|
||||
}
|
||||
},
|
||||
"name": {
|
||||
"type": "JSXMemberExpression",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 3,
|
||||
"column": 10
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 17
|
||||
}
|
||||
},
|
||||
"object": {
|
||||
"type": "JSXIdentifier",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 3,
|
||||
"column": 10
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 13
|
||||
}
|
||||
},
|
||||
"name": "Foo",
|
||||
"range": [
|
||||
28,
|
||||
31
|
||||
]
|
||||
},
|
||||
"property": {
|
||||
"type": "JSXIdentifier",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 3,
|
||||
"column": 14
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 17
|
||||
}
|
||||
},
|
||||
"name": "Bar",
|
||||
"range": [
|
||||
32,
|
||||
35
|
||||
]
|
||||
},
|
||||
"range": [
|
||||
28,
|
||||
35
|
||||
]
|
||||
},
|
||||
"attributes": [
|
||||
{
|
||||
"type": "JSXAttribute",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 3,
|
||||
"column": 18
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 24
|
||||
}
|
||||
},
|
||||
"name": {
|
||||
"type": "JSXIdentifier",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 3,
|
||||
"column": 18
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 19
|
||||
}
|
||||
},
|
||||
"name": "a",
|
||||
"range": [
|
||||
36,
|
||||
37
|
||||
]
|
||||
},
|
||||
"value": {
|
||||
"type": "JSXExpressionContainer",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 3,
|
||||
"column": 20
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 24
|
||||
}
|
||||
},
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 3,
|
||||
"column": 21
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 23
|
||||
}
|
||||
},
|
||||
"value": 10,
|
||||
"range": [
|
||||
39,
|
||||
41
|
||||
],
|
||||
"raw": "10"
|
||||
},
|
||||
"range": [
|
||||
38,
|
||||
42
|
||||
]
|
||||
},
|
||||
"range": [
|
||||
36,
|
||||
42
|
||||
]
|
||||
}
|
||||
],
|
||||
"selfClosing": false,
|
||||
"range": [
|
||||
27,
|
||||
44
|
||||
]
|
||||
},
|
||||
"children": [],
|
||||
"closingElement": {
|
||||
"type": "JSXClosingElement",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 3,
|
||||
"column": 26
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 36
|
||||
}
|
||||
},
|
||||
"name": {
|
||||
"type": "JSXMemberExpression",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 3,
|
||||
"column": 28
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 35
|
||||
}
|
||||
},
|
||||
"object": {
|
||||
"type": "JSXIdentifier",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 3,
|
||||
"column": 28
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 31
|
||||
}
|
||||
},
|
||||
"name": "Foo",
|
||||
"range": [
|
||||
46,
|
||||
49
|
||||
]
|
||||
},
|
||||
"property": {
|
||||
"type": "JSXIdentifier",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 3,
|
||||
"column": 32
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 35
|
||||
}
|
||||
},
|
||||
"name": "Bar",
|
||||
"range": [
|
||||
50,
|
||||
53
|
||||
]
|
||||
},
|
||||
"range": [
|
||||
46,
|
||||
53
|
||||
]
|
||||
},
|
||||
"range": [
|
||||
44,
|
||||
54
|
||||
]
|
||||
},
|
||||
"range": [
|
||||
27,
|
||||
54
|
||||
]
|
||||
},
|
||||
"range": [
|
||||
20,
|
||||
54
|
||||
]
|
||||
}
|
||||
],
|
||||
"range": [
|
||||
16,
|
||||
56
|
||||
]
|
||||
},
|
||||
"typeParameters": null,
|
||||
"returnType": null,
|
||||
"predicate": null,
|
||||
"generator": false,
|
||||
"async": false,
|
||||
"range": [
|
||||
1,
|
||||
56
|
||||
]
|
||||
}
|
||||
],
|
||||
"comments": [],
|
||||
"interpreter": null,
|
||||
"range": [
|
||||
1,
|
||||
56
|
||||
],
|
||||
"sourceType": "script"
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,149 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
// Manual extensions to generated types
|
||||
use crate::{
|
||||
ArrowFunctionExpression, Class, ClassDeclaration, ClassExpression, Function,
|
||||
FunctionDeclaration, FunctionExpression, ImportDeclarationSpecifier, JSXElementName,
|
||||
JSXMemberExpression, JSXMemberExpressionOrIdentifier, Pattern, SourceRange, SourceType,
|
||||
};
|
||||
|
||||
/// Sentinel trait to distinguish AST *node* types
|
||||
pub trait ESTreeNode {}
|
||||
|
||||
impl Default for SourceType {
|
||||
fn default() -> Self {
|
||||
Self::Module
|
||||
}
|
||||
}
|
||||
|
||||
impl Pattern {
|
||||
pub fn range(&self) -> Option<SourceRange> {
|
||||
match self {
|
||||
Self::ArrayPattern(pattern) => pattern.range,
|
||||
Self::AssignmentPattern(pattern) => pattern.range,
|
||||
Self::Identifier(pattern) => pattern.range,
|
||||
Self::ObjectPattern(pattern) => pattern.range,
|
||||
Self::RestElement(pattern) => pattern.range,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ImportDeclarationSpecifier {
|
||||
pub fn range(&self) -> Option<SourceRange> {
|
||||
match self {
|
||||
Self::ImportDefaultSpecifier(specifier) => specifier.range,
|
||||
Self::ImportNamespaceSpecifier(specifier) => specifier.range,
|
||||
Self::ImportSpecifier(specifier) => specifier.range,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl JSXElementName {
|
||||
pub fn root_name(&self) -> &str {
|
||||
match self {
|
||||
Self::JSXIdentifier(name) => &name.name,
|
||||
Self::JSXMemberExpression(name) => name.root_name(),
|
||||
Self::JSXNamespacedName(name) => &name.namespace.name,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl JSXMemberExpression {
|
||||
pub fn root_name(&self) -> &str {
|
||||
match &self.object {
|
||||
JSXMemberExpressionOrIdentifier::JSXMemberExpression(object) => object.root_name(),
|
||||
JSXMemberExpressionOrIdentifier::JSXIdentifier(object) => &object.name,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait IntoFunction: ESTreeNode {
|
||||
fn function(&self) -> &Function;
|
||||
|
||||
fn into_function(self) -> Function;
|
||||
}
|
||||
|
||||
impl IntoFunction for FunctionDeclaration {
|
||||
fn function(&self) -> &Function {
|
||||
&self.function
|
||||
}
|
||||
|
||||
fn into_function(self) -> Function {
|
||||
self.function
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoFunction for FunctionExpression {
|
||||
fn function(&self) -> &Function {
|
||||
&self.function
|
||||
}
|
||||
|
||||
fn into_function(self) -> Function {
|
||||
self.function
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoFunction for ArrowFunctionExpression {
|
||||
fn function(&self) -> &Function {
|
||||
&self.function
|
||||
}
|
||||
|
||||
fn into_function(self) -> Function {
|
||||
self.function
|
||||
}
|
||||
}
|
||||
|
||||
impl ESTreeNode for Function {}
|
||||
|
||||
impl IntoFunction for Function {
|
||||
fn function(&self) -> &Function {
|
||||
self
|
||||
}
|
||||
|
||||
fn into_function(self) -> Function {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
pub trait IntoClass: ESTreeNode {
|
||||
fn class(&self) -> &Class;
|
||||
|
||||
fn into_class(self) -> Class;
|
||||
}
|
||||
|
||||
impl IntoClass for ClassDeclaration {
|
||||
fn class(&self) -> &Class {
|
||||
&self.class
|
||||
}
|
||||
|
||||
fn into_class(self) -> Class {
|
||||
self.class
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoClass for ClassExpression {
|
||||
fn class(&self) -> &Class {
|
||||
&self.class
|
||||
}
|
||||
|
||||
fn into_class(self) -> Class {
|
||||
self.class
|
||||
}
|
||||
}
|
||||
|
||||
impl ESTreeNode for Class {}
|
||||
|
||||
impl IntoClass for Class {
|
||||
fn class(&self) -> &Class {
|
||||
self
|
||||
}
|
||||
|
||||
fn into_class(self) -> Class {
|
||||
self
|
||||
}
|
||||
}
|
||||
@@ -1,295 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
use serde::de::Visitor;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum JsValue {
|
||||
Boolean(bool),
|
||||
Null,
|
||||
Number(Number),
|
||||
String(String),
|
||||
Undefined,
|
||||
}
|
||||
|
||||
impl JsValue {
|
||||
pub fn is_truthy(&self) -> bool {
|
||||
match &self {
|
||||
JsValue::Boolean(value) => *value,
|
||||
JsValue::Number(value) => value.is_truthy(),
|
||||
JsValue::String(value) => !value.is_empty(),
|
||||
JsValue::Null => false,
|
||||
JsValue::Undefined => false,
|
||||
}
|
||||
}
|
||||
|
||||
// Partial implementation of loose equality for javascript, returns Some for supported
|
||||
// cases w the equality result, and None for unsupported cases
|
||||
pub fn loosely_equals(&self, other: &Self) -> Option<bool> {
|
||||
// https://tc39.es/ecma262/multipage/abstract-operations.html#sec-islooselyequal
|
||||
match (&self, &other) {
|
||||
// 1. If Type(x) is Type(y), then
|
||||
// a. Return IsStrictlyEqual(x, y).
|
||||
(JsValue::Number(left), JsValue::Number(right)) => Some(left.equals(*right)),
|
||||
(JsValue::Null, JsValue::Null) => Some(true),
|
||||
(JsValue::Undefined, JsValue::Undefined) => Some(true),
|
||||
(JsValue::Boolean(left), JsValue::Boolean(right)) => Some(left == right),
|
||||
(JsValue::String(left), JsValue::String(right)) => Some(left == right),
|
||||
|
||||
// 2. If x is null and y is undefined, return true.
|
||||
(JsValue::Null, JsValue::Undefined) => Some(true),
|
||||
|
||||
// 3. If x is undefined and y is null, return true.
|
||||
(JsValue::Undefined, JsValue::Null) => Some(true),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn not_loosely_equals(&self, other: &Self) -> Option<bool> {
|
||||
self.loosely_equals(other).map(|value| !value)
|
||||
}
|
||||
|
||||
// Complete implementation of strict equality for javascript
|
||||
pub fn strictly_equals(&self, other: &Self) -> bool {
|
||||
// https://tc39.es/ecma262/multipage/abstract-operations.html#sec-isstrictlyequal
|
||||
match (&self, &other) {
|
||||
(JsValue::Number(left), JsValue::Number(right)) => left.equals(*right),
|
||||
(JsValue::Null, JsValue::Null) => true,
|
||||
(JsValue::Undefined, JsValue::Undefined) => true,
|
||||
(JsValue::Boolean(left), JsValue::Boolean(right)) => left == right,
|
||||
(JsValue::String(left), JsValue::String(right)) => left == right,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn not_strictly_equals(&self, other: &Self) -> bool {
|
||||
!self.strictly_equals(other)
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for JsValue {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: serde::Serializer,
|
||||
{
|
||||
match self {
|
||||
Self::Boolean(b) => serializer.serialize_bool(*b),
|
||||
Self::Null => serializer.serialize_none(),
|
||||
Self::Number(n) => serializer.serialize_f64(n.into()),
|
||||
Self::String(s) => serializer.serialize_str(s),
|
||||
Self::Undefined => serializer.serialize_unit(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for JsValue {
|
||||
#[inline]
|
||||
fn deserialize<D>(deserializer: D) -> Result<JsValue, D::Error>
|
||||
where
|
||||
D: serde::Deserializer<'de>,
|
||||
{
|
||||
struct ValueVisitor;
|
||||
|
||||
impl<'de> Visitor<'de> for ValueVisitor {
|
||||
type Value = JsValue;
|
||||
|
||||
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
formatter.write_str("valid primitive JSON value (null, boolean, number, or string")
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_bool<E>(self, value: bool) -> Result<JsValue, E> {
|
||||
Ok(JsValue::Boolean(value))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_i64<E>(self, value: i64) -> Result<JsValue, E> {
|
||||
if (MIN_SAFE_INT..=MAX_SAFE_INT).contains(&value) {
|
||||
Ok(JsValue::Number((value as f64).into()))
|
||||
} else {
|
||||
panic!("Invalid number")
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_u64<E>(self, value: u64) -> Result<JsValue, E> {
|
||||
if value as i64 <= MAX_SAFE_INT {
|
||||
Ok(JsValue::Number((value as f64).into()))
|
||||
} else {
|
||||
panic!("Invalid number")
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_f64<E>(self, value: f64) -> Result<JsValue, E> {
|
||||
Ok(JsValue::Number(value.into()))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_str<E>(self, value: &str) -> Result<JsValue, E>
|
||||
where
|
||||
E: serde::de::Error,
|
||||
{
|
||||
self.visit_string(String::from(value))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_string<E>(self, value: String) -> Result<JsValue, E> {
|
||||
Ok(JsValue::String(value))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_none<E>(self) -> Result<JsValue, E> {
|
||||
Ok(JsValue::Null)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_some<D>(self, deserializer: D) -> Result<JsValue, D::Error>
|
||||
where
|
||||
D: serde::Deserializer<'de>,
|
||||
{
|
||||
Deserialize::deserialize(deserializer)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_unit<E>(self) -> Result<JsValue, E> {
|
||||
Ok(JsValue::Undefined)
|
||||
}
|
||||
}
|
||||
|
||||
deserializer.deserialize_any(ValueVisitor)
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents a JavaScript Number as its binary representation so that
|
||||
/// -1 == -1, NaN == Nan etc.
|
||||
/// Note: NaN is *always* represented as the f64::NAN constant to allow
|
||||
/// comparison of NaNs.
|
||||
#[derive(Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Debug, Hash)]
|
||||
pub struct Number(u64);
|
||||
|
||||
pub const MAX_SAFE_INT: i64 = 9007199254740991;
|
||||
pub const MIN_SAFE_INT: i64 = -9007199254740991;
|
||||
|
||||
impl From<f64> for Number {
|
||||
fn from(value: f64) -> Self {
|
||||
if value.is_nan() {
|
||||
Self(f64::NAN.to_bits())
|
||||
} else {
|
||||
Self(value.to_bits())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u32> for Number {
|
||||
fn from(value: u32) -> Self {
|
||||
f64::from(value).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Number> for f64 {
|
||||
fn from(number: Number) -> Self {
|
||||
let value = f64::from_bits(number.0);
|
||||
assert!(!f64::is_nan(value) || number.0 == f64::NAN.to_bits());
|
||||
value
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&Number> for f64 {
|
||||
fn from(number: &Number) -> Self {
|
||||
let value = f64::from_bits(number.0);
|
||||
assert!(!f64::is_nan(value) || number.0 == f64::NAN.to_bits());
|
||||
value
|
||||
}
|
||||
}
|
||||
|
||||
impl Number {
|
||||
pub fn equals(self, other: Self) -> bool {
|
||||
f64::from(self) == f64::from(other)
|
||||
}
|
||||
|
||||
pub fn not_equals(self, other: Self) -> bool {
|
||||
!self.equals(other)
|
||||
}
|
||||
|
||||
pub fn is_truthy(self) -> bool {
|
||||
let value = f64::from(self);
|
||||
!(self.0 == f64::NAN.to_bits() || value == 0.0 || value == -0.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Add for Number {
|
||||
type Output = Number;
|
||||
|
||||
fn add(self, rhs: Self) -> Self::Output {
|
||||
let result = f64::from(self) + f64::from(rhs);
|
||||
Self::from(result)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Sub for Number {
|
||||
type Output = Number;
|
||||
|
||||
fn sub(self, rhs: Self) -> Self::Output {
|
||||
let result = f64::from(self) - f64::from(rhs);
|
||||
Self::from(result)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Mul for Number {
|
||||
type Output = Number;
|
||||
|
||||
fn mul(self, rhs: Self) -> Self::Output {
|
||||
let result = f64::from(self) * f64::from(rhs);
|
||||
Self::from(result)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Div for Number {
|
||||
type Output = Number;
|
||||
|
||||
fn div(self, rhs: Self) -> Self::Output {
|
||||
let result = f64::from(self) / f64::from(rhs);
|
||||
Self::from(result)
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for Number {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: serde::Serializer,
|
||||
{
|
||||
serializer.serialize_f64(self.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for Number {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: serde::Deserializer<'de>,
|
||||
{
|
||||
struct ValueVisitor;
|
||||
|
||||
impl<'de> Visitor<'de> for ValueVisitor {
|
||||
type Value = Number;
|
||||
|
||||
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
formatter.write_str("value JavaScript number value")
|
||||
}
|
||||
|
||||
fn visit_f64<E>(self, v: f64) -> Result<Self::Value, E>
|
||||
where
|
||||
E: serde::de::Error,
|
||||
{
|
||||
Ok(v.into())
|
||||
}
|
||||
}
|
||||
|
||||
deserializer.deserialize_any(ValueVisitor)
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
mod binding;
|
||||
mod generated;
|
||||
mod generated_extensions;
|
||||
mod js_value;
|
||||
mod range;
|
||||
mod visit;
|
||||
|
||||
pub use binding::{Binding, BindingId};
|
||||
pub use generated::*;
|
||||
pub use generated_extensions::*;
|
||||
pub use js_value::{JsValue, Number};
|
||||
pub use range::SourceRange;
|
||||
pub use visit::*;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use insta::{assert_snapshot, glob};
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn fixtures() {
|
||||
glob!("fixtures/**.json", |path| {
|
||||
println!("{:?}", path);
|
||||
let input = std::fs::read_to_string(path).unwrap();
|
||||
let ast: Program = serde_json::from_str(&input).unwrap();
|
||||
let serialized = serde_json::to_string_pretty(&ast).unwrap();
|
||||
assert_snapshot!(format!("Input:\n{input}\n\nOutput:\n{serialized}"));
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
use std::num::NonZeroU32;
|
||||
|
||||
use serde::ser::SerializeTuple;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Deserialize, Copy, Clone, Debug, PartialEq, PartialOrd, Hash)]
|
||||
pub struct SourceRange {
|
||||
pub start: u32,
|
||||
pub end: NonZeroU32,
|
||||
}
|
||||
|
||||
// ESTree and Babel store the `range` as `[start, end]`, so we customize
|
||||
// the serialization to use a tuple representation.
|
||||
impl Serialize for SourceRange {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: serde::Serializer,
|
||||
{
|
||||
let mut tuple = serializer.serialize_tuple(2)?;
|
||||
tuple.serialize_element(&self.start)?;
|
||||
tuple.serialize_element(&self.end)?;
|
||||
tuple.end()
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,213 +0,0 @@
|
||||
---
|
||||
source: crates/react_estree/src/lib.rs
|
||||
expression: "format!(\"Input:\\n{input}\\n\\nOutput:\\n{serialized}\")"
|
||||
input_file: crates/react_estree/src/fixtures/import.json
|
||||
---
|
||||
Input:
|
||||
{
|
||||
"type": "Program",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 26
|
||||
}
|
||||
},
|
||||
"body": [
|
||||
{
|
||||
"type": "ImportDeclaration",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 26
|
||||
}
|
||||
},
|
||||
"specifiers": [
|
||||
{
|
||||
"type": "ImportDefaultSpecifier",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 7
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 12
|
||||
}
|
||||
},
|
||||
"local": {
|
||||
"type": "Identifier",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 7
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 12
|
||||
}
|
||||
},
|
||||
"name": "React",
|
||||
"typeAnnotation": null,
|
||||
"optional": false,
|
||||
"range": [
|
||||
7,
|
||||
12
|
||||
]
|
||||
},
|
||||
"range": [
|
||||
7,
|
||||
12
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": {
|
||||
"type": "Literal",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 18
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 25
|
||||
}
|
||||
},
|
||||
"value": "react",
|
||||
"range": [
|
||||
18,
|
||||
25
|
||||
],
|
||||
"raw": "'react'"
|
||||
},
|
||||
"attributes": [],
|
||||
"importKind": "value",
|
||||
"range": [
|
||||
0,
|
||||
26
|
||||
]
|
||||
}
|
||||
],
|
||||
"comments": [],
|
||||
"interpreter": null,
|
||||
"range": [
|
||||
0,
|
||||
26
|
||||
],
|
||||
"sourceType": "module"
|
||||
}
|
||||
|
||||
Output:
|
||||
{
|
||||
"type": "Program",
|
||||
"body": [
|
||||
{
|
||||
"type": "ImportDeclaration",
|
||||
"specifiers": [
|
||||
{
|
||||
"type": "ImportDefaultSpecifier",
|
||||
"local": {
|
||||
"type": "Identifier",
|
||||
"name": "React",
|
||||
"typeAnnotation": null,
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 7
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 12
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
7,
|
||||
12
|
||||
]
|
||||
},
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 7
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 12
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
7,
|
||||
12
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": {
|
||||
"type": "Literal",
|
||||
"value": "react",
|
||||
"raw": "'react'",
|
||||
"regex": null,
|
||||
"bigint": null,
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 18
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 25
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
18,
|
||||
25
|
||||
]
|
||||
},
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 26
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
0,
|
||||
26
|
||||
]
|
||||
}
|
||||
],
|
||||
"sourceType": "module",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 26
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
0,
|
||||
26
|
||||
]
|
||||
}
|
||||
@@ -1,379 +0,0 @@
|
||||
---
|
||||
source: crates/react_estree/src/lib.rs
|
||||
expression: "format!(\"Input:\\n{input}\\n\\nOutput:\\n{serialized}\")"
|
||||
input_file: crates/react_estree/src/fixtures/simple.json
|
||||
---
|
||||
Input:
|
||||
{
|
||||
"type": "Program",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 1
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
0,
|
||||
51
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"type": "FunctionDeclaration",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 1
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
0,
|
||||
51
|
||||
],
|
||||
"id": {
|
||||
"type": "Identifier",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 9
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 18
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
9,
|
||||
18
|
||||
],
|
||||
"name": "Component",
|
||||
"typeAnnotation": null,
|
||||
"optional": false
|
||||
},
|
||||
"params": [
|
||||
{
|
||||
"type": "Identifier",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 19
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 24
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
19,
|
||||
24
|
||||
],
|
||||
"name": "props",
|
||||
"typeAnnotation": null,
|
||||
"optional": false
|
||||
}
|
||||
],
|
||||
"body": {
|
||||
"type": "BlockStatement",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 26
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 1
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
26,
|
||||
51
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"type": "ReturnStatement",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 2,
|
||||
"column": 2
|
||||
},
|
||||
"end": {
|
||||
"line": 2,
|
||||
"column": 21
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
30,
|
||||
49
|
||||
],
|
||||
"argument": {
|
||||
"type": "MemberExpression",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 2,
|
||||
"column": 9
|
||||
},
|
||||
"end": {
|
||||
"line": 2,
|
||||
"column": 20
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
37,
|
||||
48
|
||||
],
|
||||
"object": {
|
||||
"type": "Identifier",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 2,
|
||||
"column": 9
|
||||
},
|
||||
"end": {
|
||||
"line": 2,
|
||||
"column": 14
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
37,
|
||||
42
|
||||
],
|
||||
"name": "props",
|
||||
"typeAnnotation": null,
|
||||
"optional": false
|
||||
},
|
||||
"property": {
|
||||
"type": "Identifier",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 2,
|
||||
"column": 15
|
||||
},
|
||||
"end": {
|
||||
"line": 2,
|
||||
"column": 20
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
43,
|
||||
48
|
||||
],
|
||||
"name": "value",
|
||||
"typeAnnotation": null,
|
||||
"optional": false
|
||||
},
|
||||
"computed": false
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"async": false,
|
||||
"generator": false,
|
||||
"predicate": null,
|
||||
"expression": false,
|
||||
"returnType": null,
|
||||
"typeParameters": null
|
||||
}
|
||||
],
|
||||
"comments": [],
|
||||
"errors": []
|
||||
}
|
||||
|
||||
Output:
|
||||
{
|
||||
"type": "Program",
|
||||
"body": [
|
||||
{
|
||||
"type": "FunctionDeclaration",
|
||||
"id": {
|
||||
"type": "Identifier",
|
||||
"name": "Component",
|
||||
"typeAnnotation": null,
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 9
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 18
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
9,
|
||||
18
|
||||
]
|
||||
},
|
||||
"params": [
|
||||
{
|
||||
"type": "Identifier",
|
||||
"name": "props",
|
||||
"typeAnnotation": null,
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 19
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 24
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
19,
|
||||
24
|
||||
]
|
||||
}
|
||||
],
|
||||
"body": {
|
||||
"type": "BlockStatement",
|
||||
"body": [
|
||||
{
|
||||
"type": "ReturnStatement",
|
||||
"argument": {
|
||||
"type": "MemberExpression",
|
||||
"object": {
|
||||
"type": "Identifier",
|
||||
"name": "props",
|
||||
"typeAnnotation": null,
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 2,
|
||||
"column": 9
|
||||
},
|
||||
"end": {
|
||||
"line": 2,
|
||||
"column": 14
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
37,
|
||||
42
|
||||
]
|
||||
},
|
||||
"property": {
|
||||
"type": "Identifier",
|
||||
"name": "value",
|
||||
"typeAnnotation": null,
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 2,
|
||||
"column": 15
|
||||
},
|
||||
"end": {
|
||||
"line": 2,
|
||||
"column": 20
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
43,
|
||||
48
|
||||
]
|
||||
},
|
||||
"computed": false,
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 2,
|
||||
"column": 9
|
||||
},
|
||||
"end": {
|
||||
"line": 2,
|
||||
"column": 20
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
37,
|
||||
48
|
||||
]
|
||||
},
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 2,
|
||||
"column": 2
|
||||
},
|
||||
"end": {
|
||||
"line": 2,
|
||||
"column": 21
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
30,
|
||||
49
|
||||
]
|
||||
}
|
||||
],
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 26
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 1
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
26,
|
||||
51
|
||||
]
|
||||
},
|
||||
"generator": false,
|
||||
"async": false,
|
||||
"loc": null,
|
||||
"range": null,
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 1
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
0,
|
||||
51
|
||||
]
|
||||
}
|
||||
],
|
||||
"sourceType": "module",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 1
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
0,
|
||||
51
|
||||
]
|
||||
}
|
||||
@@ -1,708 +0,0 @@
|
||||
---
|
||||
source: crates/react_estree/src/lib.rs
|
||||
expression: "format!(\"Input:\\n{input}\\n\\nOutput:\\n{serialized}\")"
|
||||
input_file: crates/react_estree/src/fixtures/test.json
|
||||
---
|
||||
Input:
|
||||
{
|
||||
"type": "Program",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 2,
|
||||
"column": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 4,
|
||||
"column": 1
|
||||
}
|
||||
},
|
||||
"body": [
|
||||
{
|
||||
"type": "FunctionDeclaration",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 2,
|
||||
"column": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 4,
|
||||
"column": 1
|
||||
}
|
||||
},
|
||||
"id": {
|
||||
"type": "Identifier",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 2,
|
||||
"column": 9
|
||||
},
|
||||
"end": {
|
||||
"line": 2,
|
||||
"column": 12
|
||||
}
|
||||
},
|
||||
"name": "foo",
|
||||
"typeAnnotation": null,
|
||||
"optional": false,
|
||||
"range": [
|
||||
10,
|
||||
13
|
||||
]
|
||||
},
|
||||
"params": [],
|
||||
"body": {
|
||||
"type": "BlockStatement",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 2,
|
||||
"column": 15
|
||||
},
|
||||
"end": {
|
||||
"line": 4,
|
||||
"column": 1
|
||||
}
|
||||
},
|
||||
"body": [
|
||||
{
|
||||
"type": "ReturnStatement",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 3,
|
||||
"column": 2
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 36
|
||||
}
|
||||
},
|
||||
"argument": {
|
||||
"type": "JSXElement",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 3,
|
||||
"column": 9
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 36
|
||||
}
|
||||
},
|
||||
"openingElement": {
|
||||
"type": "JSXOpeningElement",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 3,
|
||||
"column": 9
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 26
|
||||
}
|
||||
},
|
||||
"name": {
|
||||
"type": "JSXMemberExpression",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 3,
|
||||
"column": 10
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 17
|
||||
}
|
||||
},
|
||||
"object": {
|
||||
"type": "JSXIdentifier",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 3,
|
||||
"column": 10
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 13
|
||||
}
|
||||
},
|
||||
"name": "Foo",
|
||||
"range": [
|
||||
28,
|
||||
31
|
||||
]
|
||||
},
|
||||
"property": {
|
||||
"type": "JSXIdentifier",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 3,
|
||||
"column": 14
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 17
|
||||
}
|
||||
},
|
||||
"name": "Bar",
|
||||
"range": [
|
||||
32,
|
||||
35
|
||||
]
|
||||
},
|
||||
"range": [
|
||||
28,
|
||||
35
|
||||
]
|
||||
},
|
||||
"attributes": [
|
||||
{
|
||||
"type": "JSXAttribute",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 3,
|
||||
"column": 18
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 24
|
||||
}
|
||||
},
|
||||
"name": {
|
||||
"type": "JSXIdentifier",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 3,
|
||||
"column": 18
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 19
|
||||
}
|
||||
},
|
||||
"name": "a",
|
||||
"range": [
|
||||
36,
|
||||
37
|
||||
]
|
||||
},
|
||||
"value": {
|
||||
"type": "JSXExpressionContainer",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 3,
|
||||
"column": 20
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 24
|
||||
}
|
||||
},
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 3,
|
||||
"column": 21
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 23
|
||||
}
|
||||
},
|
||||
"value": 10,
|
||||
"range": [
|
||||
39,
|
||||
41
|
||||
],
|
||||
"raw": "10"
|
||||
},
|
||||
"range": [
|
||||
38,
|
||||
42
|
||||
]
|
||||
},
|
||||
"range": [
|
||||
36,
|
||||
42
|
||||
]
|
||||
}
|
||||
],
|
||||
"selfClosing": false,
|
||||
"range": [
|
||||
27,
|
||||
44
|
||||
]
|
||||
},
|
||||
"children": [],
|
||||
"closingElement": {
|
||||
"type": "JSXClosingElement",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 3,
|
||||
"column": 26
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 36
|
||||
}
|
||||
},
|
||||
"name": {
|
||||
"type": "JSXMemberExpression",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 3,
|
||||
"column": 28
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 35
|
||||
}
|
||||
},
|
||||
"object": {
|
||||
"type": "JSXIdentifier",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 3,
|
||||
"column": 28
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 31
|
||||
}
|
||||
},
|
||||
"name": "Foo",
|
||||
"range": [
|
||||
46,
|
||||
49
|
||||
]
|
||||
},
|
||||
"property": {
|
||||
"type": "JSXIdentifier",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 3,
|
||||
"column": 32
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 35
|
||||
}
|
||||
},
|
||||
"name": "Bar",
|
||||
"range": [
|
||||
50,
|
||||
53
|
||||
]
|
||||
},
|
||||
"range": [
|
||||
46,
|
||||
53
|
||||
]
|
||||
},
|
||||
"range": [
|
||||
44,
|
||||
54
|
||||
]
|
||||
},
|
||||
"range": [
|
||||
27,
|
||||
54
|
||||
]
|
||||
},
|
||||
"range": [
|
||||
20,
|
||||
54
|
||||
]
|
||||
}
|
||||
],
|
||||
"range": [
|
||||
16,
|
||||
56
|
||||
]
|
||||
},
|
||||
"typeParameters": null,
|
||||
"returnType": null,
|
||||
"predicate": null,
|
||||
"generator": false,
|
||||
"async": false,
|
||||
"range": [
|
||||
1,
|
||||
56
|
||||
]
|
||||
}
|
||||
],
|
||||
"comments": [],
|
||||
"interpreter": null,
|
||||
"range": [
|
||||
1,
|
||||
56
|
||||
],
|
||||
"sourceType": "script"
|
||||
}
|
||||
|
||||
Output:
|
||||
{
|
||||
"type": "Program",
|
||||
"body": [
|
||||
{
|
||||
"type": "FunctionDeclaration",
|
||||
"id": {
|
||||
"type": "Identifier",
|
||||
"name": "foo",
|
||||
"typeAnnotation": null,
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 2,
|
||||
"column": 9
|
||||
},
|
||||
"end": {
|
||||
"line": 2,
|
||||
"column": 12
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
10,
|
||||
13
|
||||
]
|
||||
},
|
||||
"params": [],
|
||||
"body": {
|
||||
"type": "BlockStatement",
|
||||
"body": [
|
||||
{
|
||||
"type": "ReturnStatement",
|
||||
"argument": {
|
||||
"type": "JSXElement",
|
||||
"openingElement": {
|
||||
"type": "JSXOpeningElement",
|
||||
"name": {
|
||||
"type": "JSXMemberExpression",
|
||||
"object": {
|
||||
"type": "JSXIdentifier",
|
||||
"name": "Foo",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 3,
|
||||
"column": 10
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 13
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
28,
|
||||
31
|
||||
]
|
||||
},
|
||||
"property": {
|
||||
"type": "JSXIdentifier",
|
||||
"name": "Bar",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 3,
|
||||
"column": 14
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 17
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
32,
|
||||
35
|
||||
]
|
||||
},
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 3,
|
||||
"column": 10
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 17
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
28,
|
||||
35
|
||||
]
|
||||
},
|
||||
"attributes": [
|
||||
{
|
||||
"type": "JSXAttribute",
|
||||
"name": {
|
||||
"type": "JSXIdentifier",
|
||||
"name": "a",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 3,
|
||||
"column": 18
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 19
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
36,
|
||||
37
|
||||
]
|
||||
},
|
||||
"value": {
|
||||
"type": "JSXExpressionContainer",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": 10.0,
|
||||
"raw": "10",
|
||||
"regex": null,
|
||||
"bigint": null,
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 3,
|
||||
"column": 21
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 23
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
39,
|
||||
41
|
||||
]
|
||||
},
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 3,
|
||||
"column": 20
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 24
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
38,
|
||||
42
|
||||
]
|
||||
},
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 3,
|
||||
"column": 18
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 24
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
36,
|
||||
42
|
||||
]
|
||||
}
|
||||
],
|
||||
"selfClosing": false,
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 3,
|
||||
"column": 9
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 26
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
27,
|
||||
44
|
||||
]
|
||||
},
|
||||
"children": [],
|
||||
"closingElement": {
|
||||
"type": "JSXClosingElement",
|
||||
"name": {
|
||||
"type": "JSXMemberExpression",
|
||||
"object": {
|
||||
"type": "JSXIdentifier",
|
||||
"name": "Foo",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 3,
|
||||
"column": 28
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 31
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
46,
|
||||
49
|
||||
]
|
||||
},
|
||||
"property": {
|
||||
"type": "JSXIdentifier",
|
||||
"name": "Bar",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 3,
|
||||
"column": 32
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 35
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
50,
|
||||
53
|
||||
]
|
||||
},
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 3,
|
||||
"column": 28
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 35
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
46,
|
||||
53
|
||||
]
|
||||
},
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 3,
|
||||
"column": 26
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 36
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
44,
|
||||
54
|
||||
]
|
||||
},
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 3,
|
||||
"column": 9
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 36
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
27,
|
||||
54
|
||||
]
|
||||
},
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 3,
|
||||
"column": 2
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 36
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
20,
|
||||
54
|
||||
]
|
||||
}
|
||||
],
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 2,
|
||||
"column": 15
|
||||
},
|
||||
"end": {
|
||||
"line": 4,
|
||||
"column": 1
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
16,
|
||||
56
|
||||
]
|
||||
},
|
||||
"generator": false,
|
||||
"async": false,
|
||||
"loc": null,
|
||||
"range": null,
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 2,
|
||||
"column": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 4,
|
||||
"column": 1
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
1,
|
||||
56
|
||||
]
|
||||
}
|
||||
],
|
||||
"sourceType": "script",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 2,
|
||||
"column": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 4,
|
||||
"column": 1
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
1,
|
||||
56
|
||||
]
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,213 +0,0 @@
|
||||
---
|
||||
source: crates/react_estree/src/lib.rs
|
||||
expression: "format!(\"Input:\\n{input}\\n\\nOutput:\\n{serialized}\")"
|
||||
input_file: crates/react_estree/src/fixtures/import.json
|
||||
---
|
||||
Input:
|
||||
{
|
||||
"type": "Program",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 26
|
||||
}
|
||||
},
|
||||
"body": [
|
||||
{
|
||||
"type": "ImportDeclaration",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 26
|
||||
}
|
||||
},
|
||||
"specifiers": [
|
||||
{
|
||||
"type": "ImportDefaultSpecifier",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 7
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 12
|
||||
}
|
||||
},
|
||||
"local": {
|
||||
"type": "Identifier",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 7
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 12
|
||||
}
|
||||
},
|
||||
"name": "React",
|
||||
"typeAnnotation": null,
|
||||
"optional": false,
|
||||
"range": [
|
||||
7,
|
||||
12
|
||||
]
|
||||
},
|
||||
"range": [
|
||||
7,
|
||||
12
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": {
|
||||
"type": "Literal",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 18
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 25
|
||||
}
|
||||
},
|
||||
"value": "react",
|
||||
"range": [
|
||||
18,
|
||||
25
|
||||
],
|
||||
"raw": "'react'"
|
||||
},
|
||||
"attributes": [],
|
||||
"importKind": "value",
|
||||
"range": [
|
||||
0,
|
||||
26
|
||||
]
|
||||
}
|
||||
],
|
||||
"comments": [],
|
||||
"interpreter": null,
|
||||
"range": [
|
||||
0,
|
||||
26
|
||||
],
|
||||
"sourceType": "module"
|
||||
}
|
||||
|
||||
Output:
|
||||
{
|
||||
"type": "Program",
|
||||
"body": [
|
||||
{
|
||||
"type": "ImportDeclaration",
|
||||
"specifiers": [
|
||||
{
|
||||
"type": "ImportDefaultSpecifier",
|
||||
"local": {
|
||||
"type": "Identifier",
|
||||
"name": "React",
|
||||
"typeAnnotation": null,
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 7
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 12
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
7,
|
||||
12
|
||||
]
|
||||
},
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 7
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 12
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
7,
|
||||
12
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": {
|
||||
"type": "Literal",
|
||||
"value": "react",
|
||||
"raw": "'react'",
|
||||
"regex": null,
|
||||
"bigint": null,
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 18
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 25
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
18,
|
||||
25
|
||||
]
|
||||
},
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 26
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
0,
|
||||
26
|
||||
]
|
||||
}
|
||||
],
|
||||
"sourceType": "module",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 26
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
0,
|
||||
26
|
||||
]
|
||||
}
|
||||
@@ -1,379 +0,0 @@
|
||||
---
|
||||
source: crates/react_estree/src/lib.rs
|
||||
expression: "format!(\"Input:\\n{input}\\n\\nOutput:\\n{serialized}\")"
|
||||
input_file: crates/react_estree/src/fixtures/simple.json
|
||||
---
|
||||
Input:
|
||||
{
|
||||
"type": "Program",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 1
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
0,
|
||||
51
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"type": "FunctionDeclaration",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 1
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
0,
|
||||
51
|
||||
],
|
||||
"id": {
|
||||
"type": "Identifier",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 9
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 18
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
9,
|
||||
18
|
||||
],
|
||||
"name": "Component",
|
||||
"typeAnnotation": null,
|
||||
"optional": false
|
||||
},
|
||||
"params": [
|
||||
{
|
||||
"type": "Identifier",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 19
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 24
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
19,
|
||||
24
|
||||
],
|
||||
"name": "props",
|
||||
"typeAnnotation": null,
|
||||
"optional": false
|
||||
}
|
||||
],
|
||||
"body": {
|
||||
"type": "BlockStatement",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 26
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 1
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
26,
|
||||
51
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"type": "ReturnStatement",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 2,
|
||||
"column": 2
|
||||
},
|
||||
"end": {
|
||||
"line": 2,
|
||||
"column": 21
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
30,
|
||||
49
|
||||
],
|
||||
"argument": {
|
||||
"type": "MemberExpression",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 2,
|
||||
"column": 9
|
||||
},
|
||||
"end": {
|
||||
"line": 2,
|
||||
"column": 20
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
37,
|
||||
48
|
||||
],
|
||||
"object": {
|
||||
"type": "Identifier",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 2,
|
||||
"column": 9
|
||||
},
|
||||
"end": {
|
||||
"line": 2,
|
||||
"column": 14
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
37,
|
||||
42
|
||||
],
|
||||
"name": "props",
|
||||
"typeAnnotation": null,
|
||||
"optional": false
|
||||
},
|
||||
"property": {
|
||||
"type": "Identifier",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 2,
|
||||
"column": 15
|
||||
},
|
||||
"end": {
|
||||
"line": 2,
|
||||
"column": 20
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
43,
|
||||
48
|
||||
],
|
||||
"name": "value",
|
||||
"typeAnnotation": null,
|
||||
"optional": false
|
||||
},
|
||||
"computed": false
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"async": false,
|
||||
"generator": false,
|
||||
"predicate": null,
|
||||
"expression": false,
|
||||
"returnType": null,
|
||||
"typeParameters": null
|
||||
}
|
||||
],
|
||||
"comments": [],
|
||||
"errors": []
|
||||
}
|
||||
|
||||
Output:
|
||||
{
|
||||
"type": "Program",
|
||||
"body": [
|
||||
{
|
||||
"type": "FunctionDeclaration",
|
||||
"id": {
|
||||
"type": "Identifier",
|
||||
"name": "Component",
|
||||
"typeAnnotation": null,
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 9
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 18
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
9,
|
||||
18
|
||||
]
|
||||
},
|
||||
"params": [
|
||||
{
|
||||
"type": "Identifier",
|
||||
"name": "props",
|
||||
"typeAnnotation": null,
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 19
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 24
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
19,
|
||||
24
|
||||
]
|
||||
}
|
||||
],
|
||||
"body": {
|
||||
"type": "BlockStatement",
|
||||
"body": [
|
||||
{
|
||||
"type": "ReturnStatement",
|
||||
"argument": {
|
||||
"type": "MemberExpression",
|
||||
"object": {
|
||||
"type": "Identifier",
|
||||
"name": "props",
|
||||
"typeAnnotation": null,
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 2,
|
||||
"column": 9
|
||||
},
|
||||
"end": {
|
||||
"line": 2,
|
||||
"column": 14
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
37,
|
||||
42
|
||||
]
|
||||
},
|
||||
"property": {
|
||||
"type": "Identifier",
|
||||
"name": "value",
|
||||
"typeAnnotation": null,
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 2,
|
||||
"column": 15
|
||||
},
|
||||
"end": {
|
||||
"line": 2,
|
||||
"column": 20
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
43,
|
||||
48
|
||||
]
|
||||
},
|
||||
"computed": false,
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 2,
|
||||
"column": 9
|
||||
},
|
||||
"end": {
|
||||
"line": 2,
|
||||
"column": 20
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
37,
|
||||
48
|
||||
]
|
||||
},
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 2,
|
||||
"column": 2
|
||||
},
|
||||
"end": {
|
||||
"line": 2,
|
||||
"column": 21
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
30,
|
||||
49
|
||||
]
|
||||
}
|
||||
],
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 26
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 1
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
26,
|
||||
51
|
||||
]
|
||||
},
|
||||
"generator": false,
|
||||
"async": false,
|
||||
"loc": null,
|
||||
"range": null,
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 1
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
0,
|
||||
51
|
||||
]
|
||||
}
|
||||
],
|
||||
"sourceType": "module",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 1
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
0,
|
||||
51
|
||||
]
|
||||
}
|
||||
@@ -1,708 +0,0 @@
|
||||
---
|
||||
source: crates/react_estree/src/lib.rs
|
||||
expression: "format!(\"Input:\\n{input}\\n\\nOutput:\\n{serialized}\")"
|
||||
input_file: crates/react_estree/src/fixtures/test.json
|
||||
---
|
||||
Input:
|
||||
{
|
||||
"type": "Program",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 2,
|
||||
"column": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 4,
|
||||
"column": 1
|
||||
}
|
||||
},
|
||||
"body": [
|
||||
{
|
||||
"type": "FunctionDeclaration",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 2,
|
||||
"column": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 4,
|
||||
"column": 1
|
||||
}
|
||||
},
|
||||
"id": {
|
||||
"type": "Identifier",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 2,
|
||||
"column": 9
|
||||
},
|
||||
"end": {
|
||||
"line": 2,
|
||||
"column": 12
|
||||
}
|
||||
},
|
||||
"name": "foo",
|
||||
"typeAnnotation": null,
|
||||
"optional": false,
|
||||
"range": [
|
||||
10,
|
||||
13
|
||||
]
|
||||
},
|
||||
"params": [],
|
||||
"body": {
|
||||
"type": "BlockStatement",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 2,
|
||||
"column": 15
|
||||
},
|
||||
"end": {
|
||||
"line": 4,
|
||||
"column": 1
|
||||
}
|
||||
},
|
||||
"body": [
|
||||
{
|
||||
"type": "ReturnStatement",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 3,
|
||||
"column": 2
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 36
|
||||
}
|
||||
},
|
||||
"argument": {
|
||||
"type": "JSXElement",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 3,
|
||||
"column": 9
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 36
|
||||
}
|
||||
},
|
||||
"openingElement": {
|
||||
"type": "JSXOpeningElement",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 3,
|
||||
"column": 9
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 26
|
||||
}
|
||||
},
|
||||
"name": {
|
||||
"type": "JSXMemberExpression",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 3,
|
||||
"column": 10
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 17
|
||||
}
|
||||
},
|
||||
"object": {
|
||||
"type": "JSXIdentifier",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 3,
|
||||
"column": 10
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 13
|
||||
}
|
||||
},
|
||||
"name": "Foo",
|
||||
"range": [
|
||||
28,
|
||||
31
|
||||
]
|
||||
},
|
||||
"property": {
|
||||
"type": "JSXIdentifier",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 3,
|
||||
"column": 14
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 17
|
||||
}
|
||||
},
|
||||
"name": "Bar",
|
||||
"range": [
|
||||
32,
|
||||
35
|
||||
]
|
||||
},
|
||||
"range": [
|
||||
28,
|
||||
35
|
||||
]
|
||||
},
|
||||
"attributes": [
|
||||
{
|
||||
"type": "JSXAttribute",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 3,
|
||||
"column": 18
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 24
|
||||
}
|
||||
},
|
||||
"name": {
|
||||
"type": "JSXIdentifier",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 3,
|
||||
"column": 18
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 19
|
||||
}
|
||||
},
|
||||
"name": "a",
|
||||
"range": [
|
||||
36,
|
||||
37
|
||||
]
|
||||
},
|
||||
"value": {
|
||||
"type": "JSXExpressionContainer",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 3,
|
||||
"column": 20
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 24
|
||||
}
|
||||
},
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 3,
|
||||
"column": 21
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 23
|
||||
}
|
||||
},
|
||||
"value": 10,
|
||||
"range": [
|
||||
39,
|
||||
41
|
||||
],
|
||||
"raw": "10"
|
||||
},
|
||||
"range": [
|
||||
38,
|
||||
42
|
||||
]
|
||||
},
|
||||
"range": [
|
||||
36,
|
||||
42
|
||||
]
|
||||
}
|
||||
],
|
||||
"selfClosing": false,
|
||||
"range": [
|
||||
27,
|
||||
44
|
||||
]
|
||||
},
|
||||
"children": [],
|
||||
"closingElement": {
|
||||
"type": "JSXClosingElement",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 3,
|
||||
"column": 26
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 36
|
||||
}
|
||||
},
|
||||
"name": {
|
||||
"type": "JSXMemberExpression",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 3,
|
||||
"column": 28
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 35
|
||||
}
|
||||
},
|
||||
"object": {
|
||||
"type": "JSXIdentifier",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 3,
|
||||
"column": 28
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 31
|
||||
}
|
||||
},
|
||||
"name": "Foo",
|
||||
"range": [
|
||||
46,
|
||||
49
|
||||
]
|
||||
},
|
||||
"property": {
|
||||
"type": "JSXIdentifier",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 3,
|
||||
"column": 32
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 35
|
||||
}
|
||||
},
|
||||
"name": "Bar",
|
||||
"range": [
|
||||
50,
|
||||
53
|
||||
]
|
||||
},
|
||||
"range": [
|
||||
46,
|
||||
53
|
||||
]
|
||||
},
|
||||
"range": [
|
||||
44,
|
||||
54
|
||||
]
|
||||
},
|
||||
"range": [
|
||||
27,
|
||||
54
|
||||
]
|
||||
},
|
||||
"range": [
|
||||
20,
|
||||
54
|
||||
]
|
||||
}
|
||||
],
|
||||
"range": [
|
||||
16,
|
||||
56
|
||||
]
|
||||
},
|
||||
"typeParameters": null,
|
||||
"returnType": null,
|
||||
"predicate": null,
|
||||
"generator": false,
|
||||
"async": false,
|
||||
"range": [
|
||||
1,
|
||||
56
|
||||
]
|
||||
}
|
||||
],
|
||||
"comments": [],
|
||||
"interpreter": null,
|
||||
"range": [
|
||||
1,
|
||||
56
|
||||
],
|
||||
"sourceType": "script"
|
||||
}
|
||||
|
||||
Output:
|
||||
{
|
||||
"type": "Program",
|
||||
"body": [
|
||||
{
|
||||
"type": "FunctionDeclaration",
|
||||
"id": {
|
||||
"type": "Identifier",
|
||||
"name": "foo",
|
||||
"typeAnnotation": null,
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 2,
|
||||
"column": 9
|
||||
},
|
||||
"end": {
|
||||
"line": 2,
|
||||
"column": 12
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
10,
|
||||
13
|
||||
]
|
||||
},
|
||||
"params": [],
|
||||
"body": {
|
||||
"type": "BlockStatement",
|
||||
"body": [
|
||||
{
|
||||
"type": "ReturnStatement",
|
||||
"argument": {
|
||||
"type": "JSXElement",
|
||||
"openingElement": {
|
||||
"type": "JSXOpeningElement",
|
||||
"name": {
|
||||
"type": "JSXMemberExpression",
|
||||
"object": {
|
||||
"type": "JSXIdentifier",
|
||||
"name": "Foo",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 3,
|
||||
"column": 10
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 13
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
28,
|
||||
31
|
||||
]
|
||||
},
|
||||
"property": {
|
||||
"type": "JSXIdentifier",
|
||||
"name": "Bar",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 3,
|
||||
"column": 14
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 17
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
32,
|
||||
35
|
||||
]
|
||||
},
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 3,
|
||||
"column": 10
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 17
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
28,
|
||||
35
|
||||
]
|
||||
},
|
||||
"attributes": [
|
||||
{
|
||||
"type": "JSXAttribute",
|
||||
"name": {
|
||||
"type": "JSXIdentifier",
|
||||
"name": "a",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 3,
|
||||
"column": 18
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 19
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
36,
|
||||
37
|
||||
]
|
||||
},
|
||||
"value": {
|
||||
"type": "JSXExpressionContainer",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": 10.0,
|
||||
"raw": "10",
|
||||
"regex": null,
|
||||
"bigint": null,
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 3,
|
||||
"column": 21
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 23
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
39,
|
||||
41
|
||||
]
|
||||
},
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 3,
|
||||
"column": 20
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 24
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
38,
|
||||
42
|
||||
]
|
||||
},
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 3,
|
||||
"column": 18
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 24
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
36,
|
||||
42
|
||||
]
|
||||
}
|
||||
],
|
||||
"selfClosing": false,
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 3,
|
||||
"column": 9
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 26
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
27,
|
||||
44
|
||||
]
|
||||
},
|
||||
"children": [],
|
||||
"closingElement": {
|
||||
"type": "JSXClosingElement",
|
||||
"name": {
|
||||
"type": "JSXMemberExpression",
|
||||
"object": {
|
||||
"type": "JSXIdentifier",
|
||||
"name": "Foo",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 3,
|
||||
"column": 28
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 31
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
46,
|
||||
49
|
||||
]
|
||||
},
|
||||
"property": {
|
||||
"type": "JSXIdentifier",
|
||||
"name": "Bar",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 3,
|
||||
"column": 32
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 35
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
50,
|
||||
53
|
||||
]
|
||||
},
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 3,
|
||||
"column": 28
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 35
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
46,
|
||||
53
|
||||
]
|
||||
},
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 3,
|
||||
"column": 26
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 36
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
44,
|
||||
54
|
||||
]
|
||||
},
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 3,
|
||||
"column": 9
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 36
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
27,
|
||||
54
|
||||
]
|
||||
},
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 3,
|
||||
"column": 2
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 36
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
20,
|
||||
54
|
||||
]
|
||||
}
|
||||
],
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 2,
|
||||
"column": 15
|
||||
},
|
||||
"end": {
|
||||
"line": 4,
|
||||
"column": 1
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
16,
|
||||
56
|
||||
]
|
||||
},
|
||||
"generator": false,
|
||||
"async": false,
|
||||
"loc": null,
|
||||
"range": null,
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 2,
|
||||
"column": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 4,
|
||||
"column": 1
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
1,
|
||||
56
|
||||
]
|
||||
}
|
||||
],
|
||||
"sourceType": "script",
|
||||
"loc": {
|
||||
"source": null,
|
||||
"start": {
|
||||
"line": 2,
|
||||
"column": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 4,
|
||||
"column": 1
|
||||
}
|
||||
},
|
||||
"range": [
|
||||
1,
|
||||
56
|
||||
]
|
||||
}
|
||||
@@ -1,537 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
use crate::{
|
||||
AssignmentPropertyOrRestElement, AssignmentTarget, Class, ClassItem, ClassPrivateProperty,
|
||||
ClassProperty, Declaration, DeclarationOrExpression, ExportAllDeclaration,
|
||||
ExportDefaultDeclaration, ExportNamedDeclaration, Expression, ExpressionOrPrivateIdentifier,
|
||||
ExpressionOrSpread, ExpressionOrSuper, ForInInit, ForInit, Function, FunctionBody,
|
||||
FunctionDeclaration, Identifier, ImportDeclaration, ImportDeclarationSpecifier,
|
||||
ImportOrExportDeclaration, Literal, MethodDefinition, ModuleItem, Pattern, PrivateIdentifier,
|
||||
PrivateName, Program, Statement, StaticBlock, Super, SwitchCase, VariableDeclarator, _Literal,
|
||||
};
|
||||
|
||||
/// Trait for visiting an estree
|
||||
#[allow(non_camel_case_types)]
|
||||
#[deprecated]
|
||||
pub trait Visitor_DEPRECATED<'ast> {
|
||||
fn visit_lvalue<F>(&mut self, f: F)
|
||||
where
|
||||
F: FnOnce(&mut Self),
|
||||
{
|
||||
f(self);
|
||||
}
|
||||
|
||||
fn visit_rvalue<F>(&mut self, f: F)
|
||||
where
|
||||
F: FnOnce(&mut Self),
|
||||
{
|
||||
f(self);
|
||||
}
|
||||
|
||||
fn visit_program(&mut self, program: &'ast Program) {
|
||||
self.default_visit_program(program)
|
||||
}
|
||||
|
||||
fn default_visit_program(&mut self, program: &'ast Program) {
|
||||
for item in &program.body {
|
||||
self.visit_module_item(item);
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_function(&mut self, function: &'ast Function) {
|
||||
self.default_visit_function(function);
|
||||
}
|
||||
|
||||
fn default_visit_function(&mut self, function: &'ast Function) {
|
||||
self.visit_lvalue(|visitor| {
|
||||
for param in &function.params {
|
||||
visitor.visit_pattern(param);
|
||||
}
|
||||
});
|
||||
match &function.body {
|
||||
Some(FunctionBody::BlockStatement(body)) => {
|
||||
for stmt in &body.body {
|
||||
self.visit_statement(stmt)
|
||||
}
|
||||
}
|
||||
Some(FunctionBody::Expression(body)) => self.visit_expression(body),
|
||||
None => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_module_item(&mut self, item: &'ast ModuleItem) {
|
||||
match item {
|
||||
ModuleItem::Statement(item) => self.visit_statement(item),
|
||||
ModuleItem::ImportOrExportDeclaration(item) => {
|
||||
self.visit_import_or_export_declaration(item)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_import_or_export_declaration(&mut self, declaration: &'ast ImportOrExportDeclaration) {
|
||||
match declaration {
|
||||
ImportOrExportDeclaration::ImportDeclaration(declaration) => {
|
||||
self.visit_import_declaration(declaration);
|
||||
}
|
||||
ImportOrExportDeclaration::ExportAllDeclaration(declaration) => {
|
||||
self.visit_export_all_declaration(declaration);
|
||||
}
|
||||
ImportOrExportDeclaration::ExportDefaultDeclaration(declaration) => {
|
||||
self.visit_export_default_declaration(declaration);
|
||||
}
|
||||
ImportOrExportDeclaration::ExportNamedDeclaration(declaration) => {
|
||||
self.visit_export_named_declaration(declaration);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_import_declaration(&mut self, declaration: &'ast ImportDeclaration) {
|
||||
self.visit_lvalue(|visitor| {
|
||||
for specifier in &declaration.specifiers {
|
||||
visitor.visit_import_declaration_specifier(specifier);
|
||||
}
|
||||
});
|
||||
self.visit_import_source(&declaration.source);
|
||||
}
|
||||
|
||||
fn visit_export_all_declaration(&mut self, declaration: &'ast ExportAllDeclaration) {
|
||||
self.visit_export_source(&declaration.source);
|
||||
}
|
||||
|
||||
fn visit_export_default_declaration(&mut self, declaration: &'ast ExportDefaultDeclaration) {
|
||||
match &declaration.declaration {
|
||||
DeclarationOrExpression::Declaration(declaration) => {
|
||||
self.visit_declaration(declaration)
|
||||
}
|
||||
DeclarationOrExpression::Expression(declaration) => self.visit_expression(declaration),
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_export_named_declaration(&mut self, declaration: &'ast ExportNamedDeclaration) {
|
||||
if let Some(declaration) = &declaration.declaration {
|
||||
self.visit_declaration(declaration)
|
||||
}
|
||||
if let Some(source) = &declaration.source {
|
||||
self.visit_export_source(source);
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_import_declaration_specifier(&mut self, specifier: &'ast ImportDeclarationSpecifier) {
|
||||
match specifier {
|
||||
ImportDeclarationSpecifier::ImportSpecifier(specifier) => {
|
||||
self.visit_identifier(&specifier.local);
|
||||
}
|
||||
ImportDeclarationSpecifier::ImportDefaultSpecifier(specifier) => {
|
||||
self.visit_identifier(&specifier.local);
|
||||
}
|
||||
ImportDeclarationSpecifier::ImportNamespaceSpecifier(specifier) => {
|
||||
self.visit_identifier(&specifier.local);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_declaration(&mut self, declaration: &'ast Declaration) {
|
||||
self.default_visit_declaration(declaration);
|
||||
}
|
||||
|
||||
fn default_visit_declaration(&mut self, declaration: &'ast Declaration) {
|
||||
match declaration {
|
||||
Declaration::ClassDeclaration(declaration) => {
|
||||
self.visit_class(&declaration.class);
|
||||
}
|
||||
Declaration::FunctionDeclaration(declaration) => {
|
||||
self.visit_function_declaration(declaration);
|
||||
}
|
||||
Declaration::VariableDeclaration(declaration) => {
|
||||
for declarator in &declaration.declarations {
|
||||
self.visit_variable_declarator(declarator)
|
||||
}
|
||||
}
|
||||
Declaration::TSTypeAliasDeclaration(_declaration) => {
|
||||
todo!("visit TSTypeAliasDeclaration")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_function_declaration(&mut self, declaration: &'ast FunctionDeclaration) {
|
||||
self.visit_function(&declaration.function);
|
||||
}
|
||||
|
||||
fn visit_statement(&mut self, stmt: &'ast Statement) {
|
||||
self.default_visit_statement(stmt);
|
||||
}
|
||||
|
||||
fn default_visit_statement(&mut self, stmt: &'ast Statement) {
|
||||
match stmt {
|
||||
Statement::BlockStatement(stmt) => {
|
||||
for stmt in &stmt.body {
|
||||
self.visit_statement(stmt)
|
||||
}
|
||||
}
|
||||
Statement::BreakStatement(_stmt) => {
|
||||
// todo
|
||||
}
|
||||
Statement::ContinueStatement(_stmt) => {
|
||||
// todo
|
||||
}
|
||||
Statement::DebuggerStatement(_stmt) => {
|
||||
// todo
|
||||
}
|
||||
Statement::ClassDeclaration(stmt) => {
|
||||
self.visit_class(&stmt.class);
|
||||
}
|
||||
Statement::DoWhileStatement(stmt) => {
|
||||
self.visit_statement(&stmt.body);
|
||||
self.visit_expression(&stmt.test);
|
||||
}
|
||||
Statement::EmptyStatement(_stmt) => {
|
||||
// nothing to do
|
||||
}
|
||||
Statement::ExpressionStatement(stmt) => {
|
||||
self.visit_expression(&stmt.expression);
|
||||
}
|
||||
Statement::ForInStatement(stmt) => {
|
||||
self.visit_for_in_init(&stmt.left);
|
||||
self.visit_expression(&stmt.right);
|
||||
self.visit_statement(&stmt.body);
|
||||
}
|
||||
Statement::ForOfStatement(stmt) => {
|
||||
self.visit_for_in_init(&stmt.left);
|
||||
self.visit_expression(&stmt.right);
|
||||
self.visit_statement(&stmt.body);
|
||||
}
|
||||
Statement::ForStatement(stmt) => {
|
||||
if let Some(init) = &stmt.init {
|
||||
self.visit_for_init(init);
|
||||
}
|
||||
if let Some(test) = &stmt.test {
|
||||
self.visit_expression(test);
|
||||
}
|
||||
if let Some(update) = &stmt.update {
|
||||
self.visit_expression(update);
|
||||
}
|
||||
self.visit_statement(&stmt.body);
|
||||
}
|
||||
Statement::FunctionDeclaration(stmt) => {
|
||||
self.visit_function_declaration(stmt);
|
||||
}
|
||||
Statement::IfStatement(stmt) => {
|
||||
self.visit_expression(&stmt.test);
|
||||
self.visit_statement(&stmt.consequent);
|
||||
if let Some(alternate) = &stmt.alternate {
|
||||
self.visit_statement(alternate);
|
||||
}
|
||||
}
|
||||
Statement::LabeledStatement(stmt) => {
|
||||
self.visit_statement(&stmt.body);
|
||||
}
|
||||
Statement::ReturnStatement(stmt) => {
|
||||
if let Some(argument) = &stmt.argument {
|
||||
self.visit_expression(argument);
|
||||
}
|
||||
}
|
||||
Statement::SwitchStatement(stmt) => {
|
||||
self.visit_expression(&stmt.discriminant);
|
||||
for case_ in &stmt.cases {
|
||||
self.visit_case(case_);
|
||||
}
|
||||
}
|
||||
Statement::ThrowStatement(stmt) => {
|
||||
self.visit_expression(&stmt.argument);
|
||||
}
|
||||
Statement::TryStatement(stmt) => {
|
||||
for item in &stmt.block.body {
|
||||
self.visit_statement(item);
|
||||
}
|
||||
if let Some(handler) = &stmt.handler {
|
||||
if let Some(param) = &handler.param {
|
||||
self.visit_lvalue(|visitor| visitor.visit_pattern(param));
|
||||
}
|
||||
for item in &handler.body.body {
|
||||
self.visit_statement(item);
|
||||
}
|
||||
}
|
||||
if let Some(finalizer) = &stmt.finalizer {
|
||||
for item in &finalizer.body {
|
||||
self.visit_statement(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
Statement::VariableDeclaration(stmt) => {
|
||||
for decl in &stmt.declarations {
|
||||
self.visit_variable_declarator(decl);
|
||||
}
|
||||
}
|
||||
Statement::WhileStatement(stmt) => {
|
||||
self.visit_expression(&stmt.test);
|
||||
self.visit_statement(&stmt.body);
|
||||
}
|
||||
Statement::WithStatement(stmt) => {
|
||||
self.visit_expression(&stmt.object);
|
||||
self.visit_statement(&stmt.body);
|
||||
}
|
||||
Statement::TSTypeAliasDeclaration(_stmt) => {
|
||||
todo!("visit TSTypeAliasDeclaration")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_class(&mut self, class: &'ast Class) {
|
||||
if let Some(id) = &class.id {
|
||||
self.visit_identifier(id)
|
||||
}
|
||||
if let Some(super_class) = &class.super_class {
|
||||
self.visit_expression(super_class);
|
||||
}
|
||||
for item in &class.body.body {
|
||||
match item {
|
||||
ClassItem::MethodDefinition(item) => self.visit_method_definition(item),
|
||||
ClassItem::ClassProperty(item) => {
|
||||
self.visit_class_property(item);
|
||||
}
|
||||
ClassItem::ClassPrivateProperty(item) => {
|
||||
self.visit_class_private_property(item);
|
||||
}
|
||||
ClassItem::StaticBlock(item) => {
|
||||
self.visit_static_block(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_class_property(&mut self, property: &'ast ClassProperty) {
|
||||
self.visit_expression(&property.key);
|
||||
if let Some(value) = &property.value {
|
||||
self.visit_expression(value)
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_class_private_property(&mut self, property: &'ast ClassPrivateProperty) {
|
||||
match &property.key {
|
||||
ExpressionOrPrivateIdentifier::Expression(key) => self.visit_expression(key),
|
||||
ExpressionOrPrivateIdentifier::PrivateIdentifier(key) => {
|
||||
self.visit_private_identifier(key)
|
||||
}
|
||||
ExpressionOrPrivateIdentifier::PrivateName(key) => self.visit_private_name(key),
|
||||
}
|
||||
if let Some(value) = &property.value {
|
||||
self.visit_expression(value)
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_static_block(&mut self, property: &'ast StaticBlock) {
|
||||
for stmt in &property.body {
|
||||
self.visit_statement(stmt)
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_method_definition(&mut self, method: &'ast MethodDefinition) {
|
||||
self.default_visit_method_definition(method);
|
||||
}
|
||||
|
||||
fn default_visit_method_definition(&mut self, method: &'ast MethodDefinition) {
|
||||
self.visit_expression(&method.key);
|
||||
self.visit_function(&method.value.function);
|
||||
}
|
||||
|
||||
fn visit_case(&mut self, case_: &'ast SwitchCase) {
|
||||
if let Some(test) = &case_.test {
|
||||
self.visit_expression(test);
|
||||
}
|
||||
for stmt in &case_.consequent {
|
||||
self.visit_statement(stmt)
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_for_init(&mut self, init: &'ast ForInit) {
|
||||
match init {
|
||||
ForInit::Expression(init) => {
|
||||
self.visit_expression(init);
|
||||
}
|
||||
ForInit::VariableDeclaration(init) => {
|
||||
for decl in &init.declarations {
|
||||
self.visit_variable_declarator(decl);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_for_in_init(&mut self, init: &'ast ForInInit) {
|
||||
match init {
|
||||
ForInInit::Pattern(init) => {
|
||||
self.visit_pattern(init);
|
||||
}
|
||||
ForInInit::VariableDeclaration(init) => {
|
||||
for decl in &init.declarations {
|
||||
self.visit_variable_declarator(decl);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_pattern(&mut self, pattern: &'ast Pattern) {
|
||||
match pattern {
|
||||
Pattern::Identifier(pattern) => self.visit_identifier(pattern),
|
||||
Pattern::ArrayPattern(pattern) => {
|
||||
for element in &pattern.elements {
|
||||
if let Some(element) = element {
|
||||
self.visit_pattern(element);
|
||||
}
|
||||
}
|
||||
}
|
||||
Pattern::ObjectPattern(pattern) => {
|
||||
for property in &pattern.properties {
|
||||
match property {
|
||||
AssignmentPropertyOrRestElement::AssignmentProperty(property) => {
|
||||
self.visit_pattern(&property.value);
|
||||
}
|
||||
AssignmentPropertyOrRestElement::RestElement(property) => {
|
||||
self.visit_pattern(&property.argument);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Pattern::RestElement(pattern) => self.visit_pattern(&pattern.argument),
|
||||
Pattern::AssignmentPattern(pattern) => {
|
||||
self.visit_pattern(&pattern.left);
|
||||
self.visit_rvalue(|visitor| {
|
||||
visitor.visit_expression(&pattern.right);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_variable_declarator(&mut self, decl: &'ast VariableDeclarator) {
|
||||
self.visit_lvalue(|visitor| {
|
||||
visitor.visit_pattern(&decl.id);
|
||||
});
|
||||
if let Some(init) = &decl.init {
|
||||
self.visit_expression(init);
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_assignment_target(&mut self, target: &'ast AssignmentTarget) {
|
||||
match target {
|
||||
AssignmentTarget::Expression(target) => {
|
||||
self.visit_expression(target);
|
||||
}
|
||||
AssignmentTarget::Pattern(target) => self.visit_pattern(target),
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_expression(&mut self, expr: &'ast Expression) {
|
||||
self.default_visit_expression(expr);
|
||||
}
|
||||
|
||||
fn default_visit_expression(&mut self, expr: &'ast Expression) {
|
||||
match expr {
|
||||
Expression::ArrayExpression(expr) => {
|
||||
for item in &expr.elements {
|
||||
match item {
|
||||
Some(ExpressionOrSpread::SpreadElement(item)) => {
|
||||
self.visit_expression(&item.argument)
|
||||
}
|
||||
Some(ExpressionOrSpread::Expression(item)) => self.visit_expression(item),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
Expression::AssignmentExpression(expr) => {
|
||||
self.visit_lvalue(|visitor| visitor.visit_assignment_target(&expr.left));
|
||||
self.visit_expression(&expr.right);
|
||||
}
|
||||
Expression::BinaryExpression(expr) => {
|
||||
self.visit_expression(&expr.left);
|
||||
self.visit_expression(&expr.right);
|
||||
}
|
||||
Expression::Identifier(expr) => {
|
||||
self.visit_identifier(expr);
|
||||
}
|
||||
Expression::Literal(expr) => self.visit_literal(expr),
|
||||
Expression::FunctionExpression(expr) => self.visit_function(&expr.function),
|
||||
Expression::ArrowFunctionExpression(expr) => self.visit_function(&expr.function),
|
||||
Expression::MemberExpression(expr) => {
|
||||
match &expr.object {
|
||||
ExpressionOrSuper::Super(object) => self.visit_super(object),
|
||||
ExpressionOrSuper::Expression(object) => self.visit_expression(object),
|
||||
};
|
||||
if !expr.is_computed {
|
||||
match &expr.property {
|
||||
ExpressionOrPrivateIdentifier::Expression(property) => {
|
||||
self.visit_expression(property)
|
||||
}
|
||||
ExpressionOrPrivateIdentifier::PrivateIdentifier(property) => {
|
||||
self.visit_private_identifier(property);
|
||||
}
|
||||
ExpressionOrPrivateIdentifier::PrivateName(property) => {
|
||||
self.visit_private_name(property);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Expression::CallExpression(expr) => {
|
||||
match &expr.callee {
|
||||
ExpressionOrSuper::Expression(callee) => self.visit_expression(callee),
|
||||
ExpressionOrSuper::Super(callee) => self.visit_super(callee),
|
||||
}
|
||||
for arg in &expr.arguments {
|
||||
match arg {
|
||||
ExpressionOrSpread::Expression(arg) => self.visit_expression(arg),
|
||||
ExpressionOrSpread::SpreadElement(arg) => {
|
||||
self.visit_expression(&arg.argument)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Expression::UpdateExpression(expr) => {
|
||||
self.visit_expression(&expr.argument);
|
||||
}
|
||||
Expression::BooleanLiteral(_)
|
||||
| Expression::NullLiteral(_)
|
||||
| Expression::StringLiteral(_)
|
||||
| Expression::NumericLiteral(_) => {
|
||||
// no-op
|
||||
}
|
||||
_ => {
|
||||
todo!("{:#?}", expr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_super(&mut self, _super: &'ast Super) {
|
||||
todo!("Implement visit_super")
|
||||
}
|
||||
|
||||
fn visit_private_identifier(&mut self, _identifier: &'ast PrivateIdentifier) {
|
||||
todo!("Implement visit_private_identifier()")
|
||||
}
|
||||
|
||||
fn visit_private_name(&mut self, _identifier: &'ast PrivateName) {
|
||||
todo!("Implement visit_private_name()")
|
||||
}
|
||||
|
||||
fn visit_identifier(&mut self, _identifier: &'ast Identifier) {
|
||||
todo!("Implement visit_identifier()")
|
||||
}
|
||||
|
||||
fn visit_import_source(&mut self, literal: &'ast _Literal) {
|
||||
self.visit_any_literal(literal);
|
||||
}
|
||||
|
||||
fn visit_export_source(&mut self, literal: &'ast _Literal) {
|
||||
self.visit_any_literal(literal);
|
||||
}
|
||||
|
||||
fn visit_any_literal(&mut self, _literal: &'ast _Literal) {
|
||||
todo!("Implement visit_any_literal()")
|
||||
}
|
||||
|
||||
fn visit_literal(&mut self, _literal: &'ast Literal) {
|
||||
todo!("Implement visit_literal()")
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
[package]
|
||||
name = "react_estree_codegen"
|
||||
version = "0.1.0"
|
||||
publish = false
|
||||
authors.workspace = true
|
||||
description.workspace = true
|
||||
edition.workspace = true
|
||||
homepage.workspace = true
|
||||
keywords.workspace = true
|
||||
license.workspace = true
|
||||
repository.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
indexmap = { workspace = true }
|
||||
prettyplease = { workspace = true }
|
||||
quote = { workspace = true }
|
||||
serde = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
syn = { workspace = true }
|
||||
@@ -1,4 +0,0 @@
|
||||
# react_estree_codegen
|
||||
|
||||
This crate is a build dependency for `react_estree`, and contains codegen logic to produce Rust code to describe the ESTree format
|
||||
given a JSON schema.
|
||||
@@ -1,969 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
use std::collections::HashSet;
|
||||
|
||||
use indexmap::IndexMap;
|
||||
use quote::__private::TokenStream;
|
||||
use quote::{format_ident, quote};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use syn::Type;
|
||||
|
||||
/// Returns prettyplease-formatted Rust source for estree
|
||||
pub fn estree() -> String {
|
||||
let src = include_str!("./ecmascript.json");
|
||||
let grammar: Grammar = serde_json::from_str(src).unwrap();
|
||||
let raw = grammar.codegen().to_string();
|
||||
|
||||
let parsed = syn::parse_file(&raw).unwrap();
|
||||
format!(
|
||||
"// {}generated\n#![cfg_attr(rustfmt, rustfmt_skip)]\n{}",
|
||||
'\u{0040}',
|
||||
prettyplease::unparse(&parsed)
|
||||
)
|
||||
}
|
||||
|
||||
/// Returns prettyplease-formatted Rust source for converting HermesParser results
|
||||
/// into estree
|
||||
pub fn estree_hermes() -> String {
|
||||
let src = include_str!("./ecmascript.json");
|
||||
let grammar: Grammar = serde_json::from_str(src).unwrap();
|
||||
let raw = grammar.codegen_hermes().to_string();
|
||||
|
||||
let parsed = syn::parse_file(&raw).unwrap();
|
||||
format!(
|
||||
"// {}generated\n#![cfg_attr(rustfmt, rustfmt_skip)]\n{}",
|
||||
'\u{0040}',
|
||||
prettyplease::unparse(&parsed)
|
||||
)
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct Grammar {
|
||||
pub objects: IndexMap<String, Object>,
|
||||
pub nodes: IndexMap<String, Node>,
|
||||
pub enums: IndexMap<String, Enum>,
|
||||
pub operators: IndexMap<String, Operator>,
|
||||
}
|
||||
|
||||
impl Grammar {
|
||||
pub fn codegen(self) -> TokenStream {
|
||||
let object_defs: Vec<_> = self
|
||||
.objects
|
||||
.iter()
|
||||
.map(|(name, object)| object.codegen(name))
|
||||
.collect();
|
||||
let object_visitors: Vec<_> = self
|
||||
.objects
|
||||
.iter()
|
||||
.filter_map(|(name, object)| {
|
||||
if object.visitor {
|
||||
Some(object.codegen_visitor(name, &self))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
let node_defs: Vec<_> = self
|
||||
.nodes
|
||||
.iter()
|
||||
.map(|(name, node)| node.codegen(name))
|
||||
.collect();
|
||||
let node_visitors: Vec<_> = self
|
||||
.nodes
|
||||
.iter()
|
||||
.map(|(name, node)| node.codegen_visitor(name, &self))
|
||||
.collect();
|
||||
let enum_defs: Vec<_> = self
|
||||
.enums
|
||||
.iter()
|
||||
.map(|(name, enum_)| enum_.codegen(name, &self.enums))
|
||||
.collect();
|
||||
let enum_visitors: Vec<_> = self
|
||||
.enums
|
||||
.iter()
|
||||
.map(|(name, enum_)| enum_.codegen_visitor(name))
|
||||
.collect();
|
||||
let operator_defs: Vec<_> = self
|
||||
.operators
|
||||
.iter()
|
||||
.map(|(name, operator)| operator.codegen(name))
|
||||
.collect();
|
||||
|
||||
quote! {
|
||||
#![allow(dead_code)]
|
||||
#![allow(unused_variables)]
|
||||
#![allow(non_snake_case)]
|
||||
#![allow(clippy::enum_variant_names)]
|
||||
|
||||
use std::num::NonZeroU32;
|
||||
use serde::ser::{Serializer, SerializeMap};
|
||||
use serde::{Serialize,Deserialize};
|
||||
use crate::{JsValue, Binding, SourceRange, Number, ESTreeNode};
|
||||
|
||||
#(#object_defs)*
|
||||
|
||||
#(#node_defs)*
|
||||
|
||||
#(#enum_defs)*
|
||||
|
||||
#(#operator_defs)*
|
||||
|
||||
pub trait Visitor {
|
||||
#(#object_visitors)*
|
||||
|
||||
#(#node_visitors)*
|
||||
|
||||
#(#enum_visitors)*
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn codegen_hermes(self) -> TokenStream {
|
||||
let nodes: Vec<_> = self
|
||||
.nodes
|
||||
.iter()
|
||||
.filter(|(_, node)| !node.skip_hermes_codegen)
|
||||
.map(|(name, node)| node.codegen_hermes(name))
|
||||
.collect();
|
||||
let enums: Vec<_> = self
|
||||
.enums
|
||||
.iter()
|
||||
.map(|(name, enum_)| enum_.codegen_hermes(name, &self))
|
||||
.collect();
|
||||
let operators: Vec<_> = self
|
||||
.operators
|
||||
.iter()
|
||||
.map(|(name, operator)| operator.codegen_hermes(name))
|
||||
.collect();
|
||||
|
||||
quote! {
|
||||
#![allow(dead_code)]
|
||||
#![allow(unused_variables)]
|
||||
#![allow(clippy::enum_variant_names)]
|
||||
|
||||
use react_estree::*;
|
||||
use hermes::parser::{NodePtr, NodeKind, NodeLabel };
|
||||
use hermes::utf::{utf8_with_surrogates_to_string};
|
||||
use crate::generated_extension::*;
|
||||
|
||||
#(#nodes)*
|
||||
|
||||
#(#enums)*
|
||||
|
||||
#(#operators)*
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct Object {
|
||||
#[serde(default)]
|
||||
pub fields: IndexMap<String, Field>,
|
||||
|
||||
#[serde(default)]
|
||||
pub visitor: bool,
|
||||
}
|
||||
|
||||
impl Object {
|
||||
pub fn codegen(&self, name: &str) -> TokenStream {
|
||||
let name = format_ident!("{}", name);
|
||||
let fields: Vec<_> = self
|
||||
.fields
|
||||
.iter()
|
||||
.map(|(name, field)| field.codegen(name))
|
||||
.collect();
|
||||
|
||||
quote! {
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct #name {
|
||||
#(#fields),*
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn codegen_visitor(&self, name: &str, grammar: &Grammar) -> TokenStream {
|
||||
let visitor_name = format_ident!("visit_{}", to_lower_snake_case(name));
|
||||
let name = format_ident!("{}", name);
|
||||
let field_visitors: Vec<_> = self
|
||||
.fields
|
||||
.iter()
|
||||
.filter_map(|(name, field)| {
|
||||
let (type_name_str, type_kind) = parse_type(&field.type_).unwrap();
|
||||
if !grammar.nodes.contains_key(&type_name_str)
|
||||
&& !grammar.enums.contains_key(&type_name_str)
|
||||
{
|
||||
return None;
|
||||
}
|
||||
let visitor_name = format_ident!("visit_{}", to_lower_snake_case(&type_name_str));
|
||||
let field_name = format_ident!("{}", name);
|
||||
Some(match type_kind {
|
||||
TypeKind::Named => {
|
||||
quote! {
|
||||
self.#visitor_name(&ast.#field_name);
|
||||
}
|
||||
}
|
||||
TypeKind::Option => {
|
||||
quote! {
|
||||
if let Some(#field_name) = &ast.#field_name {
|
||||
self.#visitor_name(#field_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
TypeKind::Vec => {
|
||||
quote! {
|
||||
for #field_name in &ast.#field_name {
|
||||
self.#visitor_name(#field_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
TypeKind::VecOfOption => {
|
||||
quote! {
|
||||
for #field_name in &ast.#field_name {
|
||||
if let Some(#field_name) = #field_name {
|
||||
self.#visitor_name(#field_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
.collect();
|
||||
quote! {
|
||||
fn #visitor_name(&mut self, ast: &#name) {
|
||||
#(#field_visitors)*
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct Node {
|
||||
#[serde(default)]
|
||||
#[serde(rename = "type")]
|
||||
pub type_: Option<String>,
|
||||
|
||||
#[serde(default)]
|
||||
pub fields: IndexMap<String, Field>,
|
||||
|
||||
#[serde(default)]
|
||||
pub skip_hermes_codegen: bool,
|
||||
|
||||
#[serde(default)]
|
||||
pub skip_hermes_enum_variant: bool,
|
||||
|
||||
#[serde(default)]
|
||||
#[serde(rename = "TODO")]
|
||||
pub todo: Option<String>,
|
||||
}
|
||||
|
||||
impl Node {
|
||||
pub fn codegen(&self, name: &str) -> TokenStream {
|
||||
let name_str = name;
|
||||
let name = format_ident!("{}", name);
|
||||
let fields: Vec<_> = self
|
||||
.fields
|
||||
.iter()
|
||||
.map(|(name, field)| field.codegen_node(name))
|
||||
.collect();
|
||||
|
||||
let type_serializer = if let Some(type_) = &self.type_ {
|
||||
quote! {
|
||||
state.serialize_entry("type", #type_)?;
|
||||
}
|
||||
} else {
|
||||
quote! {
|
||||
state.serialize_entry("type", #name_str)?;
|
||||
}
|
||||
};
|
||||
|
||||
let mut field_serializers = Vec::with_capacity(self.fields.len()); // type, loc, range
|
||||
for (field_name_str, field) in &self.fields {
|
||||
if field.skip {
|
||||
continue;
|
||||
}
|
||||
let field_name = format_ident!("{}", field_name_str);
|
||||
let serialized_field_name = field.rename.as_ref().unwrap_or(field_name_str);
|
||||
let serializer = if field.flatten {
|
||||
quote! {
|
||||
Serialize::serialize(&self.#field_name, serde::__private::ser::FlatMapSerializer(&mut state))?;
|
||||
}
|
||||
} else {
|
||||
quote! {
|
||||
state.serialize_entry(#serialized_field_name, &self.#field_name)?;
|
||||
}
|
||||
};
|
||||
field_serializers.push(serializer);
|
||||
}
|
||||
|
||||
quote! {
|
||||
#[derive(Deserialize, Clone, Debug)]
|
||||
pub struct #name {
|
||||
#(#fields,)*
|
||||
|
||||
#[serde(default)]
|
||||
pub loc: Option<SourceLocation>,
|
||||
|
||||
#[serde(default)]
|
||||
pub range: Option<SourceRange>,
|
||||
}
|
||||
|
||||
impl ESTreeNode for #name {}
|
||||
|
||||
impl Serialize for #name {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
let mut state = serializer.serialize_map(None)?;
|
||||
#type_serializer
|
||||
#(#field_serializers)*
|
||||
state.serialize_entry("loc", &self.loc)?;
|
||||
state.serialize_entry("range", &self.range)?;
|
||||
state.end()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn codegen_visitor(&self, name: &str, grammar: &Grammar) -> TokenStream {
|
||||
let visitor_name = format_ident!("visit_{}", to_lower_snake_case(name));
|
||||
let name = format_ident!("{}", name);
|
||||
let field_visitors: Vec<_> = self
|
||||
.fields
|
||||
.iter()
|
||||
.filter_map(|(name, field)| {
|
||||
let (type_name_str, type_kind) = parse_type(&field.type_).unwrap();
|
||||
if (!grammar.objects.contains_key(&type_name_str)
|
||||
|| !grammar.objects.get(&type_name_str).unwrap().visitor)
|
||||
&& !grammar.nodes.contains_key(&type_name_str)
|
||||
&& !grammar.enums.contains_key(&type_name_str)
|
||||
{
|
||||
return None;
|
||||
}
|
||||
let visitor_name = format_ident!("visit_{}", to_lower_snake_case(&type_name_str));
|
||||
let field_name = format_ident!("{}", name);
|
||||
Some(match type_kind {
|
||||
TypeKind::Named => {
|
||||
quote! {
|
||||
self.#visitor_name(&ast.#field_name);
|
||||
}
|
||||
}
|
||||
TypeKind::Option => {
|
||||
quote! {
|
||||
if let Some(#field_name) = &ast.#field_name {
|
||||
self.#visitor_name(#field_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
TypeKind::Vec => {
|
||||
quote! {
|
||||
for #field_name in &ast.#field_name {
|
||||
self.#visitor_name(#field_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
TypeKind::VecOfOption => {
|
||||
quote! {
|
||||
for #field_name in &ast.#field_name {
|
||||
if let Some(#field_name) = #field_name {
|
||||
self.#visitor_name(#field_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
.collect();
|
||||
quote! {
|
||||
fn #visitor_name(&mut self, ast: &#name) {
|
||||
#(#field_visitors)*
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn codegen_hermes(&self, name: &str) -> TokenStream {
|
||||
let name_str = name;
|
||||
let name = format_ident!("{}", name);
|
||||
let field_names: Vec<_> = self
|
||||
.fields
|
||||
.iter()
|
||||
.map(|(name, _field)| format_ident!("{}", name))
|
||||
.collect();
|
||||
let fields: Vec<_> = self
|
||||
.fields
|
||||
.iter()
|
||||
.map(|(name, field)| {
|
||||
let (type_name_str, type_kind) = parse_type(&field.type_).unwrap();
|
||||
let camelcase_name = field.rename.as_ref().unwrap_or(name);
|
||||
let field_name = format_ident!("{}", name);
|
||||
let helper = format_ident!("hermes_get_{}_{}", name_str, camelcase_name);
|
||||
let type_name = format_ident!("{}", type_name_str);
|
||||
if field.skip || field.hermes_default {
|
||||
return quote! {
|
||||
let #field_name = Default::default();
|
||||
};
|
||||
}
|
||||
if let Some(convert_with) = &field.hermes_convert_with {
|
||||
let convert_with = format_ident!("{}", convert_with);
|
||||
return quote! {
|
||||
let #field_name = #convert_with(cx, unsafe { hermes::parser::#helper(node) } );
|
||||
}
|
||||
}
|
||||
match type_kind {
|
||||
TypeKind::Named => {
|
||||
match type_name_str.as_ref() {
|
||||
"bool" => {
|
||||
quote! {
|
||||
let #field_name = unsafe { hermes::parser::#helper(node) };
|
||||
}
|
||||
}
|
||||
"Number" => {
|
||||
quote! {
|
||||
let #field_name = convert_number(unsafe { hermes::parser::#helper(node) });
|
||||
}
|
||||
}
|
||||
"String" => {
|
||||
quote! {
|
||||
let #field_name = convert_string(cx, unsafe { hermes::parser::#helper(node) });
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
quote! {
|
||||
let #field_name = #type_name::convert(cx, unsafe { hermes::parser::#helper(node) });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
TypeKind::Option => {
|
||||
match type_name_str.as_ref() {
|
||||
"String" => {
|
||||
quote! {
|
||||
let #field_name = convert_option_string(cx, unsafe { hermes::parser::#helper(node) });
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
quote! {
|
||||
let #field_name = convert_option(unsafe { hermes::parser::#helper(node) }, |node| #type_name::convert(cx, node));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
TypeKind::Vec => {
|
||||
quote! {
|
||||
let #field_name = convert_vec(unsafe { hermes::parser::#helper(node) }, |node| #type_name::convert(cx, node));
|
||||
}
|
||||
}
|
||||
TypeKind::VecOfOption => {
|
||||
quote! {
|
||||
let #field_name = convert_vec_of_option(unsafe { hermes::parser::#helper(node) }, |node| #type_name::convert(cx, node));
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
let type_ = format_ident!("{}", self.type_.as_ref().unwrap_or(&name_str.to_string()));
|
||||
quote! {
|
||||
impl FromHermes for #name {
|
||||
fn convert(cx: &mut Context, node: NodePtr) -> Self {
|
||||
let node_ref = node.as_ref();
|
||||
assert_eq!(node_ref.kind, NodeKind::#type_);
|
||||
let range = convert_range(cx, node);
|
||||
#(#fields)*
|
||||
Self {
|
||||
#(#field_names,)*
|
||||
loc: None,
|
||||
range: Some(range),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct Field {
|
||||
// TODO: deserialize with `parse_type` into a custom type
|
||||
#[serde(rename = "type")]
|
||||
pub type_: String,
|
||||
|
||||
#[serde(default)]
|
||||
pub optional: bool,
|
||||
|
||||
#[serde(default)]
|
||||
pub flatten: bool,
|
||||
|
||||
#[serde(default)]
|
||||
pub rename: Option<String>,
|
||||
|
||||
#[serde(default)]
|
||||
pub skip: bool,
|
||||
|
||||
#[serde(default)]
|
||||
#[serde(rename = "TODO")]
|
||||
pub todo: Option<String>,
|
||||
|
||||
#[serde(default)]
|
||||
pub hermes_convert_with: Option<String>,
|
||||
|
||||
#[serde(default)]
|
||||
pub hermes_default: bool,
|
||||
}
|
||||
|
||||
impl Field {
|
||||
pub fn codegen(&self, name: &str) -> TokenStream {
|
||||
let name = format_ident!("{}", name);
|
||||
parse_type(&self.type_).unwrap();
|
||||
let type_name: Type = syn::parse_str(&self.type_)
|
||||
.unwrap_or_else(|_| panic!("Expected a type name, got `{}`", &self.type_));
|
||||
|
||||
let type_ = quote!(#type_name);
|
||||
let mut field = quote!(pub #name: #type_);
|
||||
if self.optional {
|
||||
field = quote! {
|
||||
#[serde(default)]
|
||||
#field
|
||||
}
|
||||
}
|
||||
if self.flatten {
|
||||
field = quote! {
|
||||
#[serde(flatten)]
|
||||
#field
|
||||
}
|
||||
}
|
||||
if self.skip {
|
||||
field = quote! {
|
||||
#[serde(skip)]
|
||||
#field
|
||||
}
|
||||
}
|
||||
if let Some(rename) = &self.rename {
|
||||
field = quote! {
|
||||
#[serde(rename = #rename)]
|
||||
#field
|
||||
}
|
||||
}
|
||||
field
|
||||
}
|
||||
|
||||
pub fn codegen_node(&self, name: &str) -> TokenStream {
|
||||
let name = format_ident!("{}", name);
|
||||
parse_type(&self.type_).unwrap();
|
||||
let type_name: Type = syn::parse_str(&self.type_)
|
||||
.unwrap_or_else(|_| panic!("Expected a type name, got `{}`", &self.type_));
|
||||
let type_ = quote!(#type_name);
|
||||
let mut field = quote!(pub #name: #type_);
|
||||
if self.optional {
|
||||
field = quote! {
|
||||
#[serde(default)]
|
||||
#field
|
||||
}
|
||||
}
|
||||
if self.flatten {
|
||||
field = quote! {
|
||||
#[serde(flatten)]
|
||||
#field
|
||||
}
|
||||
}
|
||||
if self.skip {
|
||||
field = quote! {
|
||||
#[serde(skip)]
|
||||
#field
|
||||
}
|
||||
}
|
||||
if let Some(rename) = &self.rename {
|
||||
field = quote! {
|
||||
#[serde(rename = #rename)]
|
||||
#field
|
||||
}
|
||||
}
|
||||
field
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
#[serde(transparent)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct Enum {
|
||||
pub variants: Vec<String>,
|
||||
}
|
||||
|
||||
impl Enum {
|
||||
pub fn codegen(&self, name: &str, enums: &IndexMap<String, Enum>) -> TokenStream {
|
||||
let mut sorted_variants: Vec<_> = self.variants.iter().collect();
|
||||
sorted_variants.sort();
|
||||
|
||||
let name_str = name;
|
||||
let name = format_ident!("{}", name);
|
||||
let variants: Vec<_> = sorted_variants
|
||||
.iter()
|
||||
.map(|name| {
|
||||
let variant = format_ident!("{}", name);
|
||||
if enums.contains_key(*name) {
|
||||
quote!(#variant(#variant))
|
||||
} else {
|
||||
quote!(#variant(Box<#variant>))
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
let enum_tag = format_ident!("__{}Tag", name);
|
||||
let mut seen = HashSet::new();
|
||||
|
||||
// tag_variants is used to generate an enum of all the possible type tags (`type` values)
|
||||
// that can appear in this enum. we emit this enum and derive a deserializer for it so that
|
||||
// our enum deserializer can first decode the tag in order to know how to decode the data
|
||||
let mut tag_variants = Vec::new();
|
||||
|
||||
// once the tag is decoded, we need to match against it and deserialize according the tag (`type`)
|
||||
// tag_matches are the match arms for each type.
|
||||
let mut tag_matches = Vec::new();
|
||||
|
||||
// Imagine a case like:
|
||||
// enum ModuleItem {
|
||||
// ImportDeclaration, // struct
|
||||
// Statement // another enum
|
||||
// }
|
||||
// We need to generate matches for all the possible *concrete* `type` values, which means
|
||||
// we have to expand nested enums such as `Statement`
|
||||
for variant in self.variants.iter() {
|
||||
if let Some(nested_enum) = enums.get(variant) {
|
||||
let outer_variant = format_ident!("{}", variant);
|
||||
for variant in nested_enum.variants.iter() {
|
||||
// Skip variants that appear in multiple nested enums, we deserialize
|
||||
// as the first listed outer variant
|
||||
if !seen.insert(variant.to_string()) {
|
||||
continue;
|
||||
}
|
||||
// Modeling ESTree only requires a single level of nested enums,
|
||||
// so that's all we support. Though in theory we could support arbitrary nesting,
|
||||
// since ultimately we're matching based on the final concrete types.
|
||||
assert!(!enums.contains_key(variant));
|
||||
|
||||
let inner_variant = format_ident!("{}", variant);
|
||||
tag_variants.push(quote!(#inner_variant));
|
||||
|
||||
tag_matches.push(quote! {
|
||||
#enum_tag::#inner_variant => {
|
||||
let node: Box<#inner_variant> = <Box<#inner_variant> as Deserialize>::deserialize(
|
||||
serde::__private::de::ContentDeserializer::<D::Error>::new(tagged.1),
|
||||
)?;
|
||||
Ok(#name::#outer_variant(#outer_variant::#inner_variant(node)))
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
if !seen.insert(variant.to_string()) {
|
||||
panic!(
|
||||
"Concrete variant {} was already added by a nested enum",
|
||||
variant
|
||||
);
|
||||
}
|
||||
let variant_name = format_ident!("{}", variant);
|
||||
tag_variants.push(quote!(#variant_name));
|
||||
|
||||
tag_matches.push(quote! {
|
||||
#enum_tag::#variant_name => {
|
||||
let node: Box<#variant_name> = <Box<#variant_name> as Deserialize>::deserialize(
|
||||
serde::__private::de::ContentDeserializer::<D::Error>::new(tagged.1),
|
||||
)?;
|
||||
Ok(#name::#variant_name(node))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
quote! {
|
||||
#[derive(Serialize, Clone, Debug)]
|
||||
#[serde(untagged)]
|
||||
pub enum #name {
|
||||
#(#variants),*
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
enum #enum_tag {
|
||||
#(#tag_variants),*
|
||||
}
|
||||
|
||||
impl <'de> serde::Deserialize<'de> for #name {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where D: serde::Deserializer<'de> {
|
||||
let tagged = serde::Deserializer::deserialize_any(
|
||||
deserializer,
|
||||
serde::__private::de::TaggedContentVisitor::<#enum_tag>::new("type", #name_str)
|
||||
)?;
|
||||
match tagged.0 {
|
||||
#(#tag_matches),*
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn codegen_visitor(&self, name: &str) -> TokenStream {
|
||||
let visitor_name = format_ident!("visit_{}", to_lower_snake_case(name));
|
||||
let name = format_ident!("{}", name);
|
||||
let mut tag_matches = Vec::new();
|
||||
|
||||
for variant in self.variants.iter() {
|
||||
let node_variant = format_ident!("{}", variant);
|
||||
let visitor_name = format_ident!("visit_{}", to_lower_snake_case(variant));
|
||||
|
||||
tag_matches.push(quote! {
|
||||
#name::#node_variant(ast) => {
|
||||
self.#visitor_name(ast);
|
||||
}
|
||||
})
|
||||
}
|
||||
quote! {
|
||||
fn #visitor_name(&mut self, ast: &#name) {
|
||||
match ast {
|
||||
#(#tag_matches),*
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn codegen_hermes(&self, name: &str, grammar: &Grammar) -> TokenStream {
|
||||
let name_str = name;
|
||||
let name = format_ident!("{}", name);
|
||||
|
||||
let mut tag_matches = Vec::new();
|
||||
let mut seen = HashSet::new();
|
||||
|
||||
// Imagine a case like:
|
||||
// enum ModuleItem {
|
||||
// ImportDeclaration, // struct
|
||||
// Statement // another enum
|
||||
// }
|
||||
// We need to generate matches for all the possible *concrete* `type` values, which means
|
||||
// we have to expand nested enums such as `Statement`
|
||||
for variant in self.variants.iter() {
|
||||
if let Some(nested_enum) = grammar.enums.get(variant) {
|
||||
let outer_variant = format_ident!("{}", variant);
|
||||
for variant in nested_enum.variants.iter() {
|
||||
// Skip variants that appear in multiple nested enums, we deserialize
|
||||
// as the first listed outer variant
|
||||
if !seen.insert(variant.to_string()) {
|
||||
continue;
|
||||
}
|
||||
// Modeling ESTree only requires a single level of nested enums,
|
||||
// so that's all we support. Though in theory we could support arbitrary nesting,
|
||||
// since ultimately we're matching based on the final concrete types.
|
||||
assert!(!grammar.enums.contains_key(variant));
|
||||
let node = grammar.nodes.get(variant).unwrap();
|
||||
if node.skip_hermes_enum_variant {
|
||||
continue;
|
||||
}
|
||||
|
||||
let inner_variant = format_ident!("{}", variant);
|
||||
let node_variant_name = node.type_.as_ref().unwrap_or(variant);
|
||||
let node_variant = format_ident!("{}", node_variant_name);
|
||||
|
||||
tag_matches.push(quote! {
|
||||
NodeKind::#node_variant => {
|
||||
let node = #inner_variant::convert(cx, node);
|
||||
#name::#outer_variant(#outer_variant::#inner_variant(Box::new(node)))
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
if !seen.insert(variant.to_string()) {
|
||||
panic!(
|
||||
"Concrete variant {} was already added by a nested enum",
|
||||
variant
|
||||
);
|
||||
}
|
||||
let variant_name = format_ident!("{}", variant);
|
||||
let node = grammar.nodes.get(variant).unwrap();
|
||||
if node.skip_hermes_enum_variant {
|
||||
continue;
|
||||
}
|
||||
|
||||
let node_variant_name = node.type_.as_ref().unwrap_or(variant);
|
||||
let node_variant = format_ident!("{}", node_variant_name);
|
||||
|
||||
tag_matches.push(quote! {
|
||||
NodeKind::#node_variant => {
|
||||
let node = #variant_name::convert(cx, node);
|
||||
#name::#variant_name(Box::new(node))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
quote! {
|
||||
impl FromHermes for #name {
|
||||
fn convert(cx: &mut Context, node: NodePtr) -> Self {
|
||||
let node_ref = node.as_ref();
|
||||
match node_ref.kind {
|
||||
#(#tag_matches),*
|
||||
_ => panic!("Unexpected node kind `{:?}` for `{}`", node_ref.kind, #name_str)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
#[serde(transparent)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct Operator {
|
||||
pub variants: IndexMap<String, String>,
|
||||
}
|
||||
|
||||
impl Operator {
|
||||
pub fn codegen(&self, name: &str) -> TokenStream {
|
||||
let mut sorted_variants: Vec<_> = self.variants.iter().collect();
|
||||
sorted_variants.sort();
|
||||
|
||||
let name = format_ident!("{}", name);
|
||||
let variants: Vec<_> = sorted_variants
|
||||
.iter()
|
||||
.map(|(name, operator)| {
|
||||
let name = format_ident!("{}", name);
|
||||
let comment = format!(" {}", &operator);
|
||||
quote! {
|
||||
#[doc = #comment]
|
||||
#[serde(rename = #operator)]
|
||||
#name
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
let display_matches: Vec<_> = sorted_variants
|
||||
.iter()
|
||||
.map(|(name, operator)| {
|
||||
let name = format_ident!("{}", name);
|
||||
quote!(Self::#name => #operator)
|
||||
})
|
||||
.collect();
|
||||
|
||||
let fromstr_matches: Vec<_> = sorted_variants
|
||||
.iter()
|
||||
.map(|(name, operator)| {
|
||||
let name = format_ident!("{}", name);
|
||||
quote!(#operator => Ok(Self::#name))
|
||||
})
|
||||
.collect();
|
||||
|
||||
quote! {
|
||||
#[derive(Serialize, Deserialize, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
|
||||
pub enum #name {
|
||||
#(#variants),*
|
||||
}
|
||||
|
||||
impl std::fmt::Display for #name {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let name = match self {
|
||||
#(#display_matches),*
|
||||
};
|
||||
f.write_str(name)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::str::FromStr for #name {
|
||||
type Err = ();
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
match s {
|
||||
#(#fromstr_matches,)*
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn codegen_hermes(&self, name: &str) -> TokenStream {
|
||||
let mut sorted_variants: Vec<_> = self.variants.iter().collect();
|
||||
sorted_variants.sort();
|
||||
|
||||
let name = format_ident!("{}", name);
|
||||
|
||||
quote! {
|
||||
impl FromHermesLabel for #name {
|
||||
fn convert(cx: &mut Context, label: NodeLabel) -> Self {
|
||||
let utf_str = utf8_with_surrogates_to_string(label.as_slice()).unwrap();
|
||||
utf_str.parse().unwrap()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum TypeKind {
|
||||
/// T
|
||||
Named,
|
||||
|
||||
/// Option<T>
|
||||
Option,
|
||||
|
||||
/// Vec<T>
|
||||
Vec,
|
||||
|
||||
/// Vec<Option<T>>
|
||||
VecOfOption,
|
||||
}
|
||||
|
||||
/// Parses a given type into the underlying type name plus a descriptor of the
|
||||
/// kind of type. Only a subset of Rust types are supported:
|
||||
/// - T
|
||||
/// - Option<T>
|
||||
/// - Vec<T>
|
||||
/// - Vec<Option<T>>
|
||||
fn parse_type(type_: &str) -> Result<(String, TypeKind), String> {
|
||||
let mut current = type_;
|
||||
let mut is_list = false;
|
||||
let mut is_option = false;
|
||||
if current.starts_with("Vec<") {
|
||||
current = ¤t[4..current.len() - 1];
|
||||
is_list = true;
|
||||
}
|
||||
if current.starts_with("Option<") {
|
||||
current = ¤t[7..current.len() - 1];
|
||||
is_option = true;
|
||||
}
|
||||
if current.contains('<') {
|
||||
Err(format!(
|
||||
"Unsupported type `{current}` expected named type (`Identifier`), optional type (`Option<Identifier>`), list type (`Vec<Identifier>`), or optional list (`Vec<Option<Identifier>>`)"
|
||||
))
|
||||
} else {
|
||||
let kind = match (is_list, is_option) {
|
||||
(true, true) => TypeKind::VecOfOption,
|
||||
(true, false) => TypeKind::Vec,
|
||||
(false, true) => TypeKind::Option,
|
||||
(false, false) => TypeKind::Named,
|
||||
};
|
||||
Ok((current.to_string(), kind))
|
||||
}
|
||||
}
|
||||
|
||||
// from https://github.com/rust-lang/rust-analyzer/blob/4105378dc7479a3dbd39a4afb3eba67d083bd7f8/xtask/src/codegen/gen_syntax.rs#L406C1-L418C2
|
||||
fn to_lower_snake_case(s: &str) -> String {
|
||||
let mut buf = String::with_capacity(s.len());
|
||||
let mut prev = false;
|
||||
for c in s.chars() {
|
||||
if c.is_ascii_uppercase() {
|
||||
if prev {
|
||||
buf.push('_')
|
||||
}
|
||||
prev = false;
|
||||
} else {
|
||||
prev = true;
|
||||
}
|
||||
|
||||
buf.push(c.to_ascii_lowercase());
|
||||
}
|
||||
buf
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,10 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
mod codegen;
|
||||
|
||||
pub use codegen::{estree, estree_hermes};
|
||||
@@ -1,24 +0,0 @@
|
||||
[package]
|
||||
name = "react_fixtures"
|
||||
version = "0.1.0"
|
||||
publish = false
|
||||
authors.workspace = true
|
||||
description.workspace = true
|
||||
edition.workspace = true
|
||||
homepage.workspace = true
|
||||
keywords.workspace = true
|
||||
license.workspace = true
|
||||
repository.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dev-dependencies]
|
||||
insta = { workspace = true }
|
||||
react_estree = { workspace = true }
|
||||
react_hermes_parser = { workspace = true }
|
||||
react_hir = { workspace = true }
|
||||
react_optimization = { workspace = true }
|
||||
react_semantic_analysis = { workspace = true }
|
||||
react_ssa = { workspace = true }
|
||||
react_build_hir = { workspace = true }
|
||||
miette = { workspace = true, features = ["backtrace", "fancy"] }
|
||||
@@ -1,3 +0,0 @@
|
||||
# fixtures
|
||||
|
||||
This crate is for tests only, and runs the suite of compiler fixture tests.
|
||||
@@ -1,6 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
@@ -1,34 +0,0 @@
|
||||
function Component() {
|
||||
let a = 1;
|
||||
|
||||
let b;
|
||||
if (a === 1) {
|
||||
b = true;
|
||||
} else {
|
||||
b = false;
|
||||
}
|
||||
|
||||
let c;
|
||||
if (b) {
|
||||
c = "hello";
|
||||
} else {
|
||||
c = null;
|
||||
}
|
||||
|
||||
let d;
|
||||
if (c === "hello") {
|
||||
d = 42.0;
|
||||
} else {
|
||||
d = 42.001;
|
||||
}
|
||||
|
||||
let e;
|
||||
if (d === 42.0) {
|
||||
e = "ok";
|
||||
} else {
|
||||
e = "nope";
|
||||
}
|
||||
|
||||
// should constant-propagate to "ok"
|
||||
return e;
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
function Component(props) {
|
||||
// global propagation
|
||||
let a;
|
||||
a = Math;
|
||||
a; // Math
|
||||
|
||||
// primitive propagation w phi
|
||||
let b;
|
||||
if (props) {
|
||||
b = true;
|
||||
} else {
|
||||
b = true;
|
||||
}
|
||||
b; // true
|
||||
|
||||
// primitive propagation fails if different values
|
||||
let c;
|
||||
if (props) {
|
||||
c = true;
|
||||
} else {
|
||||
c = 42;
|
||||
}
|
||||
c; // <no change>
|
||||
|
||||
// constant evaluation
|
||||
42 + 1; // 43
|
||||
42 - 1; // 41
|
||||
42 * 2; // 84
|
||||
42 / 2; // 21
|
||||
0 == 1; // false
|
||||
0 != 1; // true
|
||||
0 === 1; // false
|
||||
0 !== 1; // true
|
||||
0 == 0; // true
|
||||
// TODO: unary operators
|
||||
// 0 == -0; // false
|
||||
// 0 != -0; // true
|
||||
// 0 === -0; // false
|
||||
// 0 !== -0; // true
|
||||
NaN == NaN; // false
|
||||
NaN != NaN; // true
|
||||
NaN !== NaN; // true
|
||||
NaN !== NaN; // true
|
||||
"hello" == "hello"; // true
|
||||
"hello" != "hello"; // false
|
||||
"hello" === "hello"; // true
|
||||
"hello" !== "hello"; // false
|
||||
"hello" == "world"; // false
|
||||
"hello" != "world"; // true
|
||||
"hello" === "world"; // false
|
||||
"hello" !== "world"; // true
|
||||
true == true; // true
|
||||
true != true; // false
|
||||
true === true; // true
|
||||
true !== true; // false
|
||||
|
||||
// constant evaluation through variable
|
||||
let x = 5 * 60 * 60 * 1000; // 5 hours in milliseconds
|
||||
x;
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
function Component(a, b) {
|
||||
const [c, , ...d] = a;
|
||||
const [[[e]], ...[f]] = b;
|
||||
return [c, d, e, f];
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
function Component(a, b) {
|
||||
const {
|
||||
c,
|
||||
d,
|
||||
e: { e },
|
||||
f: { _f: f },
|
||||
g: {
|
||||
g: {
|
||||
g: { g, ...h },
|
||||
},
|
||||
},
|
||||
...i
|
||||
} = a;
|
||||
return [c, d, e, f, g, h, i];
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
function foo() {
|
||||
x = true;
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
function foo() {
|
||||
let x = 0;
|
||||
for (let i = 0; i < 10; i = i + 1) {
|
||||
x = x + i;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
function Component(props) {
|
||||
const x = 2;
|
||||
const foo = function foo(y) {
|
||||
let a = 1;
|
||||
let b;
|
||||
if (a === 1) {
|
||||
b = 5 + 3;
|
||||
} else {
|
||||
b = false;
|
||||
}
|
||||
x + y + a + b;
|
||||
const bar = function bar(z) {
|
||||
let c = 2;
|
||||
let d;
|
||||
d = 3;
|
||||
x + y + a + b + z + c + d;
|
||||
};
|
||||
bar;
|
||||
foo;
|
||||
};
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
// import React from "react";
|
||||
|
||||
// const FOO = false;
|
||||
|
||||
function id(x) {
|
||||
// React;
|
||||
// FOO;
|
||||
Math;
|
||||
id;
|
||||
let y = true;
|
||||
y = false;
|
||||
y;
|
||||
let z;
|
||||
z;
|
||||
return x;
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
function foo(a, b, c, d) {
|
||||
if (a) {
|
||||
return b;
|
||||
} else {
|
||||
c;
|
||||
}
|
||||
d;
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
function Component(a) {
|
||||
Math;
|
||||
let b = 0;
|
||||
const foo = function foo_(c) {
|
||||
let d = 1;
|
||||
return a + b + c + d;
|
||||
};
|
||||
return foo();
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
function Component(props) {
|
||||
let a;
|
||||
if (props) {
|
||||
a = 1;
|
||||
} else {
|
||||
a = 2;
|
||||
}
|
||||
return a;
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
function test() {
|
||||
[true, false, null, 1, 3.14, ...["hello world!"]];
|
||||
return 2;
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
function Component(a, b) {
|
||||
let x;
|
||||
let y = 0;
|
||||
let z = 10;
|
||||
if (a) {
|
||||
x = 1;
|
||||
if (b) {
|
||||
z = 20;
|
||||
} else {
|
||||
z = 30;
|
||||
}
|
||||
} else {
|
||||
x = 2;
|
||||
}
|
||||
return x + y + z;
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
import { useMemo } from "react";
|
||||
|
||||
function Component(x) {
|
||||
const y = useMemo(() => {
|
||||
return x;
|
||||
});
|
||||
return y;
|
||||
}
|
||||
@@ -1,88 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
use std::env;
|
||||
use std::fmt::Write;
|
||||
|
||||
use insta::{assert_snapshot, glob};
|
||||
use miette::{NamedSource, Report};
|
||||
use react_build_hir::build;
|
||||
use react_estree::{ModuleItem, Statement};
|
||||
use react_hermes_parser::parse;
|
||||
use react_hir::{inline_use_memo, Environment, Features, Print, Registry};
|
||||
use react_optimization::constant_propagation;
|
||||
use react_semantic_analysis::analyze;
|
||||
use react_ssa::{eliminate_redundant_phis, enter_ssa};
|
||||
|
||||
#[test]
|
||||
fn fixtures() {
|
||||
glob!("fixtures/**.js", |path| {
|
||||
println!("fixture {}", path.to_str().unwrap());
|
||||
let input = std::fs::read_to_string(path).unwrap();
|
||||
let ast = parse(&input, path.to_str().unwrap()).unwrap();
|
||||
println!("ok parse");
|
||||
|
||||
let mut output = String::new();
|
||||
|
||||
let mut analysis = analyze(&ast, Default::default());
|
||||
let diagnostics = analysis.diagnostics();
|
||||
if !diagnostics.is_empty() {
|
||||
for diagnostic in diagnostics {
|
||||
eprintln!(
|
||||
"{:?}",
|
||||
Report::new(diagnostic)
|
||||
.with_source_code(NamedSource::new(path.to_string_lossy(), input.clone(),))
|
||||
);
|
||||
}
|
||||
}
|
||||
let environment = Environment::new(
|
||||
Features {
|
||||
validate_frozen_lambdas: true,
|
||||
},
|
||||
Registry,
|
||||
analysis,
|
||||
);
|
||||
for (ix, item) in ast.body.iter().enumerate() {
|
||||
if let ModuleItem::Statement(stmt) = item {
|
||||
if let Statement::FunctionDeclaration(fun) = stmt {
|
||||
if ix != 0 {
|
||||
output.push_str("\n\n");
|
||||
}
|
||||
match build(&environment, &fun.function) {
|
||||
Ok(mut fun) => {
|
||||
println!("ok build");
|
||||
enter_ssa(&environment, &mut fun).unwrap();
|
||||
println!("ok enter_ssa");
|
||||
eliminate_redundant_phis(&environment, &mut fun);
|
||||
println!("ok eliminate_redundant_phis");
|
||||
constant_propagation(&environment, &mut fun).unwrap();
|
||||
println!("ok constant_propagation");
|
||||
inline_use_memo(&environment, &mut fun).unwrap();
|
||||
println!("ok inline_use_memo");
|
||||
fun.print(&fun.body, &mut output).unwrap();
|
||||
println!("ok print");
|
||||
}
|
||||
Err(error) => {
|
||||
write!(&mut output, "{}", error,).unwrap();
|
||||
eprintln!(
|
||||
"{:?}",
|
||||
Report::new(error).with_source_code(NamedSource::new(
|
||||
path.to_string_lossy(),
|
||||
input.clone(),
|
||||
))
|
||||
);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let output = output.trim();
|
||||
assert_snapshot!(format!("Input:\n{input}\n\nOutput:\n{output}"));
|
||||
});
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
---
|
||||
source: crates/react_fixtures/tests/fixtures_test.rs
|
||||
expression: "format!(\"Input:\\n{input}\\n\\nOutput:\\n{output}\")"
|
||||
input_file: crates/react_fixtures/tests/fixtures/constant-propagation-constant-if-condition.js
|
||||
---
|
||||
Input:
|
||||
function Component() {
|
||||
let a = 1;
|
||||
|
||||
let b;
|
||||
if (a === 1) {
|
||||
b = true;
|
||||
} else {
|
||||
b = false;
|
||||
}
|
||||
|
||||
let c;
|
||||
if (b) {
|
||||
c = "hello";
|
||||
} else {
|
||||
c = null;
|
||||
}
|
||||
|
||||
let d;
|
||||
if (c === "hello") {
|
||||
d = 42.0;
|
||||
} else {
|
||||
d = 42.001;
|
||||
}
|
||||
|
||||
let e;
|
||||
if (d === 42.0) {
|
||||
e = "ok";
|
||||
} else {
|
||||
e = "nope";
|
||||
}
|
||||
|
||||
// should constant-propagate to "ok"
|
||||
return e;
|
||||
}
|
||||
|
||||
|
||||
Output:
|
||||
function Component(
|
||||
)
|
||||
entry bb0
|
||||
bb0 (block)
|
||||
[0] unknown $39 = 1
|
||||
[1] unknown $41 = StoreLocal Let unknown a$40 = unknown $39
|
||||
[2] unknown $43 = DeclareLocal Let unknown b$42
|
||||
[3] unknown $44 = 1
|
||||
[4] unknown $45 = 1
|
||||
[5] unknown $46 = true
|
||||
[6] unknown $47 = true
|
||||
[7] unknown $49 = StoreLocal Reassign unknown b$48 = unknown $47
|
||||
[8] unknown $54 = DeclareLocal Let unknown c$53
|
||||
[9] unknown $56 = true
|
||||
[10] unknown $57 = "hello"
|
||||
[11] unknown $59 = StoreLocal Reassign unknown c$58 = unknown $57
|
||||
[12] unknown $64 = DeclareLocal Let unknown d$63
|
||||
[13] unknown $66 = "hello"
|
||||
[14] unknown $67 = "hello"
|
||||
[15] unknown $68 = true
|
||||
[16] unknown $69 = 42
|
||||
[17] unknown $71 = StoreLocal Reassign unknown d$70 = unknown $69
|
||||
[18] unknown $76 = DeclareLocal Let unknown e$75
|
||||
[19] unknown $78 = 42
|
||||
[20] unknown $79 = 42
|
||||
[21] unknown $80 = true
|
||||
[22] unknown $81 = "ok"
|
||||
[23] unknown $83 = StoreLocal Reassign unknown e$82 = unknown $81
|
||||
[24] unknown $88 = "ok"
|
||||
[25] Return unknown $88
|
||||
@@ -1,198 +0,0 @@
|
||||
---
|
||||
source: crates/react_fixtures/tests/fixtures_test.rs
|
||||
expression: "format!(\"Input:\\n{input}\\n\\nOutput:\\n{output}\")"
|
||||
input_file: crates/react_fixtures/tests/fixtures/constant-propagation.js
|
||||
---
|
||||
Input:
|
||||
function Component(props) {
|
||||
// global propagation
|
||||
let a;
|
||||
a = Math;
|
||||
a; // Math
|
||||
|
||||
// primitive propagation w phi
|
||||
let b;
|
||||
if (props) {
|
||||
b = true;
|
||||
} else {
|
||||
b = true;
|
||||
}
|
||||
b; // true
|
||||
|
||||
// primitive propagation fails if different values
|
||||
let c;
|
||||
if (props) {
|
||||
c = true;
|
||||
} else {
|
||||
c = 42;
|
||||
}
|
||||
c; // <no change>
|
||||
|
||||
// constant evaluation
|
||||
42 + 1; // 43
|
||||
42 - 1; // 41
|
||||
42 * 2; // 84
|
||||
42 / 2; // 21
|
||||
0 == 1; // false
|
||||
0 != 1; // true
|
||||
0 === 1; // false
|
||||
0 !== 1; // true
|
||||
0 == 0; // true
|
||||
// TODO: unary operators
|
||||
// 0 == -0; // false
|
||||
// 0 != -0; // true
|
||||
// 0 === -0; // false
|
||||
// 0 !== -0; // true
|
||||
NaN == NaN; // false
|
||||
NaN != NaN; // true
|
||||
NaN !== NaN; // true
|
||||
NaN !== NaN; // true
|
||||
"hello" == "hello"; // true
|
||||
"hello" != "hello"; // false
|
||||
"hello" === "hello"; // true
|
||||
"hello" !== "hello"; // false
|
||||
"hello" == "world"; // false
|
||||
"hello" != "world"; // true
|
||||
"hello" === "world"; // false
|
||||
"hello" !== "world"; // true
|
||||
true == true; // true
|
||||
true != true; // false
|
||||
true === true; // true
|
||||
true !== true; // false
|
||||
|
||||
// constant evaluation through variable
|
||||
let x = 5 * 60 * 60 * 1000; // 5 hours in milliseconds
|
||||
x;
|
||||
}
|
||||
|
||||
|
||||
Output:
|
||||
function Component(
|
||||
unknown props$108,
|
||||
)
|
||||
entry bb0
|
||||
bb0 (block)
|
||||
[0] unknown $110 = DeclareLocal Let unknown a$109
|
||||
[1] unknown $111 = LoadGlobal Math
|
||||
[2] unknown $113 = StoreLocal Reassign unknown a$112 = unknown $111
|
||||
[3] unknown $114 = LoadGlobal Math
|
||||
[4] unknown $116 = DeclareLocal Let unknown b$115
|
||||
[5] unknown $117 = LoadLocal unknown props$108
|
||||
[6] If unknown $117 consequent=bb2 alternate=bb3 fallthrough=bb1
|
||||
bb2 (block)
|
||||
predecessors: bb0
|
||||
[7] unknown $118 = true
|
||||
[8] unknown $120 = StoreLocal Reassign unknown b$119 = unknown $118
|
||||
[9] Goto bb1
|
||||
bb3 (block)
|
||||
predecessors: bb0
|
||||
[10] unknown $121 = true
|
||||
[11] unknown $123 = StoreLocal Reassign unknown b$122 = unknown $121
|
||||
[12] Goto bb1
|
||||
bb1 (block)
|
||||
predecessors: bb2, bb3
|
||||
b$124: phi(bb2: b$119, bb3: b$122)
|
||||
[13] unknown $125 = true
|
||||
[14] unknown $127 = DeclareLocal Let unknown c$126
|
||||
[15] unknown $129 = LoadLocal unknown props$108
|
||||
[16] If unknown $129 consequent=bb5 alternate=bb6 fallthrough=bb4
|
||||
bb5 (block)
|
||||
predecessors: bb1
|
||||
[17] unknown $130 = true
|
||||
[18] unknown $132 = StoreLocal Reassign unknown c$131 = unknown $130
|
||||
[19] Goto bb4
|
||||
bb6 (block)
|
||||
predecessors: bb1
|
||||
[20] unknown $133 = 42
|
||||
[21] unknown $135 = StoreLocal Reassign unknown c$134 = unknown $133
|
||||
[22] Goto bb4
|
||||
bb4 (block)
|
||||
predecessors: bb5, bb6
|
||||
c$136: phi(bb5: c$131, bb6: c$134)
|
||||
[23] unknown $137 = LoadLocal unknown c$136
|
||||
[24] unknown $138 = 42
|
||||
[25] unknown $139 = 1
|
||||
[26] unknown $140 = 43
|
||||
[27] unknown $141 = 42
|
||||
[28] unknown $142 = 1
|
||||
[29] unknown $143 = 41
|
||||
[30] unknown $144 = 42
|
||||
[31] unknown $145 = 2
|
||||
[32] unknown $146 = 84
|
||||
[33] unknown $147 = 42
|
||||
[34] unknown $148 = 2
|
||||
[35] unknown $149 = 21
|
||||
[36] unknown $150 = 0
|
||||
[37] unknown $151 = 1
|
||||
[38] unknown $152 = false
|
||||
[39] unknown $153 = 0
|
||||
[40] unknown $154 = 1
|
||||
[41] unknown $155 = true
|
||||
[42] unknown $156 = 0
|
||||
[43] unknown $157 = 1
|
||||
[44] unknown $158 = false
|
||||
[45] unknown $159 = 0
|
||||
[46] unknown $160 = 1
|
||||
[47] unknown $161 = true
|
||||
[48] unknown $162 = 0
|
||||
[49] unknown $163 = 0
|
||||
[50] unknown $164 = true
|
||||
[51] unknown $165 = LoadGlobal NaN
|
||||
[52] unknown $166 = LoadGlobal NaN
|
||||
[53] unknown $167 = Binary unknown $165 == unknown $166
|
||||
[54] unknown $168 = LoadGlobal NaN
|
||||
[55] unknown $169 = LoadGlobal NaN
|
||||
[56] unknown $170 = Binary unknown $168 != unknown $169
|
||||
[57] unknown $171 = LoadGlobal NaN
|
||||
[58] unknown $172 = LoadGlobal NaN
|
||||
[59] unknown $173 = Binary unknown $171 !== unknown $172
|
||||
[60] unknown $174 = LoadGlobal NaN
|
||||
[61] unknown $175 = LoadGlobal NaN
|
||||
[62] unknown $176 = Binary unknown $174 !== unknown $175
|
||||
[63] unknown $177 = "hello"
|
||||
[64] unknown $178 = "hello"
|
||||
[65] unknown $179 = true
|
||||
[66] unknown $180 = "hello"
|
||||
[67] unknown $181 = "hello"
|
||||
[68] unknown $182 = false
|
||||
[69] unknown $183 = "hello"
|
||||
[70] unknown $184 = "hello"
|
||||
[71] unknown $185 = true
|
||||
[72] unknown $186 = "hello"
|
||||
[73] unknown $187 = "hello"
|
||||
[74] unknown $188 = false
|
||||
[75] unknown $189 = "hello"
|
||||
[76] unknown $190 = "world"
|
||||
[77] unknown $191 = false
|
||||
[78] unknown $192 = "hello"
|
||||
[79] unknown $193 = "world"
|
||||
[80] unknown $194 = true
|
||||
[81] unknown $195 = "hello"
|
||||
[82] unknown $196 = "world"
|
||||
[83] unknown $197 = false
|
||||
[84] unknown $198 = "hello"
|
||||
[85] unknown $199 = "world"
|
||||
[86] unknown $200 = true
|
||||
[87] unknown $201 = true
|
||||
[88] unknown $202 = true
|
||||
[89] unknown $203 = true
|
||||
[90] unknown $204 = true
|
||||
[91] unknown $205 = true
|
||||
[92] unknown $206 = false
|
||||
[93] unknown $207 = true
|
||||
[94] unknown $208 = true
|
||||
[95] unknown $209 = true
|
||||
[96] unknown $210 = true
|
||||
[97] unknown $211 = true
|
||||
[98] unknown $212 = false
|
||||
[99] unknown $213 = 5
|
||||
[100] unknown $214 = 60
|
||||
[101] unknown $215 = 300
|
||||
[102] unknown $216 = 60
|
||||
[103] unknown $217 = 18000
|
||||
[104] unknown $218 = 1000
|
||||
[105] unknown $219 = 18000000
|
||||
[106] unknown $221 = StoreLocal Let unknown x$220 = unknown $219
|
||||
[107] unknown $222 = 18000000
|
||||
[108] unknown $223 = <undefined>
|
||||
[109] Return unknown $223
|
||||
@@ -1,33 +0,0 @@
|
||||
---
|
||||
source: crates/react_fixtures/tests/fixtures_test.rs
|
||||
expression: "format!(\"Input:\\n{input}\\n\\nOutput:\\n{output}\")"
|
||||
input_file: crates/react_fixtures/tests/fixtures/destructure-array.js
|
||||
---
|
||||
Input:
|
||||
function Component(a, b) {
|
||||
const [c, , ...d] = a;
|
||||
const [[[e]], ...[f]] = b;
|
||||
return [c, d, e, f];
|
||||
}
|
||||
|
||||
|
||||
Output:
|
||||
function Component(
|
||||
unknown a$22,
|
||||
unknown b$23,
|
||||
)
|
||||
entry bb0
|
||||
bb0 (block)
|
||||
[0] unknown $24 = LoadLocal unknown a$22
|
||||
[1] unknown $27 = Destructure [ unknown c$25, <hole>, ...unknown d$26 ] = unknown $24
|
||||
[2] unknown $28 = LoadLocal unknown b$23
|
||||
[3] unknown $31 = Destructure [ unknown $29, ...unknown $30 ] = unknown $28
|
||||
[4] unknown $33 = Destructure [ unknown $32 ] = unknown $29
|
||||
[5] unknown $35 = Destructure [ unknown e$34 ] = unknown $32
|
||||
[6] unknown $37 = Destructure [ unknown f$36 ] = unknown $30
|
||||
[7] unknown $38 = LoadLocal unknown c$25
|
||||
[8] unknown $39 = LoadLocal unknown d$26
|
||||
[9] unknown $40 = LoadLocal unknown e$34
|
||||
[10] unknown $41 = LoadLocal unknown f$36
|
||||
[11] unknown $42 = Array [unknown $38, unknown $39, unknown $40, unknown $41]
|
||||
[12] Return unknown $42
|
||||
@@ -1,46 +0,0 @@
|
||||
---
|
||||
source: crates/react_fixtures/tests/fixtures_test.rs
|
||||
expression: "format!(\"Input:\\n{input}\\n\\nOutput:\\n{output}\")"
|
||||
input_file: crates/react_fixtures/tests/fixtures/destructure-object.js
|
||||
---
|
||||
Input:
|
||||
function Component(a, b) {
|
||||
const {
|
||||
c,
|
||||
d,
|
||||
e: { e },
|
||||
f: { _f: f },
|
||||
g: {
|
||||
g: {
|
||||
g: { g, ...h },
|
||||
},
|
||||
},
|
||||
...i
|
||||
} = a;
|
||||
return [c, d, e, f, g, h, i];
|
||||
}
|
||||
|
||||
|
||||
Output:
|
||||
function Component(
|
||||
unknown a$30,
|
||||
unknown b$31,
|
||||
)
|
||||
entry bb0
|
||||
bb0 (block)
|
||||
[0] unknown $32 = LoadLocal unknown a$30
|
||||
[1] unknown $39 = Destructure { c: unknown c$33, d: unknown d$34, e: unknown $35, f: unknown $36, g: unknown $37, ...unknown i$38 } = unknown $32
|
||||
[2] unknown $41 = Destructure { e: unknown e$40 } = unknown $35
|
||||
[3] unknown $43 = Destructure { _f: unknown f$42 } = unknown $36
|
||||
[4] unknown $45 = Destructure { g: unknown $44 } = unknown $37
|
||||
[5] unknown $47 = Destructure { g: unknown $46 } = unknown $44
|
||||
[6] unknown $50 = Destructure { g: unknown g$48, ...unknown h$49 } = unknown $46
|
||||
[7] unknown $51 = LoadLocal unknown c$33
|
||||
[8] unknown $52 = LoadLocal unknown d$34
|
||||
[9] unknown $53 = LoadLocal unknown e$40
|
||||
[10] unknown $54 = LoadLocal unknown f$42
|
||||
[11] unknown $55 = LoadLocal unknown g$48
|
||||
[12] unknown $56 = LoadLocal unknown h$49
|
||||
[13] unknown $57 = LoadLocal unknown i$38
|
||||
[14] unknown $58 = Array [unknown $51, unknown $52, unknown $53, unknown $54, unknown $55, unknown $56, unknown $57]
|
||||
[15] Return unknown $58
|
||||
@@ -1,13 +0,0 @@
|
||||
---
|
||||
source: crates/react_fixtures/tests/fixtures_test.rs
|
||||
expression: "format!(\"Input:\\n{input}\\n\\nOutput:\\n{output}\")"
|
||||
input_file: crates/react_fixtures/tests/fixtures/error.assign-to-global.js
|
||||
---
|
||||
Input:
|
||||
function foo() {
|
||||
x = true;
|
||||
}
|
||||
|
||||
|
||||
Output:
|
||||
React functions may not reassign variables defined outside of the component or hook
|
||||
@@ -1,54 +0,0 @@
|
||||
---
|
||||
source: crates/react_fixtures/tests/fixtures_test.rs
|
||||
expression: "format!(\"Input:\\n{input}\\n\\nOutput:\\n{output}\")"
|
||||
input_file: crates/react_fixtures/tests/fixtures/for-statement.js
|
||||
---
|
||||
Input:
|
||||
function foo() {
|
||||
let x = 0;
|
||||
for (let i = 0; i < 10; i = i + 1) {
|
||||
x = x + i;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
|
||||
Output:
|
||||
function foo(
|
||||
)
|
||||
entry bb0
|
||||
bb0 (block)
|
||||
[0] unknown $19 = 0
|
||||
[1] unknown $21 = StoreLocal Let unknown x$20 = unknown $19
|
||||
[2] For init=bb3 test=bb1 update=bb4 body=bb5 fallthrough=bb2
|
||||
bb3 (loop)
|
||||
predecessors: bb0
|
||||
[3] unknown $22 = 0
|
||||
[4] unknown $24 = StoreLocal Let unknown i$23 = unknown $22
|
||||
[5] Goto bb1
|
||||
bb1 (loop)
|
||||
predecessors: bb3, bb4
|
||||
i$25: phi(bb3: i$23, bb4: i$38)
|
||||
x$29: phi(bb3: x$20, bb4: x$33)
|
||||
[6] unknown $26 = LoadLocal unknown i$25
|
||||
[7] unknown $27 = 10
|
||||
[8] unknown $28 = Binary unknown $26 < unknown $27
|
||||
[9] Branch unknown $28 consequent=bb5 alternate=bb2
|
||||
bb5 (block)
|
||||
predecessors: bb1
|
||||
[10] unknown $30 = LoadLocal unknown x$29
|
||||
[11] unknown $31 = LoadLocal unknown i$25
|
||||
[12] unknown $32 = Binary unknown $30 + unknown $31
|
||||
[13] unknown $34 = StoreLocal Reassign unknown x$33 = unknown $32
|
||||
[14] Goto bb4
|
||||
bb4 (loop)
|
||||
predecessors: bb5
|
||||
[15] unknown $35 = LoadLocal unknown i$25
|
||||
[16] unknown $36 = 1
|
||||
[17] unknown $37 = Binary unknown $35 + unknown $36
|
||||
[18] unknown $39 = StoreLocal Reassign unknown i$38 = unknown $37
|
||||
[19] Goto bb1
|
||||
bb2 (block)
|
||||
predecessors: bb1
|
||||
[20] unknown $40 = LoadLocal unknown x$29
|
||||
[21] Return unknown $40
|
||||
@@ -1,94 +0,0 @@
|
||||
---
|
||||
source: crates/react_fixtures/tests/fixtures_test.rs
|
||||
expression: "format!(\"Input:\\n{input}\\n\\nOutput:\\n{output}\")"
|
||||
input_file: crates/react_fixtures/tests/fixtures/function-expressions.js
|
||||
---
|
||||
Input:
|
||||
function Component(props) {
|
||||
const x = 2;
|
||||
const foo = function foo(y) {
|
||||
let a = 1;
|
||||
let b;
|
||||
if (a === 1) {
|
||||
b = 5 + 3;
|
||||
} else {
|
||||
b = false;
|
||||
}
|
||||
x + y + a + b;
|
||||
const bar = function bar(z) {
|
||||
let c = 2;
|
||||
let d;
|
||||
d = 3;
|
||||
x + y + a + b + z + c + d;
|
||||
};
|
||||
bar;
|
||||
foo;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Output:
|
||||
function Component(
|
||||
unknown props$58,
|
||||
)
|
||||
entry bb0
|
||||
bb0 (block)
|
||||
[0] unknown $59 = 2
|
||||
[1] unknown $61 = StoreLocal Const unknown x$60 = unknown $59
|
||||
[2] unknown $62 = Function @deps[] @context[unknown x$60]:
|
||||
function foo(
|
||||
unknown y$63,
|
||||
)
|
||||
entry bb1
|
||||
bb1 (block)
|
||||
[0] unknown $64 = 1
|
||||
[1] unknown $66 = StoreLocal Let unknown a$65 = unknown $64
|
||||
[2] unknown $68 = DeclareLocal Let unknown b$67
|
||||
[3] unknown $69 = 1
|
||||
[4] unknown $70 = 1
|
||||
[5] unknown $71 = true
|
||||
[6] unknown $72 = 5
|
||||
[7] unknown $73 = 3
|
||||
[8] unknown $74 = 8
|
||||
[9] unknown $76 = StoreLocal Reassign unknown b$75 = unknown $74
|
||||
[10] unknown $81 = 2
|
||||
[11] unknown $83 = LoadLocal unknown y$63
|
||||
[12] unknown $84 = Binary unknown $81 + unknown $83
|
||||
[13] unknown $86 = 1
|
||||
[14] unknown $87 = Binary unknown $84 + unknown $86
|
||||
[15] unknown $89 = 8
|
||||
[16] unknown $90 = Binary unknown $87 + unknown $89
|
||||
[17] unknown $91 = Function @deps[] @context[unknown x$60, unknown y$63, unknown a$65, unknown b$75]:
|
||||
function bar(
|
||||
unknown z$92,
|
||||
)
|
||||
entry bb5
|
||||
bb5 (block)
|
||||
[0] unknown $93 = 2
|
||||
[1] unknown $95 = StoreLocal Let unknown c$94 = unknown $93
|
||||
[2] unknown $97 = DeclareLocal Let unknown d$96
|
||||
[3] unknown $98 = 3
|
||||
[4] unknown $100 = StoreLocal Reassign unknown d$99 = unknown $98
|
||||
[5] unknown $101 = LoadLocal unknown x$80
|
||||
[6] unknown $102 = LoadLocal unknown y$82
|
||||
[7] unknown $103 = Binary unknown $101 + unknown $102
|
||||
[8] unknown $104 = LoadLocal unknown a$85
|
||||
[9] unknown $105 = Binary unknown $103 + unknown $104
|
||||
[10] unknown $106 = LoadLocal unknown b$88
|
||||
[11] unknown $107 = Binary unknown $105 + unknown $106
|
||||
[12] unknown $108 = LoadLocal unknown z$92
|
||||
[13] unknown $109 = Binary unknown $107 + unknown $108
|
||||
[14] unknown $110 = 2
|
||||
[15] unknown $111 = Binary unknown $109 + unknown $110
|
||||
[16] unknown $112 = 3
|
||||
[17] unknown $113 = Binary unknown $111 + unknown $112
|
||||
[18] unknown $114 = <undefined>
|
||||
[19] Return unknown $114
|
||||
[18] unknown $116 = StoreLocal Const unknown bar$115 = unknown $91
|
||||
[19] unknown $117 = LoadLocal unknown bar$115
|
||||
[20] unknown $118 = LoadGlobal foo
|
||||
[21] unknown $119 = <undefined>
|
||||
[22] Return unknown $119
|
||||
[3] unknown $121 = StoreLocal Const unknown foo$120 = unknown $62
|
||||
[4] unknown $122 = <undefined>
|
||||
[5] Return unknown $122
|
||||
@@ -1,41 +0,0 @@
|
||||
---
|
||||
source: crates/react_fixtures/tests/fixtures_test.rs
|
||||
expression: "format!(\"Input:\\n{input}\\n\\nOutput:\\n{output}\")"
|
||||
input_file: crates/react_fixtures/tests/fixtures/identifiers.js
|
||||
---
|
||||
Input:
|
||||
// import React from "react";
|
||||
|
||||
// const FOO = false;
|
||||
|
||||
function id(x) {
|
||||
// React;
|
||||
// FOO;
|
||||
Math;
|
||||
id;
|
||||
let y = true;
|
||||
y = false;
|
||||
y;
|
||||
let z;
|
||||
z;
|
||||
return x;
|
||||
}
|
||||
|
||||
|
||||
Output:
|
||||
function id(
|
||||
unknown x$14,
|
||||
)
|
||||
entry bb0
|
||||
bb0 (block)
|
||||
[0] unknown $15 = LoadGlobal Math
|
||||
[1] unknown $16 = LoadGlobal id
|
||||
[2] unknown $17 = true
|
||||
[3] unknown $19 = StoreLocal Let unknown y$18 = unknown $17
|
||||
[4] unknown $20 = false
|
||||
[5] unknown $22 = StoreLocal Reassign unknown y$21 = unknown $20
|
||||
[6] unknown $23 = false
|
||||
[7] unknown $25 = DeclareLocal Let unknown z$24
|
||||
[8] unknown $26 = LoadLocal unknown z$24
|
||||
[9] unknown $27 = LoadLocal unknown x$14
|
||||
[10] Return unknown $27
|
||||
@@ -1,40 +0,0 @@
|
||||
---
|
||||
source: crates/react_fixtures/tests/fixtures_test.rs
|
||||
expression: "format!(\"Input:\\n{input}\\n\\nOutput:\\n{output}\")"
|
||||
input_file: crates/react_fixtures/tests/fixtures/if-statement.js
|
||||
---
|
||||
Input:
|
||||
function foo(a, b, c, d) {
|
||||
if (a) {
|
||||
return b;
|
||||
} else {
|
||||
c;
|
||||
}
|
||||
d;
|
||||
}
|
||||
|
||||
|
||||
Output:
|
||||
function foo(
|
||||
unknown a$9,
|
||||
unknown b$10,
|
||||
unknown c$11,
|
||||
unknown d$12,
|
||||
)
|
||||
entry bb0
|
||||
bb0 (block)
|
||||
[0] unknown $13 = LoadLocal unknown a$9
|
||||
[1] If unknown $13 consequent=bb2 alternate=bb4 fallthrough=bb1
|
||||
bb2 (block)
|
||||
predecessors: bb0
|
||||
[2] unknown $14 = LoadLocal unknown b$10
|
||||
[3] Return unknown $14
|
||||
bb4 (block)
|
||||
predecessors: bb0
|
||||
[4] unknown $15 = LoadLocal unknown c$11
|
||||
[5] Goto bb1
|
||||
bb1 (block)
|
||||
predecessors: bb4
|
||||
[6] unknown $16 = LoadLocal unknown d$12
|
||||
[7] unknown $17 = <undefined>
|
||||
[8] Return unknown $17
|
||||
@@ -1,46 +0,0 @@
|
||||
---
|
||||
source: crates/react_fixtures/tests/fixtures_test.rs
|
||||
expression: "format!(\"Input:\\n{input}\\n\\nOutput:\\n{output}\")"
|
||||
input_file: crates/react_fixtures/tests/fixtures/simple-function.js
|
||||
---
|
||||
Input:
|
||||
function Component(a) {
|
||||
Math;
|
||||
let b = 0;
|
||||
const foo = function foo_(c) {
|
||||
let d = 1;
|
||||
return a + b + c + d;
|
||||
};
|
||||
return foo();
|
||||
}
|
||||
|
||||
|
||||
Output:
|
||||
function Component(
|
||||
unknown a$23,
|
||||
)
|
||||
entry bb0
|
||||
bb0 (block)
|
||||
[0] unknown $24 = LoadGlobal Math
|
||||
[1] unknown $25 = 0
|
||||
[2] unknown $27 = StoreLocal Let unknown b$26 = unknown $25
|
||||
[3] unknown $28 = Function @deps[] @context[unknown a$23, unknown b$26]:
|
||||
function foo_(
|
||||
unknown c$29,
|
||||
)
|
||||
entry bb1
|
||||
bb1 (block)
|
||||
[0] unknown $30 = 1
|
||||
[1] unknown $32 = StoreLocal Let unknown d$31 = unknown $30
|
||||
[2] unknown $33 = LoadLocal unknown a$23
|
||||
[3] unknown $34 = 0
|
||||
[4] unknown $35 = Binary unknown $33 + unknown $34
|
||||
[5] unknown $36 = LoadLocal unknown c$29
|
||||
[6] unknown $37 = Binary unknown $35 + unknown $36
|
||||
[7] unknown $38 = 1
|
||||
[8] unknown $39 = Binary unknown $37 + unknown $38
|
||||
[9] Return unknown $39
|
||||
[4] unknown $41 = StoreLocal Const unknown foo$40 = unknown $28
|
||||
[5] unknown $42 = LoadLocal unknown foo$40
|
||||
[6] unknown $43 = Call unknown $42()
|
||||
[7] Return unknown $43
|
||||
@@ -1,41 +0,0 @@
|
||||
---
|
||||
source: crates/react_fixtures/tests/fixtures_test.rs
|
||||
expression: "format!(\"Input:\\n{input}\\n\\nOutput:\\n{output}\")"
|
||||
input_file: crates/react_fixtures/tests/fixtures/simple-ssa.js
|
||||
---
|
||||
Input:
|
||||
function Component(props) {
|
||||
let a;
|
||||
if (props) {
|
||||
a = 1;
|
||||
} else {
|
||||
a = 2;
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
|
||||
Output:
|
||||
function Component(
|
||||
unknown props$10,
|
||||
)
|
||||
entry bb0
|
||||
bb0 (block)
|
||||
[0] unknown $12 = DeclareLocal Let unknown a$11
|
||||
[1] unknown $13 = LoadLocal unknown props$10
|
||||
[2] If unknown $13 consequent=bb2 alternate=bb3 fallthrough=bb1
|
||||
bb2 (block)
|
||||
predecessors: bb0
|
||||
[3] unknown $14 = 1
|
||||
[4] unknown $16 = StoreLocal Reassign unknown a$15 = unknown $14
|
||||
[5] Goto bb1
|
||||
bb3 (block)
|
||||
predecessors: bb0
|
||||
[6] unknown $17 = 2
|
||||
[7] unknown $19 = StoreLocal Reassign unknown a$18 = unknown $17
|
||||
[8] Goto bb1
|
||||
bb1 (block)
|
||||
predecessors: bb2, bb3
|
||||
a$20: phi(bb2: a$15, bb3: a$18)
|
||||
[9] unknown $21 = LoadLocal unknown a$20
|
||||
[10] Return unknown $21
|
||||
@@ -1,27 +0,0 @@
|
||||
---
|
||||
source: crates/react_fixtures/tests/fixtures_test.rs
|
||||
expression: "format!(\"Input:\\n{input}\\n\\nOutput:\\n{output}\")"
|
||||
input_file: crates/react_fixtures/tests/fixtures/simple.js
|
||||
---
|
||||
Input:
|
||||
function test() {
|
||||
[true, false, null, 1, 3.14, ...["hello world!"]];
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
||||
Output:
|
||||
function test(
|
||||
)
|
||||
entry bb0
|
||||
bb0 (block)
|
||||
[0] unknown $10 = true
|
||||
[1] unknown $11 = false
|
||||
[2] unknown $12 = null
|
||||
[3] unknown $13 = 1
|
||||
[4] unknown $14 = 3.14
|
||||
[5] unknown $15 = "hello world!"
|
||||
[6] unknown $16 = Array [unknown $15]
|
||||
[7] unknown $17 = Array [unknown $10, unknown $11, unknown $12, unknown $13, unknown $14, ...unknown $16]
|
||||
[8] unknown $18 = 2
|
||||
[9] Return unknown $18
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user