├── .github ├── CODEOWNERS ├── dependabot.yml └── workflows │ ├── audit.yml │ ├── ci.yml │ ├── release.yml │ ├── scorecard.yml │ └── update-swc.yml ├── .gitignore ├── .nvmrc ├── .release-please-manifest.json ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE.md ├── README.md ├── biome.json ├── commitlint.config.mjs ├── deny.toml ├── deps └── swc │ ├── .cargo │ └── config.toml │ ├── Cargo.lock │ ├── Cargo.toml │ ├── LICENSE │ ├── bindings │ ├── .gitignore │ ├── Cargo.lock │ ├── Cargo.toml │ ├── README.md │ ├── binding_core_node │ │ ├── Cargo.toml │ │ ├── LICENSE │ │ ├── build.rs │ │ └── src │ │ │ ├── analyze.rs │ │ │ ├── bundle.rs │ │ │ ├── lib.rs │ │ │ ├── minify.rs │ │ │ ├── parse.rs │ │ │ ├── print.rs │ │ │ ├── transform.rs │ │ │ └── util.rs │ ├── binding_core_wasm │ │ ├── Cargo.toml │ │ ├── LICENSE │ │ ├── __tests__ │ │ │ ├── error.js │ │ │ └── simple.js │ │ ├── example │ │ │ ├── .gitignore │ │ │ ├── index.js │ │ │ ├── package.json │ │ │ ├── readme.txt │ │ │ └── webpack.config.js │ │ ├── package.json │ │ ├── scripts │ │ │ └── test.sh │ │ └── src │ │ │ ├── lib.rs │ │ │ └── types.rs │ ├── binding_html_node │ │ ├── Cargo.toml │ │ ├── build.rs │ │ └── src │ │ │ ├── lib.rs │ │ │ └── util.rs │ ├── binding_minifier_node │ │ ├── Cargo.toml │ │ ├── LICENSE │ │ ├── build.rs │ │ └── src │ │ │ ├── lib.rs │ │ │ ├── minify.rs │ │ │ └── util.rs │ ├── binding_minifier_wasm │ │ ├── Cargo.toml │ │ ├── LICENSE │ │ ├── __tests__ │ │ │ ├── __snapshots__ │ │ │ │ └── simple.js.snap │ │ │ └── simple.js │ │ ├── package.json │ │ ├── scripts │ │ │ └── test.sh │ │ └── src │ │ │ ├── lib.rs │ │ │ └── types.rs │ ├── binding_typescript_wasm │ │ ├── .cargo │ │ │ └── config.toml │ │ ├── Cargo.toml │ │ ├── LICENSE │ │ ├── README.md │ │ ├── __tests__ │ │ │ ├── __snapshots__ │ │ │ │ └── transform.js.snap │ │ │ └── transform.js │ │ ├── package.json │ │ ├── scripts │ │ │ ├── build.sh │ │ │ ├── esm.mjs │ │ │ ├── esm.sh │ │ │ ├── patch.mjs │ │ │ └── test.sh │ │ └── src │ │ │ ├── error_reporter.rs │ │ │ ├── lib.rs │ │ │ └── wasm-node.js │ ├── node_macro_deps │ │ ├── Cargo.toml │ │ ├── README.md │ │ └── src │ │ │ └── lib.rs │ └── swc_cli │ │ ├── Cargo.toml │ │ └── src │ │ └── main.rs │ ├── rust-toolchain │ └── xtask │ ├── Cargo.toml │ └── src │ ├── bench.rs │ ├── clean.rs │ ├── es │ ├── minifier.rs │ └── mod.rs │ ├── git │ ├── mod.rs │ └── reduce │ │ ├── core_ver.rs │ │ └── mod.rs │ ├── main.rs │ ├── npm │ ├── mod.rs │ ├── nightly.rs │ └── util.rs │ └── util │ └── mod.rs ├── esbuild.config.mjs ├── lib ├── LICENSE ├── README.md ├── package.json ├── wasm.d.ts ├── wasm.js └── wasm_bg.wasm.d.ts ├── package.json ├── release-please-config.json ├── src ├── errors.ts ├── index.ts ├── register │ ├── register-strip.mjs │ └── register-transform.mjs ├── strip-loader.ts ├── transform-loader.ts └── transform.ts ├── test ├── fixtures │ ├── enum.ts │ ├── hello.js │ ├── hello.ts │ ├── invalid-syntax.ts │ └── stacktrace.ts ├── index.test.js ├── loader.test.js ├── snapshots │ ├── index.test.js.snapshot │ ├── snapshot-config.js │ └── transform.test.js.snapshot ├── transform.test.js └── util │ └── util.js ├── tools ├── build-wasm.js └── update-swc.sh └── tsconfig.json /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @marco-ippolito 2 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # Basic set up for three package managers 2 | 3 | version: 2 4 | updates: 5 | 6 | # Maintain dependencies for GitHub Actions 7 | - package-ecosystem: "github-actions" 8 | directory: "/" 9 | schedule: 10 | interval: "weekly" 11 | -------------------------------------------------------------------------------- /.github/workflows/audit.yml: -------------------------------------------------------------------------------- 1 | name: Security audit 2 | 3 | on: 4 | schedule: 5 | # Runs at 00:00 UTC everyday 6 | - cron: '0 0 * * *' 7 | pull_request: 8 | paths: 9 | - 'deps/**' 10 | - '.github/workflows/audit.yml' 11 | - package.json 12 | - lib/** 13 | - src/** 14 | 15 | jobs: 16 | rust-audit: 17 | runs-on: ubuntu-22.04 18 | steps: 19 | - name: Checkout repository 20 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 21 | - uses: EmbarkStudios/cargo-deny-action@34899fc7ba81ca6268d5947a7a16b4649013fea1 # v2.0.11 22 | with: 23 | manifest-path: "deps/swc/bindings/binding_typescript_wasm/Cargo.toml" 24 | 25 | typescript-audit: 26 | runs-on: ubuntu-22.04 27 | permissions: 28 | security-events: write 29 | packages: read 30 | actions: read 31 | contents: read 32 | strategy: 33 | matrix: 34 | include: 35 | - language: javascript-typescript 36 | steps: 37 | - name: Checkout repository 38 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 39 | - name: Initialize CodeQL 40 | uses: github/codeql-action/init@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v3.28.18 41 | with: 42 | languages: ${{ matrix.language }} 43 | - name: Perform CodeQL Analysis 44 | uses: github/codeql-action/analyze@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v3.28.18 45 | with: 46 | category: "/language:${{matrix.language}}" 47 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | pull_request: 5 | 6 | jobs: 7 | commit-lint: 8 | name: Commit Lint 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 12 | with: 13 | fetch-depth: 0 14 | - uses: wagoid/commitlint-github-action@b948419dd99f3fd78a6548d48f94e3df7f6bf3ed # v6.2.1 15 | 16 | code-quality: 17 | name: Code Quality 18 | needs: commit-lint 19 | runs-on: ubuntu-latest 20 | steps: 21 | - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 22 | - name: Setup Biome CLI 23 | uses: biomejs/setup-biome@f382a98e582959e6aaac8e5f8b17b31749018780 # v2.5.0 24 | - name: Run Biome 25 | run: biome ci 26 | 27 | build-and-test: 28 | needs: code-quality 29 | strategy: 30 | fail-fast: false 31 | matrix: 32 | node: 33 | - 22 34 | - 23 35 | platform: 36 | - ubuntu-latest 37 | - macos-latest 38 | - windows-latest 39 | name: "${{matrix.platform}} w/ Node.js ${{matrix.node}}.x" 40 | runs-on: ${{matrix.platform}} 41 | steps: 42 | - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 43 | - name: "Use Node.js ${{matrix.node}}.x" 44 | uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 45 | with: 46 | node-version: ${{matrix.node}}.x 47 | - run: npm install 48 | - run: npm run typecheck 49 | - run: npm run build 50 | - run: npm test 51 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: release 2 | on: 3 | push: 4 | branches: 5 | - main 6 | workflow_dispatch: 7 | 8 | permissions: 9 | contents: read 10 | 11 | jobs: 12 | release-please: 13 | runs-on: ubuntu-latest 14 | outputs: 15 | release_created: ${{ steps.release.outputs.release_created }} 16 | permissions: 17 | contents: write 18 | pull-requests: write 19 | steps: 20 | - uses: googleapis/release-please-action@a02a34c4d625f9be7cb89156071d8567266a2445 # v4.2.0 21 | id: release 22 | with: 23 | token: ${{ secrets.RELEASE_PLEASE_GITHUB_TOKEN }} 24 | config-file: release-please-config.json 25 | manifest-file: .release-please-manifest.json 26 | 27 | release: 28 | needs: release-please 29 | if: ${{ needs.release-please.outputs.release_created }} 30 | runs-on: ubuntu-latest 31 | permissions: 32 | contents: write 33 | id-token: write 34 | steps: 35 | - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 36 | - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 37 | with: 38 | node-version-file: '.nvmrc' 39 | registry-url: 'https://registry.npmjs.org' 40 | - run: npm install 41 | - run: npm run build 42 | - name: Create NPM release 43 | run: npm publish --provenance --access public 44 | env: 45 | NODE_AUTH_TOKEN: ${{ secrets.NPM_AUTH_TOKEN }} 46 | -------------------------------------------------------------------------------- /.github/workflows/scorecard.yml: -------------------------------------------------------------------------------- 1 | # This workflow uses actions that are not certified by GitHub. They are provided 2 | # by a third-party and are governed by separate terms of service, privacy 3 | # policy, and support documentation. 4 | 5 | name: Scorecard supply-chain security 6 | on: 7 | # For Branch-Protection check. Only the default branch is supported. See 8 | # https://github.com/ossf/scorecard/blob/main/docs/checks.md#branch-protection 9 | branch_protection_rule: 10 | # To guarantee Maintained check is occasionally updated. See 11 | # https://github.com/ossf/scorecard/blob/main/docs/checks.md#maintained 12 | schedule: 13 | - cron: '20 7 * * 2' 14 | push: 15 | branches: ["main"] 16 | 17 | # Declare default permissions as read only. 18 | permissions: read-all 19 | 20 | jobs: 21 | analysis: 22 | name: Scorecard analysis 23 | runs-on: ubuntu-latest 24 | permissions: 25 | # Needed to upload the results to code-scanning dashboard. 26 | security-events: write 27 | # Needed to publish results and get a badge (see publish_results below). 28 | id-token: write 29 | contents: read 30 | actions: read 31 | 32 | steps: 33 | - name: Harden Runner 34 | uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 35 | with: 36 | egress-policy: audit 37 | 38 | - name: "Checkout code" 39 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 40 | with: 41 | persist-credentials: false 42 | 43 | - name: "Run analysis" 44 | uses: ossf/scorecard-action@f49aabe0b5af0936a0987cfb85d86b75731b0186 # v2.4.1 45 | with: 46 | results_file: results.sarif 47 | results_format: sarif 48 | # (Optional) "write" PAT token. Uncomment the `repo_token` line below if: 49 | # - you want to enable the Branch-Protection check on a *public* repository, or 50 | # - you are installing Scorecards on a *private* repository 51 | # To create the PAT, follow the steps in https://github.com/ossf/scorecard-action#authentication-with-pat. 52 | # repo_token: ${{ secrets.SCORECARD_TOKEN }} 53 | 54 | # Public repositories: 55 | # - Publish results to OpenSSF REST API for easy access by consumers 56 | # - Allows the repository to include the Scorecard badge. 57 | # - See https://github.com/ossf/scorecard-action#publishing-results. 58 | # For private repositories: 59 | # - `publish_results` will always be set to `false`, regardless 60 | # of the value entered here. 61 | publish_results: true 62 | 63 | # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF 64 | # format to the repository Actions tab. 65 | - name: "Upload artifact" 66 | uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 67 | with: 68 | name: SARIF file 69 | path: results.sarif 70 | retention-days: 5 71 | 72 | # Upload the results to GitHub's code scanning dashboard. 73 | - name: "Upload to code-scanning" 74 | uses: github/codeql-action/upload-sarif@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v3.28.18 75 | with: 76 | sarif_file: results.sarif 77 | -------------------------------------------------------------------------------- /.github/workflows/update-swc.yml: -------------------------------------------------------------------------------- 1 | name: Update SWC and Build WASM 2 | 3 | on: 4 | workflow_dispatch: 5 | inputs: 6 | swc_version: 7 | description: 'SWC version to update to (e.g., 1.7.5)' 8 | required: false 9 | schedule: 10 | - cron: '0 0 * * 1' # Every Monday at 00:00 UTC 11 | 12 | env: 13 | NODE_VERSION: lts/* 14 | 15 | jobs: 16 | update-swc: 17 | runs-on: ubuntu-latest 18 | permissions: 19 | contents: write 20 | pull-requests: write 21 | steps: 22 | - name: Checkout repository 23 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 24 | with: 25 | persist-credentials: false 26 | 27 | - name: Set up Node.js 28 | uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 29 | 30 | - name: Check if SWC update is required 31 | id: version-check 32 | run: | 33 | CURRENT_SWC_VERSION=$(cat lib/package.json | jq -r '.version') 34 | if [[ -n "${{ github.event.inputs.swc_version }}" ]]; then 35 | NEW_SWC_VERSION="${{ github.event.inputs.swc_version }}" 36 | else 37 | NEW_SWC_VERSION=$(npm view @swc/core version) 38 | fi 39 | 40 | echo "CURRENT_SWC_VERSION=$CURRENT_SWC_VERSION" >> $GITHUB_OUTPUT 41 | echo "NEW_SWC_VERSION=$NEW_SWC_VERSION" >> $GITHUB_OUTPUT 42 | 43 | if [[ "$CURRENT_SWC_VERSION" != "$NEW_SWC_VERSION" ]]; then 44 | echo "UPDATE_REQUIRED=true" >> $GITHUB_OUTPUT 45 | else 46 | echo "UPDATE_REQUIRED=false" >> $GITHUB_OUTPUT 47 | fi 48 | 49 | - name: Update SWC 50 | if: steps.version-check.outputs.UPDATE_REQUIRED == 'true' 51 | run: ./tools/update-swc.sh 52 | 53 | - name: Create Pull Request with first commit 54 | if: steps.version-check.outputs.UPDATE_REQUIRED == 'true' 55 | uses: gr2m/create-or-update-pull-request-action@b65137ca591da0b9f43bad7b24df13050ea45d1b # v1.10.1 56 | env: 57 | GITHUB_TOKEN: ${{ secrets.RELEASE_PLEASE_GITHUB_TOKEN }} 58 | with: 59 | author: Node.js GitHub Bot 60 | title: "chore(deps): update SWC to v${{ github.event.inputs.swc_version || steps.version-check.outputs.NEW_SWC_VERSION }}" 61 | branch: "chore/update-swc-${{ github.event.inputs.swc_version || steps.version-check.outputs.NEW_SWC_VERSION }}" 62 | commit-message: "chore: update swc to v${{ github.event.inputs.swc_version || steps.version-check.outputs.NEW_SWC_VERSION }}" 63 | path: deps 64 | update-pull-request-title-and-body: true 65 | body: | 66 | This PR updates SWC to v${{ github.event.inputs.swc_version || steps.version-check.outputs.NEW_SWC_VERSION }}. 67 | View the [SWC changelog](https://github.com/swc-project/swc/releases/tag/v${{ github.event.inputs.swc_version || steps.version-check.outputs.NEW_SWC_VERSION }}) for more information. 68 | 69 | - name: Set up Docker 70 | if: steps.version-check.outputs.UPDATE_REQUIRED == 'true' 71 | uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # v3.10.0 72 | 73 | - name: Build WASM 74 | if: steps.version-check.outputs.UPDATE_REQUIRED == 'true' 75 | run: node ./tools/build-wasm.js 76 | 77 | - name: Create second commit 78 | if: steps.version-check.outputs.UPDATE_REQUIRED == 'true' 79 | uses: gr2m/create-or-update-pull-request-action@b65137ca591da0b9f43bad7b24df13050ea45d1b # v1.10.1 80 | env: 81 | GITHUB_TOKEN: ${{ secrets.RELEASE_PLEASE_GITHUB_TOKEN }} 82 | with: 83 | author: Node.js GitHub Bot 84 | branch: "chore/update-swc-${{ github.event.inputs.swc_version || steps.version-check.outputs.NEW_SWC_VERSION }}" 85 | commit-message: "chore: build wasm from swc v${{ github.event.inputs.swc_version || steps.version-check.outputs.NEW_SWC_VERSION }}" 86 | path: lib 87 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .vscode 3 | node_modules 4 | dist 5 | package-lock.json 6 | deps/swc/bindings/target/ 7 | -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | 22 2 | -------------------------------------------------------------------------------- /.release-please-manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | ".": "0.5.3" 3 | } 4 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Code of Conduct 2 | 3 | Amaro is committed to upholding the Node.js Code of Conduct. 4 | 5 | The Node.js Code of Conduct document can be found at 6 | 7 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to Amaro 2 | 3 | If you want to build Amaro yourself, you can build the project like this: 4 | 5 | 1. Clone this repository. 6 | 2. Run `npm install`. 7 | 3. Run `npm run build`. 8 | 9 | The `dist/` directory now contains the Amaro build. 10 | You can run the tests with `npm test`. 11 | 12 | ## Developer's Certificate of Origin 1.1 13 | 14 | By making a contribution to this project, I certify that: 15 | 16 | - (a) The contribution was created in whole or in part by me and I 17 | have the right to submit it under the open source license 18 | indicated in the file; or 19 | 20 | - (b) The contribution is based upon previous work that, to the best 21 | of my knowledge, is covered under an appropriate open source 22 | license and I have the right under that license to submit that 23 | work with modifications, whether created in whole or in part 24 | by me, under the same open source license (unless I am 25 | permitted to submit under a different license), as indicated 26 | in the file; or 27 | 28 | - (c) The contribution was provided directly to me by some other 29 | person who certified (a), (b) or (c) and I have not modified 30 | it. 31 | 32 | - (d) I understand and agree that this project and the contribution 33 | are public and that a record of the contribution (including all 34 | personal information I submit with it, including my sign-off) is 35 | maintained indefinitely and may be redistributed consistent with 36 | this project or the open source license(s) involved. 37 | 38 | ## Moderation Policy 39 | 40 | The [Node.js Moderation Policy] applies to this project. 41 | 42 | [Node.js Moderation Policy]: 43 | https://github.com/nodejs/admin/blob/master/Moderation-Policy.md 44 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Marco Ippolito and Amaro contributors 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Amaro 2 | 3 | Amaro is a wrapper around `@swc/wasm-typescript`, a WebAssembly port of the SWC TypeScript parser. 4 | It's used as an internal in Node.js for [Type Stripping](https://nodejs.org/api/typescript.html#type-stripping) but can also be used as a standalone package. 5 | 6 | > Amaro means "bitter" in Italian. It's a reference to [Mount Amaro](https://en.wikipedia.org/wiki/Monte_Amaro_(Abruzzo)) on whose slopes this package was conceived. 7 | 8 | This package provides a stable API for the TypeScript parser and allows users to upgrade to the latest version of TypeScript transpiler indipendently from the one used internally in Node.js. 9 | 10 | ## How to Install 11 | 12 | To install Amaro, run: 13 | 14 | ```shell 15 | npm install amaro 16 | ``` 17 | 18 | ## How to Use 19 | 20 | By default Amaro exports a `transformSync` function that performs type stripping. 21 | Stack traces are preserved, by replacing removed types with white spaces. 22 | 23 | ```javascript 24 | const amaro = require('amaro'); 25 | const { code } = amaro.transformSync("const foo: string = 'bar';", { mode: "strip-only" }); 26 | console.log(code); // "const foo = 'bar';" 27 | ``` 28 | 29 | ### Loader 30 | 31 | It is possible to use Amaro as an external loader to execute TypeScript files. 32 | This allows the installed Amaro to override the Amaro version used by Node.js. 33 | In order to use Amaro as an external loader, type stripping needs to be enabled. 34 | 35 | In node v23 and later you can omit the `--experimental-strip-types` flag, as it is enabled by default. 36 | 37 | ```bash 38 | node --experimental-strip-types --import="amaro/strip" file.ts 39 | ``` 40 | 41 | Enabling TypeScript feature transformation: 42 | 43 | ```bash 44 | node --experimental-transform-types --import="amaro/transform" file.ts 45 | ``` 46 | 47 | > Note that the "amaro/transform" loader should be used with `--experimental-transform-types` flag, or 48 | > at least with `--enable-source-maps` flag, to preserve the original source maps. 49 | 50 | #### Type stripping in dependencies 51 | 52 | Contrary to the Node.js [TypeScript support](https://nodejs.org/docs/latest/api/typescript.html#type-stripping-in-dependencies), when used as a loader, Amaro handles TypeScript files inside folders under a `node_modules` path. 53 | 54 | ### Monorepo usage 55 | 56 | Amaro makes working in monorepos smoother by removing the need to rebuild internal packages during development. When used with the [`--conditions`](https://nodejs.org/docs/latest/api/cli.html#-c-condition---conditionscondition) flag, you can reference TypeScript source files directly in exports: 57 | 58 | ```json 59 | "exports": { 60 | ".": { 61 | "typescript": "./src/index.ts", 62 | "types": "./dist/index.d.ts", 63 | "require": "./dist/index.js", 64 | "import": "./dist/index.js" 65 | } 66 | } 67 | ``` 68 | 69 | Then run your app with: 70 | 71 | ```bash 72 | node --watch --import="amaro/strip" --conditions=typescript ./src/index.ts 73 | ``` 74 | 75 | This setup allows Node.js to load TypeScript files from linked packages without a build step. Changes to any package are picked up immediately, speeding up and simplifying local development in monorepos. 76 | 77 | ### TypeScript Version 78 | 79 | The supported TypeScript version is 5.8. 80 | 81 | ## License (MIT) 82 | 83 | See [`LICENSE.md`](./LICENSE.md). 84 | -------------------------------------------------------------------------------- /biome.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://biomejs.dev/schemas/1.8.3/schema.json", 3 | "organizeImports": { 4 | "enabled": true 5 | }, 6 | "linter": { 7 | "enabled": true, 8 | "rules": { 9 | "recommended": true 10 | } 11 | }, 12 | "formatter": { 13 | "enabled": true 14 | }, 15 | "files": { 16 | "ignore": [ 17 | "package.json", 18 | "dist/**", 19 | "deps/**", 20 | "lib/**", 21 | "node_modules/**", 22 | "test/snapshot/**", 23 | "test/fixtures/**" 24 | ] 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /commitlint.config.mjs: -------------------------------------------------------------------------------- 1 | export default { 2 | extends: ["@commitlint/config-conventional"], 3 | rules: { 4 | "body-max-line-length": [0, "always"], 5 | }, 6 | }; 7 | -------------------------------------------------------------------------------- /deny.toml: -------------------------------------------------------------------------------- 1 | [graph] 2 | targets = [] 3 | 4 | [advisories] 5 | ignore = [] 6 | 7 | [licenses] 8 | allow = [ 9 | "Apache-2.0", 10 | "Apache-2.0 WITH LLVM-exception", 11 | "MIT", 12 | "MPL-2.0", 13 | "BSD-3-Clause", 14 | "BSD-2-Clause", 15 | "Unicode-DFS-2016", 16 | "BSL-1.0", 17 | "Unicode-3.0" 18 | ] 19 | confidence-threshold = 0.8 20 | exceptions = [] 21 | 22 | [licenses.private] 23 | ignore = false 24 | registries = [] 25 | 26 | [bans] 27 | multiple-versions = "allow" 28 | wildcards = "allow" 29 | highlight = "all" 30 | allow = [] 31 | deny = [] 32 | skip = [] 33 | skip-tree = [] 34 | 35 | [sources] 36 | allow-registry = ["https://github.com/rust-lang/crates.io-index"] 37 | -------------------------------------------------------------------------------- /deps/swc/.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [env] 2 | CARGO_WORKSPACE_DIR = { value = "", relative = true } 3 | 4 | [alias] 5 | bump = "run --package swc-releaser -- bump" 6 | codegen = "run --package generate-code --" 7 | releaser = "run --package swc-releaser --" 8 | xtask = "run --package xtask --" 9 | 10 | [build] 11 | 12 | rustdocflags = ["--cfg", "docsrs"] 13 | rustflags = ["-Zshare-generics=y"] 14 | 15 | [target.x86_64-unknown-linux-gnu] 16 | rustflags = ["-C", "target-feature=+sse2", "-Zshare-generics=y", "-C", "link-args=-Wl,-z,nodelete"] 17 | 18 | [target.aarch64-unknown-linux-gnu] 19 | linker = "aarch64-linux-gnu-gcc" 20 | rustflags = ["-C", "link-args=-Wl,-z,nodelete"] 21 | 22 | [target.aarch64-unknown-linux-musl] 23 | linker = "aarch64-linux-musl-gcc" 24 | rustflags = [ 25 | "-C", 26 | "target-feature=-crt-static", 27 | "-C", 28 | "link-arg=-lgcc", 29 | "-Zshare-generics=y", 30 | ] 31 | 32 | [target.armv7-unknown-linux-gnueabihf] 33 | linker = "arm-linux-gnueabihf-gcc" 34 | rustflags = ["-C", "link-args=-Wl,-z,nodelete"] 35 | 36 | [target.x86_64-pc-windows-msvc] 37 | linker = "rust-lld" 38 | rustflags = ["-C", "target-feature=+crt-static", "-Zshare-generics=y"] 39 | 40 | 41 | [target.aarch64-pc-windows-msvc] 42 | linker = "rust-lld" 43 | -------------------------------------------------------------------------------- /deps/swc/Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | members = ["xtask", "crates/*", "tools/generate-code", "tools/swc-releaser"] 3 | resolver = "2" 4 | 5 | [workspace.package] 6 | edition = "2021" 7 | license = "Apache-2.0" 8 | repository = "https://github.com/swc-project/swc.git" 9 | 10 | 11 | [workspace.dependencies] 12 | # bytecheck version should be in sync with rkyv version. Do not bump individually. 13 | bytecheck = "0.8.0" 14 | rancor = "0.1.0" 15 | rkyv = "0.8.8" 16 | 17 | 18 | Inflector = "0.11.4" 19 | allocator-api2 = "0.2.18" 20 | ansi_term = "0.12.1" 21 | anyhow = "1.0.81" 22 | arbitrary = "1" 23 | arrayvec = "0.7.4" 24 | ascii = "1.1.0" 25 | assert_cmd = "2.0.12" 26 | assert_fs = "1.0.13" 27 | assume = "0.5.0" 28 | auto_impl = "1.2.0" 29 | backtrace = "0.3.61" 30 | base64 = "0.22.1" 31 | bitflags = "2.5.0" 32 | browserslist-rs = "0.18.1" 33 | bumpalo = "3.16.0" 34 | cargo_metadata = "0.18.1" 35 | cfg-if = "1.0.0" 36 | changesets = "0.2.2" 37 | chili = "0.2.1" 38 | chrono = "0.4.38" 39 | codspeed-criterion-compat = "2.6.0" 40 | compact_str = "0.7.1" 41 | console_error_panic_hook = "0.1.7" 42 | copyless = "0.1.5" 43 | crc = "2.1.0" 44 | criterion = "0.5.1" 45 | crossbeam-queue = "0.3.11" 46 | dashmap = "5.5.3" 47 | dialoguer = "0.10.2" 48 | difference = "2" 49 | either = "1.10.0" 50 | enumset = "1.1.2" 51 | flate2 = "1.0" 52 | futures = "0.3" 53 | glob = "0.3.0" 54 | hashbrown = "0.14.5" 55 | hex = "0.4.3" 56 | humansize = "2.1.3" 57 | indexmap = "2.0.0" 58 | is-macro = "0.3.5" 59 | js-sys = "0.3.59" 60 | jsonc-parser = "0.26.2" 61 | kstring = "2.0.0" 62 | lazy_static = "1.4.0" 63 | lexical = "6.1.0" 64 | lru = "0.10.0" 65 | memchr = "2.6.1" 66 | miette = "7.2.0" 67 | napi = { version = "2.0.0", default-features = false } 68 | napi-derive = { version = "2.0.0", default-features = false } 69 | new_debug_unreachable = "1.0.6" 70 | nom = "7.1.3" 71 | ntest = "0.7.2" 72 | num-bigint = "0.4.3" 73 | num-traits = "0.2.15" 74 | num_cpus = "1.13.1" 75 | once_cell = "1.19.0" 76 | par-core = { version = "1.0.3", default-features = false } 77 | par-iter = "1.0.2" 78 | parking_lot = "0.12.1" 79 | path-absolutize = "3.0.11" 80 | pathdiff = "0.2.1" 81 | petgraph = "0.7.1" 82 | phf = "0.11.2" 83 | pretty_assertions = "1.3" 84 | proc-macro2 = "1.0.24" 85 | ptr_meta = "0.3.0" 86 | quote = "1.0.7" 87 | radix_fmt = "1.0.0" 88 | rand = "0.8.5" 89 | rayon = "1.7.0" 90 | regex = "1.5.4" 91 | relative-path = "1.6.1" 92 | reqwest = "0.11.14" 93 | rustc-hash = "2" 94 | ryu-js = "1.0.0" 95 | scoped-tls = "1.0.1" 96 | semver = "1.0.20" 97 | serde = "1.0.197" 98 | serde-wasm-bindgen = "0.4.5" 99 | serde_derive = "1.0.197" 100 | serde_json = "1.0.115" 101 | sha1 = "0.10.6" 102 | sha2 = "0.10.8" 103 | shrink-to-fit = "0.2.1" 104 | siphasher = "0.3.9" 105 | smallvec = "1.8.0" 106 | smartstring = "1.0.1" 107 | smol_str = "0.2.0" 108 | sourcemap = "9.0.0" 109 | st-map = "0.2.0" 110 | string_cache = "0.8.7" 111 | syn = "2" 112 | tempfile = "3.6.0" 113 | termcolor = "1.0" 114 | thiserror = "1.0.30" 115 | tokio = { version = "1", default-features = false } 116 | toml = "0.8.2" 117 | tracing = "0.1.40" 118 | tracing-chrome = "0.5.0" 119 | tracing-futures = "0.2.5" 120 | tracing-subscriber = "0.3.18" 121 | triomphe = "0.1.13" 122 | typed-arena = "2.0.1" 123 | unicode-id = "0.3" 124 | unicode-id-start = "1.2.0" 125 | unicode-width = "0.1.4" 126 | url = "2.5.4" 127 | vergen = { version = "9.0.0", default-features = false } 128 | virtual-fs = { version = "0.19.0", default-features = false } 129 | walkdir = "2.4.0" 130 | wasm-bindgen = "0.2.91" 131 | wasm-bindgen-futures = "0.4.41" 132 | wasmer = { version = "=5.0.5-rc1", default-features = false } 133 | wasmer-wasix = { version = "0.35.0", default-features = false } 134 | wide = "0.7.32" 135 | 136 | [profile.release] 137 | lto = true 138 | 139 | # We use CARGO_PROFILE_RELEASE_LTO for production builds 140 | # lto = "fat" 141 | 142 | # debug = true 143 | # opt-level = 'z' 144 | 145 | [profile.bench] 146 | debug = true 147 | lto = true 148 | 149 | # Optimize for iteration 150 | [profile.dev.build-override] 151 | opt-level = 3 152 | 153 | [profile.dev.package."*"] 154 | opt-level = 3 155 | 156 | 157 | [profile.test.package.swc_ecma_minifier] 158 | opt-level = 3 159 | 160 | [profile.test.package.swc_ecma_transforms_optimization] 161 | opt-level = 3 162 | 163 | [profile.test.package.swc_ecma_usage_analyzer] 164 | opt-level = 3 165 | -------------------------------------------------------------------------------- /deps/swc/bindings/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ -------------------------------------------------------------------------------- /deps/swc/bindings/Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | members = [ 3 | "binding_core_node", 4 | "binding_core_wasm", 5 | "binding_html_node", 6 | "binding_minifier_node", 7 | "binding_minifier_wasm", 8 | "binding_typescript_wasm", 9 | "swc_cli", 10 | ] 11 | resolver = "2" 12 | 13 | [workspace.package] 14 | edition = "2021" 15 | license = "Apache-2.0" 16 | repository = "https://github.com/swc-project/swc.git" 17 | 18 | 19 | [workspace.dependencies] 20 | anyhow = "1.0.86" 21 | backtrace = "0.3" 22 | getrandom = "0.2.15" 23 | js-sys = "0.3.77" 24 | lightningcss = "1.0.0-alpha.58" 25 | miette = "7.5.0" 26 | napi = { version = "2", default-features = false } 27 | napi-build = "2" 28 | napi-derive = { version = "2", default-features = false } 29 | par-core = "1.0.0" 30 | path-clean = "1.0" 31 | quote = "1" 32 | rustc-hash = "2" 33 | serde = "1" 34 | serde-wasm-bindgen = "0.6.5" 35 | serde_json = "1.0.120" 36 | sourcemap = "8.0.1" 37 | swc_atoms = "5.0.0" 38 | swc_cached = "2.0.0" 39 | swc_cli_impl = "22.0.0" 40 | swc_common = "8.1.1" 41 | swc_compiler_base = "18.0.0" 42 | swc_config = "2.0.0" 43 | swc_core = "22.5.4" 44 | swc_css_ast = "8.0.0" 45 | swc_css_codegen = "8.0.0" 46 | swc_css_minifier = "8.0.0" 47 | swc_css_parser = "8.0.0" 48 | swc_error_reporters = "10.0.0" 49 | swc_fast_ts_strip = "15.0.0" 50 | swc_html = "16.0.0" 51 | swc_html_ast = "8.0.0" 52 | swc_html_minifier = "16.0.0" 53 | swc_malloc = "1.2.2" 54 | swc_nodejs_common = "1.0.0" 55 | tracing = "0.1.40" 56 | tracing-chrome = "0.7.2" 57 | tracing-futures = "0.2.5" 58 | tracing-subscriber = "0.3.18" 59 | wasm-bindgen = "0.2.92" 60 | wasm-bindgen-futures = "0.4.42" 61 | 62 | [profile.release] 63 | # lto = true 64 | 65 | # We use CARGO_PROFILE_RELEASE_LTO for production builds 66 | lto = "fat" 67 | 68 | # debug = true 69 | # opt-level = 'z' 70 | 71 | # Strip debug symbols 72 | strip = "symbols" 73 | 74 | [profile.release.package] 75 | 76 | [profile.release.package.wasmer-wasix] 77 | opt-level = "s" 78 | 79 | [profile.release.package.cranelift-codegen] 80 | opt-level = "s" 81 | 82 | [profile.release.package.swc_ecma_minifier] 83 | opt-level = 3 84 | 85 | [profile.release.package.swc] 86 | opt-level = 3 87 | 88 | [profile.release.package.swc_ecma_compat_es2015] 89 | opt-level = "s" 90 | 91 | [profile.release.package.swc_ecma_parser] 92 | opt-level = 3 93 | 94 | [profile.release.package.wast] 95 | opt-level = "s" 96 | 97 | [profile.release.package.wasmparser] 98 | opt-level = "s" 99 | 100 | [profile.release.package.browserslist-rs] 101 | opt-level = "s" 102 | 103 | [profile.release.package.swc_ecma_transforms_module] 104 | opt-level = "s" 105 | 106 | [profile.release.package.swc_ecma_transforms_proposal] 107 | opt-level = "s" 108 | 109 | [profile.release.package.swc_ecma_transforms_optimization] 110 | opt-level = 3 111 | 112 | [profile.release.package.swc_ecma_ast] 113 | opt-level = 3 114 | 115 | [profile.release.package.swc_ecma_transforms_base] 116 | opt-level = 3 117 | 118 | [profile.release.package.webc] 119 | opt-level = "s" 120 | 121 | [profile.release.package.swc_ecma_compat_es2022] 122 | opt-level = "s" 123 | 124 | [profile.release.package.regex-automata] 125 | opt-level = "s" 126 | 127 | [profile.release.package.swc_ecma_transforms_typescript] 128 | opt-level = 3 129 | 130 | [profile.release.package.clap] 131 | opt-level = "s" 132 | 133 | [profile.release.package.swc_cli_impl] 134 | opt-level = "s" 135 | 136 | [profile.release.package.wasmer-config] 137 | opt-level = "s" 138 | 139 | [profile.release.package.swc_ecma_utils] 140 | opt-level = 3 141 | 142 | [profile.release.package.wasmer-compiler] 143 | opt-level = "s" 144 | 145 | 146 | [profile.dev.package."*"] 147 | debug-assertions = false 148 | -------------------------------------------------------------------------------- /deps/swc/bindings/README.md: -------------------------------------------------------------------------------- 1 | ## SWC bindings 2 | 3 | This folder contains actual bindings binary SWC will build for the supported platforms (`@swc/core`, `swc_cli`, `@swc/wasm`). 4 | 5 | All the bindings binary uses publicly published `swc_core` SDK to build deterministic host binary for the specific changes, in result Cargo's workspace gets confused to select dependency versions if it belongs to the workspace contains unpublished packages. To avoid those problems, these bindings are not being built as part of the workspace. 6 | 7 | -------------------------------------------------------------------------------- /deps/swc/bindings/binding_core_node/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | authors = ["강동윤 "] 3 | build = "build.rs" 4 | edition = "2021" 5 | exclude = ["artifacts.json", "index.node"] 6 | license = "Apache-2.0" 7 | name = "binding_core_node" 8 | publish = false 9 | version = "0.1.0" 10 | 11 | [lib] 12 | bench = false 13 | crate-type = ["cdylib"] 14 | 15 | [features] 16 | default = ["swc_v1", "plugin"] 17 | plugin = [ 18 | "swc_core/plugin_transform_host_native", 19 | "swc_core/plugin_transform_host_native_filesystem_cache", 20 | ] 21 | swc_v1 = ["swc_core/bundler_node_v1"] 22 | swc_v2 = ["swc_core/bundler_node_v2"] 23 | 24 | # Internal flag for testing purpose only. 25 | __plugin_transform_vtest = [ 26 | # We know what we're doing - enable internal features for testing fixture setup. 27 | "swc_core/__plugin_transform_host", 28 | "swc_core/__plugin_transform_host_schema_vtest", 29 | "swc_core/__plugin_transform_env_native", 30 | ] 31 | 32 | [build-dependencies] 33 | napi-build = { workspace = true } 34 | 35 | [dependencies] 36 | anyhow = { workspace = true } 37 | backtrace = { workspace = true } 38 | napi = { workspace = true, features = ["napi3", "serde-json"] } 39 | napi-derive = { workspace = true, features = ["type-def"] } 40 | node_macro_deps = { path = "../node_macro_deps" } 41 | par-core = { workspace = true, features = ["chili"] } 42 | path-clean = { workspace = true } 43 | rustc-hash = { workspace = true } 44 | serde = { workspace = true, features = ["derive"] } 45 | serde_json = { workspace = true, features = ["unbounded_depth"] } 46 | tracing = { workspace = true, features = ["release_max_level_info"] } 47 | tracing-chrome = { workspace = true } 48 | tracing-futures = { workspace = true } 49 | tracing-subscriber = { workspace = true, features = ["env-filter"] } 50 | 51 | swc_core = { workspace = true, features = [ 52 | "allocator_node", 53 | "ecma_ast", 54 | "ecma_minifier", 55 | "ecma_codegen", 56 | "ecma_ast_serde", 57 | "common_concurrent", 58 | "bundler", 59 | "ecma_loader", 60 | "ecma_transforms", 61 | "ecma_visit", 62 | "base_node", 63 | "base_concurrent", 64 | ] } 65 | swc_malloc = { workspace = true } 66 | -------------------------------------------------------------------------------- /deps/swc/bindings/binding_core_node/build.rs: -------------------------------------------------------------------------------- 1 | use std::{ 2 | env, 3 | fs::File, 4 | io::{BufWriter, Write}, 5 | path::Path, 6 | }; 7 | 8 | extern crate napi_build; 9 | 10 | #[cfg(all(not(feature = "swc_v1"), not(feature = "swc_v2")))] 11 | compile_error!("Please enable swc_v1 or swc_v2 feature"); 12 | 13 | #[cfg(all(feature = "swc_v1", feature = "swc_v2"))] 14 | compile_error!("Features swc_v1 and swc_v2 are incompatible"); 15 | 16 | fn main() { 17 | let out_dir = env::var("OUT_DIR").expect("Outdir should exist"); 18 | let dest_path = Path::new(&out_dir).join("triple.txt"); 19 | let mut f = 20 | BufWriter::new(File::create(dest_path).expect("Failed to create target triple text")); 21 | write!( 22 | f, 23 | "{}", 24 | env::var("TARGET").expect("Target should be specified") 25 | ) 26 | .expect("Failed to write target triple text"); 27 | 28 | napi_build::setup(); 29 | } 30 | -------------------------------------------------------------------------------- /deps/swc/bindings/binding_core_node/src/analyze.rs: -------------------------------------------------------------------------------- 1 | use std::sync::Arc; 2 | 3 | use napi::{ 4 | bindgen_prelude::{AbortSignal, AsyncTask}, 5 | Env, JsBuffer, JsBufferValue, Ref, Task, 6 | }; 7 | use swc_core::{ 8 | base::{wasm_analysis::WasmAnalysisOptions, Compiler}, 9 | common::{comments::SingleThreadedComments, FileName}, 10 | node::MapErr, 11 | }; 12 | use tracing::instrument; 13 | 14 | use crate::{get_fresh_compiler, util::try_with}; 15 | 16 | pub struct AnalyzeTask { 17 | pub c: Arc, 18 | pub input: Option, 19 | pub options: Ref, 20 | } 21 | 22 | #[napi] 23 | impl Task for AnalyzeTask { 24 | type JsValue = String; 25 | type Output = String; 26 | 27 | #[instrument(level = "trace", skip_all)] 28 | fn compute(&mut self) -> napi::Result { 29 | let options: WasmAnalysisOptions = serde_json::from_slice(self.options.as_ref())?; 30 | 31 | try_with(self.c.cm.clone(), false, options.error_format, |handler| { 32 | let comments = SingleThreadedComments::default(); 33 | 34 | let fm = self.c.cm.new_source_file( 35 | if let Some(filename) = options.filename.as_deref() { 36 | FileName::Real(filename.into()).into() 37 | } else { 38 | FileName::Anon.into() 39 | }, 40 | self.input.take().unwrap(), 41 | ); 42 | 43 | self.c.run_wasm_analysis(fm, handler, &options, &comments) 44 | }) 45 | .convert_err() 46 | } 47 | 48 | fn resolve(&mut self, _env: Env, result: Self::Output) -> napi::Result { 49 | Ok(result) 50 | } 51 | 52 | fn finally(&mut self, env: Env) -> napi::Result<()> { 53 | self.options.unref(env)?; 54 | Ok(()) 55 | } 56 | } 57 | 58 | #[napi] 59 | pub fn analyze( 60 | src: String, 61 | options: JsBuffer, 62 | signal: Option, 63 | ) -> napi::Result> { 64 | crate::util::init_default_trace_subscriber(); 65 | 66 | let task = AnalyzeTask { 67 | c: get_fresh_compiler(), 68 | input: Some(src), 69 | options: options.into_ref()?, 70 | }; 71 | Ok(AsyncTask::with_optional_signal(task, signal)) 72 | } 73 | -------------------------------------------------------------------------------- /deps/swc/bindings/binding_core_node/src/bundle.rs: -------------------------------------------------------------------------------- 1 | use std::{ 2 | panic::{catch_unwind, AssertUnwindSafe}, 3 | sync::Arc, 4 | }; 5 | 6 | use anyhow::{bail, Error}; 7 | use napi::{ 8 | bindgen_prelude::{AbortSignal, AsyncTask, Buffer}, 9 | Env, Status, Task, 10 | }; 11 | use rustc_hash::FxHashMap; 12 | use serde::Deserialize; 13 | use swc_core::{ 14 | atoms::Atom, 15 | base::{ 16 | config::SourceMapsConfig, 17 | resolver::{environment_resolver, paths_resolver}, 18 | Compiler, PrintArgs, TransformOutput, 19 | }, 20 | bundler::{BundleKind, Bundler, Load, ModuleRecord, Resolve}, 21 | common::{Globals, Span, GLOBALS}, 22 | ecma::{ 23 | ast::{ 24 | Bool, Expr, IdentName, KeyValueProp, Lit, MemberExpr, MemberProp, MetaPropExpr, 25 | MetaPropKind, PropName, Str, 26 | }, 27 | loader::{TargetEnv, NODE_BUILTINS}, 28 | }, 29 | node::{get_deserialized, MapErr}, 30 | }; 31 | 32 | use crate::get_compiler; 33 | 34 | struct ConfigItem { 35 | loader: Box, 36 | resolver: Box, 37 | static_items: StaticConfigItem, 38 | } 39 | 40 | #[derive(Debug, Deserialize)] 41 | #[serde(rename_all = "camelCase")] 42 | struct StaticConfigItem { 43 | #[cfg(feature = "swc_v1")] 44 | #[serde(flatten)] 45 | config: swc_core::bundler::node::v1::Config, 46 | } 47 | 48 | pub(crate) struct BundleTask { 49 | swc: Arc, 50 | config: ConfigItem, 51 | } 52 | 53 | #[cfg(feature = "swc_v1")] 54 | #[napi] 55 | impl Task for BundleTask { 56 | type JsValue = FxHashMap; 57 | type Output = FxHashMap; 58 | 59 | fn compute(&mut self) -> napi::Result { 60 | let builtins = if let TargetEnv::Node = self.config.static_items.config.target { 61 | NODE_BUILTINS 62 | .iter() 63 | .copied() 64 | .map(Atom::from) 65 | .collect::>() 66 | } else { 67 | Vec::new() 68 | }; 69 | 70 | // Defaults to es3 71 | let codegen_target = self 72 | .config 73 | .static_items 74 | .config 75 | .codegen_target() 76 | .unwrap_or_default(); 77 | 78 | let globals = Globals::default(); 79 | GLOBALS.set(&globals, || { 80 | let res = catch_unwind(AssertUnwindSafe(|| { 81 | let mut bundler = Bundler::new( 82 | &globals, 83 | self.swc.cm.clone(), 84 | &self.config.loader, 85 | &self.config.resolver, 86 | swc_core::bundler::Config { 87 | require: true, 88 | external_modules: builtins 89 | .into_iter() 90 | .chain( 91 | self.config 92 | .static_items 93 | .config 94 | .external_modules 95 | .iter() 96 | .cloned(), 97 | ) 98 | .collect(), 99 | ..Default::default() 100 | }, 101 | Box::new(Hook), 102 | ); 103 | 104 | let result = bundler 105 | .bundle(self.config.static_items.config.entry.clone().into()) 106 | .convert_err()?; 107 | 108 | let result = result 109 | .into_iter() 110 | .map(|bundle| match bundle.kind { 111 | BundleKind::Named { name } | BundleKind::Lib { name } => { 112 | Ok((name, bundle.module)) 113 | } 114 | BundleKind::Dynamic => bail!("unimplemented: dynamic code splitting"), 115 | }) 116 | .map(|res| { 117 | res.and_then(|(k, m)| { 118 | // TODO: Source map 119 | let minify = self 120 | .config 121 | .static_items 122 | .config 123 | .options 124 | .as_ref() 125 | .map(|v| v.config.minify.into_bool()) 126 | .unwrap_or(false); 127 | 128 | let output = self.swc.print( 129 | &m, 130 | PrintArgs { 131 | inline_sources_content: true, 132 | source_map: SourceMapsConfig::Bool(true), 133 | emit_source_map_columns: true, 134 | codegen_config: swc_core::ecma::codegen::Config::default() 135 | .with_target(codegen_target) 136 | .with_minify(minify), 137 | ..Default::default() 138 | }, 139 | )?; 140 | 141 | Ok((k, output)) 142 | }) 143 | }) 144 | .collect::>() 145 | .convert_err()?; 146 | 147 | Ok(result) 148 | })); 149 | 150 | let err = match res { 151 | Ok(v) => return v, 152 | Err(err) => err, 153 | }; 154 | 155 | if let Some(s) = err.downcast_ref::() { 156 | return Err(napi::Error::new( 157 | Status::GenericFailure, 158 | format!("panic detected: {}", s), 159 | )); 160 | } 161 | 162 | Err(napi::Error::new( 163 | Status::GenericFailure, 164 | "panic detected".to_string(), 165 | )) 166 | }) 167 | } 168 | 169 | fn resolve(&mut self, _env: Env, output: Self::Output) -> napi::Result { 170 | Ok(output) 171 | } 172 | } 173 | 174 | #[cfg(feature = "swc_v2")] 175 | impl Task for BundleTask { 176 | type JsValue = FxHashMap; 177 | type Output = FxHashMap; 178 | 179 | fn compute(&mut self) -> napi::Result { 180 | todo!() 181 | } 182 | 183 | fn resolve(&mut self, env: Env, output: Self::Output) -> napi::Result { 184 | todo!() 185 | } 186 | } 187 | 188 | #[cfg(feature = "swc_v1")] 189 | #[napi(ts_return_type = "Promise<{ [index: string]: { code: string, map?: string } }>")] 190 | pub(crate) fn bundle( 191 | conf_items: Buffer, 192 | signal: Option, 193 | ) -> napi::Result> { 194 | crate::util::init_default_trace_subscriber(); 195 | 196 | let c: Arc = get_compiler(); 197 | 198 | let static_items: StaticConfigItem = get_deserialized(&conf_items)?; 199 | 200 | let loader = Box::new(swc_core::bundler::node::loaders::swc::SwcLoader::new( 201 | c.clone(), 202 | static_items 203 | .config 204 | .options 205 | .as_ref() 206 | .cloned() 207 | .unwrap_or_else(|| { 208 | serde_json::from_value(serde_json::Value::Object(Default::default())).unwrap() 209 | }), 210 | )); 211 | 212 | let target_env = static_items.config.target; 213 | 214 | let paths = static_items.config.options.as_ref().map(|options| { 215 | let paths: Vec<(String, Vec)> = options 216 | .config 217 | .jsc 218 | .paths 219 | .iter() 220 | .map(|(k, v)| (k.clone(), v.clone())) 221 | .collect(); 222 | (options.config.jsc.base_url.clone(), paths) 223 | }); 224 | 225 | let alias = static_items 226 | .config 227 | .alias 228 | .get(&target_env) 229 | .cloned() 230 | .unwrap_or_default(); 231 | 232 | let resolver: Box = if let Some((base_url, paths)) = paths { 233 | Box::new(paths_resolver( 234 | target_env, 235 | alias, 236 | base_url, 237 | paths, 238 | static_items.config.preserve_symlinks, 239 | )) 240 | } else { 241 | Box::new(environment_resolver( 242 | target_env, 243 | alias, 244 | static_items.config.preserve_symlinks, 245 | )) 246 | }; 247 | 248 | Ok(AsyncTask::with_optional_signal( 249 | BundleTask { 250 | swc: c, 251 | config: ConfigItem { 252 | loader, 253 | resolver, 254 | static_items, 255 | }, 256 | }, 257 | signal, 258 | )) 259 | } 260 | 261 | #[cfg(feature = "swc_v2")] 262 | #[napi] 263 | pub(crate) fn bundle() -> napi::Result> { 264 | todo!() 265 | } 266 | 267 | struct Hook; 268 | 269 | impl swc_core::bundler::Hook for Hook { 270 | fn get_import_meta_props( 271 | &self, 272 | span: Span, 273 | module_record: &ModuleRecord, 274 | ) -> Result, Error> { 275 | let file_name = module_record.file_name.to_string(); 276 | 277 | Ok(vec![ 278 | KeyValueProp { 279 | key: PropName::Ident(IdentName::new("url".into(), span)), 280 | value: Box::new(Expr::Lit(Lit::Str(Str { 281 | span, 282 | raw: None, 283 | value: file_name.into(), 284 | }))), 285 | }, 286 | KeyValueProp { 287 | key: PropName::Ident(IdentName::new("main".into(), span)), 288 | value: Box::new(if module_record.is_entry { 289 | Expr::Member(MemberExpr { 290 | span, 291 | obj: Box::new(Expr::MetaProp(MetaPropExpr { 292 | span, 293 | kind: MetaPropKind::ImportMeta, 294 | })), 295 | prop: MemberProp::Ident(IdentName::new("main".into(), span)), 296 | }) 297 | } else { 298 | Expr::Lit(Lit::Bool(Bool { span, value: false })) 299 | }), 300 | }, 301 | ]) 302 | } 303 | } 304 | -------------------------------------------------------------------------------- /deps/swc/bindings/binding_core_node/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![recursion_limit = "2048"] 2 | #![allow(dead_code)] 3 | 4 | #[macro_use] 5 | extern crate napi_derive; 6 | 7 | extern crate swc_malloc; 8 | 9 | use std::{env, panic::set_hook, sync::Arc}; 10 | 11 | use backtrace::Backtrace; 12 | use swc_core::{ 13 | base::Compiler, 14 | common::{sync::Lazy, FilePathMapping, SourceMap}, 15 | }; 16 | 17 | #[cfg(feature = "plugin")] 18 | mod analyze; 19 | mod bundle; 20 | mod minify; 21 | mod parse; 22 | mod print; 23 | mod transform; 24 | mod util; 25 | 26 | static COMPILER: Lazy> = Lazy::new(|| { 27 | let cm = Arc::new(SourceMap::new(FilePathMapping::empty())); 28 | 29 | Arc::new(Compiler::new(cm)) 30 | }); 31 | 32 | #[napi::module_init] 33 | fn init() { 34 | if cfg!(debug_assertions) || env::var("SWC_DEBUG").unwrap_or_default() == "1" { 35 | set_hook(Box::new(|panic_info| { 36 | let backtrace = Backtrace::new(); 37 | println!("Panic: {:?}\nBacktrace: {:?}", panic_info, backtrace); 38 | })); 39 | } 40 | } 41 | 42 | fn get_compiler() -> Arc { 43 | COMPILER.clone() 44 | } 45 | 46 | fn get_fresh_compiler() -> Arc { 47 | let cm = Arc::new(SourceMap::new(FilePathMapping::empty())); 48 | 49 | Arc::new(Compiler::new(cm)) 50 | } 51 | 52 | #[napi(js_name = "Compiler")] 53 | pub struct JsCompiler { 54 | _compiler: Arc, 55 | } 56 | 57 | #[napi] 58 | impl JsCompiler { 59 | #[napi(constructor)] 60 | #[allow(clippy::new_without_default)] 61 | #[tracing::instrument(level = "info", skip_all)] 62 | pub fn new() -> Self { 63 | Self { 64 | _compiler: COMPILER.clone(), 65 | } 66 | } 67 | } 68 | 69 | pub type ArcCompiler = Arc; 70 | 71 | /// Hack for `Type Generation` 72 | #[napi(object)] 73 | pub struct TransformOutput { 74 | pub code: String, 75 | pub map: Option, 76 | } 77 | -------------------------------------------------------------------------------- /deps/swc/bindings/binding_core_node/src/minify.rs: -------------------------------------------------------------------------------- 1 | use std::sync::Arc; 2 | 3 | use napi::{ 4 | bindgen_prelude::{AbortSignal, AsyncTask, Buffer, External}, 5 | Env, JsExternal, JsObject, JsUnknown, Task, 6 | }; 7 | use rustc_hash::FxHashMap; 8 | use serde::Deserialize; 9 | use swc_core::{ 10 | base::{ 11 | config::{ErrorFormat, JsMinifyOptions}, 12 | JsMinifyExtras, TransformOutput, 13 | }, 14 | common::{sync::Lrc, FileName, SourceFile, SourceMap}, 15 | ecma::minifier::option::{MangleCache, SimpleMangleCache}, 16 | node::{deserialize_json, get_deserialized, MapErr}, 17 | }; 18 | 19 | use crate::{get_fresh_compiler, util::try_with}; 20 | 21 | #[napi(object)] 22 | pub struct NapiMinifyExtra { 23 | #[napi(ts_type = "object")] 24 | pub mangle_name_cache: Option, 25 | } 26 | 27 | struct MinifyTask { 28 | c: Arc, 29 | code: String, 30 | options: String, 31 | extras: JsMinifyExtras, 32 | } 33 | 34 | #[derive(Deserialize)] 35 | #[serde(untagged)] 36 | enum MinifyTarget { 37 | /// Code to minify. 38 | Single(String), 39 | /// `{ filename: code }` 40 | Map(FxHashMap), 41 | } 42 | 43 | impl MinifyTarget { 44 | fn to_file(&self, cm: Lrc) -> Lrc { 45 | match self { 46 | MinifyTarget::Single(code) => cm.new_source_file(FileName::Anon.into(), code.clone()), 47 | MinifyTarget::Map(codes) => { 48 | assert_eq!( 49 | codes.len(), 50 | 1, 51 | "swc.minify does not support concatting multiple files yet" 52 | ); 53 | 54 | let (filename, code) = codes.iter().next().unwrap(); 55 | 56 | cm.new_source_file(FileName::Real(filename.clone().into()).into(), code.clone()) 57 | } 58 | } 59 | } 60 | } 61 | 62 | #[napi] 63 | impl Task for MinifyTask { 64 | type JsValue = TransformOutput; 65 | type Output = TransformOutput; 66 | 67 | fn compute(&mut self) -> napi::Result { 68 | let input: MinifyTarget = deserialize_json(&self.code)?; 69 | let options: JsMinifyOptions = deserialize_json(&self.options)?; 70 | 71 | try_with(self.c.cm.clone(), false, ErrorFormat::Normal, |handler| { 72 | let fm = input.to_file(self.c.cm.clone()); 73 | 74 | self.c.minify(fm, handler, &options, self.extras.clone()) 75 | }) 76 | .convert_err() 77 | } 78 | 79 | fn resolve(&mut self, _env: napi::Env, output: Self::Output) -> napi::Result { 80 | Ok(output) 81 | } 82 | } 83 | 84 | type NameMangleCache = External>; 85 | 86 | #[napi(ts_return_type = "object")] 87 | fn new_mangle_name_cache() -> NameMangleCache { 88 | let cache = Arc::new(SimpleMangleCache::default()); 89 | External::new(cache) 90 | } 91 | 92 | #[napi] 93 | fn minify( 94 | code: Buffer, 95 | opts: Buffer, 96 | extras: NapiMinifyExtra, 97 | signal: Option, 98 | ) -> AsyncTask { 99 | crate::util::init_default_trace_subscriber(); 100 | let code = String::from_utf8_lossy(code.as_ref()).to_string(); 101 | let options = String::from_utf8_lossy(opts.as_ref()).to_string(); 102 | let extras = JsMinifyExtras::default() 103 | .with_mangle_name_cache(extras.mangle_name_cache.as_deref().cloned()); 104 | 105 | let c = get_fresh_compiler(); 106 | 107 | let task = MinifyTask { 108 | c, 109 | code, 110 | options, 111 | extras, 112 | }; 113 | 114 | AsyncTask::with_optional_signal(task, signal) 115 | } 116 | 117 | #[napi] 118 | pub fn minify_sync( 119 | code: Buffer, 120 | opts: Buffer, 121 | extras: NapiMinifyExtra, 122 | ) -> napi::Result { 123 | crate::util::init_default_trace_subscriber(); 124 | let code: MinifyTarget = get_deserialized(code)?; 125 | let opts = get_deserialized(opts)?; 126 | let extras = JsMinifyExtras::default() 127 | .with_mangle_name_cache(extras.mangle_name_cache.as_deref().cloned()); 128 | 129 | let c = get_fresh_compiler(); 130 | 131 | let fm = code.to_file(c.cm.clone()); 132 | 133 | try_with( 134 | c.cm.clone(), 135 | false, 136 | // TODO(kdy1): Maybe make this configurable? 137 | ErrorFormat::Normal, 138 | |handler| c.minify(fm, handler, &opts, extras), 139 | ) 140 | .convert_err() 141 | } 142 | -------------------------------------------------------------------------------- /deps/swc/bindings/binding_core_node/src/parse.rs: -------------------------------------------------------------------------------- 1 | use std::{ 2 | path::{Path, PathBuf}, 3 | sync::Arc, 4 | }; 5 | 6 | use anyhow::Context as _; 7 | use napi::{ 8 | bindgen_prelude::{AbortSignal, AsyncTask, Buffer}, 9 | Either, Env, Task, 10 | }; 11 | use swc_core::{ 12 | base::{ 13 | config::{ErrorFormat, ParseOptions}, 14 | Compiler, 15 | }, 16 | common::{comments::Comments, FileName, Mark}, 17 | ecma::{transforms::base::resolver, visit::VisitMutWith}, 18 | node::{deserialize_json, get_deserialized, MapErr}, 19 | }; 20 | 21 | use crate::{get_compiler, util::try_with}; 22 | 23 | // ----- Parsing ----- 24 | 25 | pub struct ParseTask { 26 | pub c: Arc, 27 | pub filename: FileName, 28 | pub src: String, 29 | pub options: String, 30 | } 31 | 32 | pub struct ParseFileTask { 33 | pub c: Arc, 34 | pub path: PathBuf, 35 | pub options: String, 36 | } 37 | 38 | #[napi] 39 | impl Task for ParseTask { 40 | type JsValue = String; 41 | type Output = String; 42 | 43 | fn compute(&mut self) -> napi::Result { 44 | let options: ParseOptions = deserialize_json(&self.options)?; 45 | let fm = self 46 | .c 47 | .cm 48 | .new_source_file(self.filename.clone().into(), self.src.clone()); 49 | 50 | let comments = if options.comments { 51 | Some(self.c.comments() as &dyn Comments) 52 | } else { 53 | None 54 | }; 55 | 56 | let program = try_with(self.c.cm.clone(), false, ErrorFormat::Normal, |handler| { 57 | let mut p = self.c.parse_js( 58 | fm, 59 | handler, 60 | options.target, 61 | options.syntax, 62 | options.is_module, 63 | comments, 64 | )?; 65 | 66 | p.visit_mut_with(&mut resolver( 67 | Mark::new(), 68 | Mark::new(), 69 | options.syntax.typescript(), 70 | )); 71 | 72 | Ok(p) 73 | }) 74 | .convert_err()?; 75 | 76 | let ast_json = serde_json::to_string(&program)?; 77 | 78 | Ok(ast_json) 79 | } 80 | 81 | fn resolve(&mut self, _env: Env, result: Self::Output) -> napi::Result { 82 | Ok(result) 83 | } 84 | } 85 | 86 | #[napi] 87 | impl Task for ParseFileTask { 88 | type JsValue = String; 89 | type Output = String; 90 | 91 | fn compute(&mut self) -> napi::Result { 92 | let program = try_with(self.c.cm.clone(), false, ErrorFormat::Normal, |handler| { 93 | self.c.run(|| { 94 | let options: ParseOptions = deserialize_json(&self.options)?; 95 | 96 | let fm = self 97 | .c 98 | .cm 99 | .load_file(&self.path) 100 | .context("failed to read module")?; 101 | 102 | let c = self.c.comments().clone(); 103 | let comments = if options.comments { 104 | Some(&c as &dyn Comments) 105 | } else { 106 | None 107 | }; 108 | 109 | let mut p = self.c.parse_js( 110 | fm, 111 | handler, 112 | options.target, 113 | options.syntax, 114 | options.is_module, 115 | comments, 116 | )?; 117 | 118 | p.visit_mut_with(&mut resolver( 119 | Mark::new(), 120 | Mark::new(), 121 | options.syntax.typescript(), 122 | )); 123 | 124 | Ok(p) 125 | }) 126 | }) 127 | .convert_err()?; 128 | 129 | let ast_json = serde_json::to_string(&program)?; 130 | 131 | Ok(ast_json) 132 | } 133 | 134 | fn resolve(&mut self, _env: Env, result: Self::Output) -> napi::Result { 135 | Ok(result) 136 | } 137 | } 138 | 139 | fn stringify(src: Either) -> String { 140 | match src { 141 | Either::A(src) => String::from_utf8_lossy(src.as_ref()).into_owned(), 142 | Either::B(src) => src, 143 | } 144 | } 145 | 146 | #[napi] 147 | pub fn parse( 148 | src: Either, 149 | options: Buffer, 150 | filename: Option, 151 | signal: Option, 152 | ) -> AsyncTask { 153 | crate::util::init_default_trace_subscriber(); 154 | 155 | let c = get_compiler(); 156 | let src = stringify(src); 157 | let options = String::from_utf8_lossy(options.as_ref()).to_string(); 158 | let filename = if let Some(value) = filename { 159 | FileName::Real(value.into()) 160 | } else { 161 | FileName::Anon 162 | }; 163 | 164 | AsyncTask::with_optional_signal( 165 | ParseTask { 166 | c, 167 | filename, 168 | src, 169 | options, 170 | }, 171 | signal, 172 | ) 173 | } 174 | 175 | #[napi] 176 | pub fn parse_sync( 177 | src: Either, 178 | opts: Buffer, 179 | filename: Option, 180 | ) -> napi::Result { 181 | crate::util::init_default_trace_subscriber(); 182 | 183 | let c = get_compiler(); 184 | let src = stringify(src); 185 | let options: ParseOptions = get_deserialized(&opts)?; 186 | let filename = if let Some(value) = filename { 187 | FileName::Real(value.into()) 188 | } else { 189 | FileName::Anon 190 | }; 191 | 192 | let program = try_with(c.cm.clone(), false, ErrorFormat::Normal, |handler| { 193 | c.run(|| { 194 | let fm = c.cm.new_source_file(filename.into(), src); 195 | 196 | let comments = if options.comments { 197 | Some(c.comments() as &dyn Comments) 198 | } else { 199 | None 200 | }; 201 | 202 | let mut p = c.parse_js( 203 | fm, 204 | handler, 205 | options.target, 206 | options.syntax, 207 | options.is_module, 208 | comments, 209 | )?; 210 | 211 | p.visit_mut_with(&mut resolver( 212 | Mark::new(), 213 | Mark::new(), 214 | options.syntax.typescript(), 215 | )); 216 | 217 | Ok(p) 218 | }) 219 | }) 220 | .convert_err()?; 221 | 222 | Ok(serde_json::to_string(&program)?) 223 | } 224 | 225 | #[napi] 226 | pub fn parse_file_sync(path: String, opts: Buffer) -> napi::Result { 227 | crate::util::init_default_trace_subscriber(); 228 | let c = get_compiler(); 229 | let options: ParseOptions = get_deserialized(&opts)?; 230 | 231 | let program = { 232 | try_with(c.cm.clone(), false, ErrorFormat::Normal, |handler| { 233 | let fm = 234 | c.cm.load_file(Path::new(path.as_str())) 235 | .expect("failed to read program file"); 236 | 237 | let comments = if options.comments { 238 | Some(c.comments() as &dyn Comments) 239 | } else { 240 | None 241 | }; 242 | 243 | let mut p = c.parse_js( 244 | fm, 245 | handler, 246 | options.target, 247 | options.syntax, 248 | options.is_module, 249 | comments, 250 | )?; 251 | p.visit_mut_with(&mut resolver( 252 | Mark::new(), 253 | Mark::new(), 254 | options.syntax.typescript(), 255 | )); 256 | 257 | Ok(p) 258 | }) 259 | } 260 | .convert_err()?; 261 | 262 | Ok(serde_json::to_string(&program)?) 263 | } 264 | 265 | #[napi] 266 | pub fn parse_file( 267 | path: String, 268 | options: Buffer, 269 | signal: Option, 270 | ) -> AsyncTask { 271 | crate::util::init_default_trace_subscriber(); 272 | 273 | let c = get_compiler(); 274 | let path = PathBuf::from(&path); 275 | let options = String::from_utf8_lossy(options.as_ref()).to_string(); 276 | 277 | AsyncTask::with_optional_signal(ParseFileTask { c, path, options }, signal) 278 | } 279 | -------------------------------------------------------------------------------- /deps/swc/bindings/binding_core_node/src/print.rs: -------------------------------------------------------------------------------- 1 | use std::sync::Arc; 2 | 3 | use napi::{ 4 | bindgen_prelude::{AbortSignal, AsyncTask, Buffer}, 5 | Env, Task, 6 | }; 7 | use swc_core::{ 8 | base::{ 9 | config::{Options, SourceMapsConfig}, 10 | Compiler, PrintArgs, TransformOutput, 11 | }, 12 | common::GLOBALS, 13 | ecma::ast::{EsVersion, Program}, 14 | node::{deserialize_json, get_deserialized, MapErr}, 15 | }; 16 | 17 | use crate::get_compiler; 18 | 19 | // ----- Printing ----- 20 | 21 | pub struct PrintTask { 22 | pub c: Arc, 23 | pub program_json: String, 24 | pub options: String, 25 | } 26 | 27 | #[napi] 28 | impl Task for PrintTask { 29 | type JsValue = TransformOutput; 30 | type Output = TransformOutput; 31 | 32 | fn compute(&mut self) -> napi::Result { 33 | let program: Program = deserialize_json(&self.program_json)?; 34 | let options: Options = deserialize_json(&self.options)?; 35 | 36 | GLOBALS.set(&Default::default(), || { 37 | self.c 38 | .print( 39 | &program, 40 | PrintArgs { 41 | output_path: options.output_path.clone(), 42 | inline_sources_content: true, 43 | source_map: options 44 | .source_maps 45 | .clone() 46 | .unwrap_or(SourceMapsConfig::Bool(false)), 47 | emit_source_map_columns: options.config.emit_source_map_columns.into_bool(), 48 | codegen_config: swc_core::ecma::codegen::Config::default() 49 | .with_target(options.config.jsc.target.unwrap_or(EsVersion::Es2020)) 50 | .with_minify(options.config.minify.into_bool()), 51 | ..Default::default() 52 | }, 53 | ) 54 | .convert_err() 55 | }) 56 | } 57 | 58 | fn resolve(&mut self, _env: Env, result: Self::Output) -> napi::Result { 59 | Ok(result) 60 | } 61 | } 62 | 63 | #[napi] 64 | pub fn print( 65 | program_json: String, 66 | options: Buffer, 67 | signal: Option, 68 | ) -> napi::Result> { 69 | crate::util::init_default_trace_subscriber(); 70 | 71 | let c = get_compiler(); 72 | let options = String::from_utf8_lossy(&options).to_string(); 73 | 74 | Ok(AsyncTask::with_optional_signal( 75 | PrintTask { 76 | c, 77 | program_json, 78 | options, 79 | }, 80 | signal, 81 | )) 82 | } 83 | 84 | #[napi] 85 | pub fn print_sync(program: String, options: Buffer) -> napi::Result { 86 | crate::util::init_default_trace_subscriber(); 87 | 88 | let c = get_compiler(); 89 | 90 | let program: Program = deserialize_json(program.as_str())?; 91 | 92 | let options: Options = get_deserialized(&options)?; 93 | 94 | // Defaults to es3 95 | let codegen_target = options.codegen_target().unwrap_or_default(); 96 | 97 | GLOBALS.set(&Default::default(), || { 98 | c.print( 99 | &program, 100 | PrintArgs { 101 | output_path: options.output_path, 102 | inline_sources_content: true, 103 | source_map: options 104 | .source_maps 105 | .clone() 106 | .unwrap_or(SourceMapsConfig::Bool(false)), 107 | emit_source_map_columns: options.config.emit_source_map_columns.into_bool(), 108 | codegen_config: swc_core::ecma::codegen::Config::default() 109 | .with_target(codegen_target) 110 | .with_minify(options.config.minify.into_bool()), 111 | ..Default::default() 112 | }, 113 | ) 114 | .convert_err() 115 | }) 116 | } 117 | -------------------------------------------------------------------------------- /deps/swc/bindings/binding_core_node/src/transform.rs: -------------------------------------------------------------------------------- 1 | use std::{ 2 | path::{Path, PathBuf}, 3 | sync::Arc, 4 | }; 5 | 6 | use anyhow::Context as _; 7 | use napi::{ 8 | bindgen_prelude::{AbortSignal, AsyncTask, Buffer}, 9 | Env, JsBuffer, JsBufferValue, Ref, Task, 10 | }; 11 | use path_clean::clean; 12 | use swc_core::{ 13 | base::{config::Options, Compiler, TransformOutput}, 14 | common::FileName, 15 | ecma::ast::Program, 16 | node::{deserialize_json, get_deserialized, MapErr}, 17 | }; 18 | use tracing::instrument; 19 | 20 | use crate::{get_compiler, get_fresh_compiler, util::try_with}; 21 | 22 | /// Input to transform 23 | #[derive(Debug)] 24 | pub enum Input { 25 | /// json string 26 | Program(String), 27 | /// Raw source code. 28 | Source { src: String }, 29 | /// File 30 | File(PathBuf), 31 | } 32 | 33 | pub struct TransformTask { 34 | pub c: Arc, 35 | pub input: Input, 36 | pub options: Ref, 37 | } 38 | 39 | #[napi] 40 | impl Task for TransformTask { 41 | type JsValue = TransformOutput; 42 | type Output = TransformOutput; 43 | 44 | #[instrument(level = "trace", skip_all)] 45 | fn compute(&mut self) -> napi::Result { 46 | let mut options: Options = serde_json::from_slice(self.options.as_ref())?; 47 | if !options.filename.is_empty() { 48 | options.config.adjust(Path::new(&options.filename)); 49 | } 50 | 51 | let error_format = options.experimental.error_format.unwrap_or_default(); 52 | 53 | try_with( 54 | self.c.cm.clone(), 55 | !options.config.error.filename.into_bool(), 56 | error_format, 57 | |handler| { 58 | self.c.run(|| match &self.input { 59 | Input::Program(ref s) => { 60 | let program: Program = 61 | deserialize_json(s).expect("failed to deserialize Program"); 62 | // TODO: Source map 63 | self.c.process_js(handler, program, &options) 64 | } 65 | 66 | Input::File(ref path) => { 67 | let fm = self.c.cm.load_file(path).context("failed to load file")?; 68 | self.c.process_js_file(fm, handler, &options) 69 | } 70 | 71 | Input::Source { src } => { 72 | let fm = self.c.cm.new_source_file( 73 | if options.filename.is_empty() { 74 | FileName::Anon.into() 75 | } else { 76 | FileName::Real(options.filename.clone().into()).into() 77 | }, 78 | src.to_string(), 79 | ); 80 | 81 | self.c.process_js_file(fm, handler, &options) 82 | } 83 | }) 84 | }, 85 | ) 86 | .convert_err() 87 | } 88 | 89 | fn resolve(&mut self, _env: Env, result: Self::Output) -> napi::Result { 90 | Ok(result) 91 | } 92 | 93 | fn finally(&mut self, env: Env) -> napi::Result<()> { 94 | self.options.unref(env)?; 95 | Ok(()) 96 | } 97 | } 98 | 99 | #[napi] 100 | #[instrument(level = "trace", skip_all)] 101 | pub fn transform( 102 | src: String, 103 | is_module: bool, 104 | options: JsBuffer, 105 | signal: Option, 106 | ) -> napi::Result> { 107 | crate::util::init_default_trace_subscriber(); 108 | 109 | let (input, c) = if is_module { 110 | (Input::Program(src), get_compiler()) 111 | } else { 112 | (Input::Source { src }, get_fresh_compiler()) 113 | }; 114 | 115 | let task = TransformTask { 116 | c, 117 | input, 118 | options: options.into_ref()?, 119 | }; 120 | Ok(AsyncTask::with_optional_signal(task, signal)) 121 | } 122 | 123 | #[napi] 124 | #[instrument(level = "trace", skip_all)] 125 | pub fn transform_sync(s: String, is_module: bool, opts: Buffer) -> napi::Result { 126 | crate::util::init_default_trace_subscriber(); 127 | 128 | let c = if is_module { 129 | get_compiler() 130 | } else { 131 | get_fresh_compiler() 132 | }; 133 | 134 | let mut options: Options = get_deserialized(&opts)?; 135 | 136 | if !options.filename.is_empty() { 137 | options.config.adjust(Path::new(&options.filename)); 138 | } 139 | 140 | let error_format = options.experimental.error_format.unwrap_or_default(); 141 | 142 | try_with( 143 | c.cm.clone(), 144 | !options.config.error.filename.into_bool(), 145 | error_format, 146 | |handler| { 147 | c.run(|| { 148 | if is_module { 149 | let program: Program = 150 | deserialize_json(s.as_str()).context("failed to deserialize Program")?; 151 | c.process_js(handler, program, &options) 152 | } else { 153 | let fm = c.cm.new_source_file( 154 | if options.filename.is_empty() { 155 | FileName::Anon.into() 156 | } else { 157 | FileName::Real(options.filename.clone().into()).into() 158 | }, 159 | s, 160 | ); 161 | c.process_js_file(fm, handler, &options) 162 | } 163 | }) 164 | }, 165 | ) 166 | .convert_err() 167 | } 168 | 169 | #[napi] 170 | #[instrument(level = "trace", skip_all)] 171 | pub fn transform_file( 172 | src: String, 173 | _is_module: bool, 174 | options: JsBuffer, 175 | signal: Option, 176 | ) -> napi::Result> { 177 | crate::util::init_default_trace_subscriber(); 178 | 179 | let c = get_fresh_compiler(); 180 | 181 | let path = clean(&src); 182 | let task = TransformTask { 183 | c, 184 | input: Input::File(path), 185 | options: options.into_ref()?, 186 | }; 187 | Ok(AsyncTask::with_optional_signal(task, signal)) 188 | } 189 | 190 | #[napi] 191 | pub fn transform_file_sync( 192 | s: String, 193 | is_module: bool, 194 | opts: Buffer, 195 | ) -> napi::Result { 196 | crate::util::init_default_trace_subscriber(); 197 | 198 | let c = get_fresh_compiler(); 199 | 200 | let mut options: Options = get_deserialized(&opts)?; 201 | 202 | if !options.filename.is_empty() { 203 | options.config.adjust(Path::new(&options.filename)); 204 | } 205 | 206 | let error_format = options.experimental.error_format.unwrap_or_default(); 207 | 208 | try_with( 209 | c.cm.clone(), 210 | !options.config.error.filename.into_bool(), 211 | error_format, 212 | |handler| { 213 | c.run(|| { 214 | if is_module { 215 | let program: Program = 216 | deserialize_json(s.as_str()).context("failed to deserialize Program")?; 217 | c.process_js(handler, program, &options) 218 | } else { 219 | let fm = c.cm.load_file(Path::new(&s)).expect("failed to load file"); 220 | c.process_js_file(fm, handler, &options) 221 | } 222 | }) 223 | }, 224 | ) 225 | .convert_err() 226 | } 227 | -------------------------------------------------------------------------------- /deps/swc/bindings/binding_core_node/src/util.rs: -------------------------------------------------------------------------------- 1 | #![deny(warnings)] 2 | 3 | use std::panic::{catch_unwind, AssertUnwindSafe}; 4 | 5 | use anyhow::{anyhow, Error}; 6 | use napi::Env; 7 | use swc_core::{ 8 | base::{config::ErrorFormat, try_with_handler}, 9 | common::{ 10 | errors::Handler, 11 | sync::{Lrc, OnceCell}, 12 | SourceMap, GLOBALS, 13 | }, 14 | }; 15 | use tracing::instrument; 16 | use tracing_chrome::ChromeLayerBuilder; 17 | use tracing_subscriber::{ 18 | filter, prelude::__tracing_subscriber_SubscriberExt, util::SubscriberInitExt, EnvFilter, Layer, 19 | }; 20 | 21 | static TARGET_TRIPLE: &str = include_str!(concat!(env!("OUT_DIR"), "/triple.txt")); 22 | static CUSTOM_TRACE_SUBSCRIBER: OnceCell = OnceCell::new(); 23 | 24 | #[napi] 25 | pub fn get_target_triple() -> napi::Result { 26 | Ok(TARGET_TRIPLE.to_string()) 27 | } 28 | 29 | #[napi] 30 | pub fn init_custom_trace_subscriber( 31 | mut env: Env, 32 | trace_out_file_path: Option, 33 | ) -> napi::Result<()> { 34 | CUSTOM_TRACE_SUBSCRIBER.get_or_init(|| { 35 | let mut layer = ChromeLayerBuilder::new().include_args(true); 36 | if let Some(trace_out_file) = trace_out_file_path { 37 | layer = layer.file(trace_out_file); 38 | } 39 | 40 | let (chrome_layer, guard) = layer.build(); 41 | tracing_subscriber::registry() 42 | .with(chrome_layer.with_filter(filter::filter_fn(|metadata| { 43 | !metadata.target().contains("cranelift") && !metadata.name().contains("log ") 44 | }))) 45 | .try_init() 46 | .expect("Failed to register tracing subscriber"); 47 | 48 | env.add_env_cleanup_hook(guard, |flush_guard| { 49 | flush_guard.flush(); 50 | drop(flush_guard); 51 | }) 52 | .expect("Should able to initialize cleanup for custom trace subscriber"); 53 | 54 | true 55 | }); 56 | 57 | Ok(()) 58 | } 59 | 60 | #[instrument(level = "trace", skip_all)] 61 | pub fn try_with( 62 | cm: Lrc, 63 | skip_filename: bool, 64 | _error_format: ErrorFormat, 65 | op: F, 66 | ) -> Result 67 | where 68 | F: FnOnce(&Handler) -> Result, 69 | { 70 | GLOBALS 71 | .set(&Default::default(), || { 72 | try_with_handler( 73 | cm, 74 | swc_core::base::HandlerOpts { 75 | skip_filename, 76 | ..Default::default() 77 | }, 78 | |handler| { 79 | // 80 | let result = catch_unwind(AssertUnwindSafe(|| op(handler))); 81 | 82 | let p = match result { 83 | Ok(v) => return v, 84 | Err(v) => v, 85 | }; 86 | 87 | if let Some(s) = p.downcast_ref::() { 88 | Err(anyhow!("failed to handle: {}", s)) 89 | } else if let Some(s) = p.downcast_ref::<&str>() { 90 | Err(anyhow!("failed to handle: {}", s)) 91 | } else { 92 | Err(anyhow!("failed to handle with unknown panic message")) 93 | } 94 | }, 95 | ) 96 | }) 97 | .map_err(|e| e.to_pretty_error()) 98 | } 99 | 100 | // This was originally under swc_nodejs_common, but this is not a public 101 | // interface for the custom binary - they should choose own trace initialization 102 | // instead. Will keep as hidden for now until there's proper usecase. 103 | 104 | /// Trying to initialize default subscriber if global dispatch is not set. 105 | /// This can be called multiple time, however subsequent calls will be ignored 106 | /// as tracing_subscriber only allows single global dispatch. 107 | pub fn init_default_trace_subscriber() { 108 | let _unused = tracing_subscriber::FmtSubscriber::builder() 109 | .without_time() 110 | .with_target(false) 111 | .with_writer(std::io::stderr) 112 | .with_ansi(true) 113 | .with_env_filter(EnvFilter::from_env("SWC_LOG")) 114 | .pretty() 115 | .try_init(); 116 | } 117 | -------------------------------------------------------------------------------- /deps/swc/bindings/binding_core_wasm/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | authors = ["강동윤 "] 3 | description = "wasm module for swc" 4 | edition = { workspace = true } 5 | license = { workspace = true } 6 | name = "binding_core_wasm" 7 | publish = false 8 | repository = { workspace = true } 9 | version = "1.11.24" 10 | 11 | [lib] 12 | bench = false 13 | crate-type = ["cdylib"] 14 | 15 | [features] 16 | default = ["swc_v1"] 17 | swc_v1 = [] 18 | swc_v2 = [] 19 | # This feature exists to allow cargo operations 20 | # [TODO]: this is disabled due to signature mismatch between host_native and host_js, 21 | # which causes build errors like 22 | # .call(&mut self.store, ptr.0, ptr.1) 23 | # | ^^^^ the trait `NativeWasmTypeInto` is not implemented for `u32` 24 | # | 25 | # = help: the following other types implement trait `NativeWasmTypeInto`: 26 | # f32 27 | # f64 28 | # i32 29 | # i64 30 | # u128 31 | plugin = [] 32 | 33 | [dependencies] 34 | anyhow = { workspace = true } 35 | getrandom = { workspace = true, features = ["js"] } 36 | serde = { workspace = true, features = ["derive"] } 37 | serde-wasm-bindgen = { workspace = true } 38 | swc_core = { workspace = true, features = [ 39 | "ecma_ast_serde", 40 | "ecma_codegen", 41 | "binding_macro_wasm", 42 | "ecma_transforms", 43 | "ecma_visit", 44 | ] } 45 | tracing = { workspace = true, features = ["max_level_off"] } 46 | wasm-bindgen = { workspace = true, features = ["enable-interning"] } 47 | 48 | [package.metadata.wasm-pack.profile.release] 49 | wasm-opt = false 50 | -------------------------------------------------------------------------------- /deps/swc/bindings/binding_core_wasm/__tests__/error.js: -------------------------------------------------------------------------------- 1 | const swc = require("../pkg"); 2 | 3 | it("properly reports error", () => { 4 | expect(() => { 5 | swc.transformSync("Foo {}", {}); 6 | }).toThrow("Syntax Error"); 7 | 8 | expect(() => { 9 | swc.transformSync("Foo {}", {}); 10 | }).toThrow("Expected ';', '}' or "); 11 | }); 12 | -------------------------------------------------------------------------------- /deps/swc/bindings/binding_core_wasm/__tests__/simple.js: -------------------------------------------------------------------------------- 1 | const swc = require("../pkg"); 2 | 3 | describe("transform", () => { 4 | it("should work", () => { 5 | const output = swc.transformSync("class Foo {}", {}); 6 | 7 | expect(output).toMatchInlineSnapshot(` 8 | { 9 | "code": "function _class_call_check(instance, Constructor) { 10 | if (!(instance instanceof Constructor)) { 11 | throw new TypeError("Cannot call a class as a function"); 12 | } 13 | } 14 | var Foo = function Foo() { 15 | "use strict"; 16 | _class_call_check(this, Foo); 17 | }; 18 | ", 19 | "diagnostics": [], 20 | } 21 | `); 22 | }); 23 | 24 | it("should work with async facade", async () => { 25 | const output = await swc.transform("class Foo {}", {}); 26 | 27 | expect(output).toMatchInlineSnapshot(` 28 | { 29 | "code": "function _class_call_check(instance, Constructor) { 30 | if (!(instance instanceof Constructor)) { 31 | throw new TypeError("Cannot call a class as a function"); 32 | } 33 | } 34 | var Foo = function Foo() { 35 | "use strict"; 36 | _class_call_check(this, Foo); 37 | }; 38 | ", 39 | "diagnostics": [], 40 | } 41 | `); 42 | }); 43 | 44 | it("should work with program object", async () => { 45 | const input = swc.parseSync("class Foo {}", { 46 | syntax: "typescript", 47 | target: "es2021", 48 | }); 49 | 50 | const output = await swc.transform(input, {}); 51 | expect(output).toMatchInlineSnapshot(` 52 | { 53 | "code": "function _class_call_check(instance, Constructor) { 54 | if (!(instance instanceof Constructor)) { 55 | throw new TypeError("Cannot call a class as a function"); 56 | } 57 | } 58 | var Foo = function Foo() { 59 | "use strict"; 60 | _class_call_check(this, Foo); 61 | }; 62 | ", 63 | "diagnostics": [], 64 | } 65 | `); 66 | }); 67 | 68 | it("should support 'paths' and 'baseUrl'", () => { 69 | const { code } = swc.transformSync( 70 | ` 71 | import foo from '@src/app'; 72 | console.log(foo) 73 | `, 74 | { 75 | filename: "main.js", 76 | jsc: { 77 | parser: { 78 | syntax: "typescript", 79 | }, 80 | target: "es2021", 81 | transform: {}, 82 | baseUrl: __dirname, 83 | paths: { 84 | "@src/*": ["bar/*"], 85 | }, 86 | }, 87 | module: { 88 | type: "commonjs", 89 | }, 90 | } 91 | ); 92 | 93 | expect(code).toContain(`bar/app`); 94 | }); 95 | }); 96 | 97 | describe("parse", () => { 98 | it("should work", () => { 99 | const output = swc.parseSync("class Foo {}", { 100 | syntax: "typescript", 101 | target: "es2021", 102 | }); 103 | 104 | expect(output).toMatchInlineSnapshot(` 105 | { 106 | "body": [ 107 | { 108 | "body": [], 109 | "ctxt": 0, 110 | "declare": false, 111 | "decorators": [], 112 | "identifier": { 113 | "ctxt": 2, 114 | "optional": false, 115 | "span": { 116 | "end": 289, 117 | "start": 286, 118 | }, 119 | "type": "Identifier", 120 | "value": "Foo", 121 | }, 122 | "implements": [], 123 | "isAbstract": false, 124 | "span": { 125 | "end": 292, 126 | "start": 280, 127 | }, 128 | "superClass": null, 129 | "superTypeParams": null, 130 | "type": "ClassDeclaration", 131 | "typeParams": null, 132 | }, 133 | ], 134 | "interpreter": null, 135 | "span": { 136 | "end": 292, 137 | "start": 280, 138 | }, 139 | "type": "Module", 140 | } 141 | `); 142 | }); 143 | 144 | it("should work with async facade", async () => { 145 | const output = await swc.parse("class Foo {}", { 146 | syntax: "typescript", 147 | target: "es2021", 148 | }); 149 | 150 | expect(output).toMatchInlineSnapshot(` 151 | { 152 | "body": [ 153 | { 154 | "body": [], 155 | "ctxt": 0, 156 | "declare": false, 157 | "decorators": [], 158 | "identifier": { 159 | "ctxt": 2, 160 | "optional": false, 161 | "span": { 162 | "end": 302, 163 | "start": 299, 164 | }, 165 | "type": "Identifier", 166 | "value": "Foo", 167 | }, 168 | "implements": [], 169 | "isAbstract": false, 170 | "span": { 171 | "end": 305, 172 | "start": 293, 173 | }, 174 | "superClass": null, 175 | "superTypeParams": null, 176 | "type": "ClassDeclaration", 177 | "typeParams": null, 178 | }, 179 | ], 180 | "interpreter": null, 181 | "span": { 182 | "end": 305, 183 | "start": 293, 184 | }, 185 | "type": "Module", 186 | } 187 | `); 188 | }); 189 | }); 190 | 191 | describe("minify", () => { 192 | it("should work", () => { 193 | const output = swc.minifySync( 194 | "const somename = 1; console.log(somename);", 195 | { module: false } 196 | ); 197 | 198 | expect(output).toMatchInlineSnapshot(` 199 | { 200 | "code": "let somename=1;console.log(1);", 201 | "diagnostics": [], 202 | } 203 | `); 204 | }); 205 | 206 | it("should work with async facade", async () => { 207 | const output = await swc.minify( 208 | "const somename = 1; console.log(somename);", 209 | { module: false } 210 | ); 211 | 212 | expect(output).toMatchInlineSnapshot(` 213 | { 214 | "code": "let somename=1;console.log(1);", 215 | "diagnostics": [], 216 | } 217 | `); 218 | }); 219 | }); 220 | 221 | describe("print", () => { 222 | it("should work", () => { 223 | const input = swc.parseSync("class Foo {}", { 224 | syntax: "typescript", 225 | target: "es2021", 226 | }); 227 | 228 | const output = swc.printSync(input); 229 | expect(output).toMatchInlineSnapshot(` 230 | { 231 | "code": "class Foo { 232 | } 233 | ", 234 | "diagnostics": [], 235 | } 236 | `); 237 | }); 238 | 239 | it("should work with async facade", async () => { 240 | const input = swc.parseSync("class Foo {}", { 241 | syntax: "typescript", 242 | target: "es2021", 243 | }); 244 | 245 | const output = await swc.print(input); 246 | expect(output).toMatchInlineSnapshot(` 247 | { 248 | "code": "class Foo { 249 | } 250 | ", 251 | "diagnostics": [], 252 | } 253 | `); 254 | }); 255 | }); 256 | -------------------------------------------------------------------------------- /deps/swc/bindings/binding_core_wasm/example/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /deps/swc/bindings/binding_core_wasm/example/index.js: -------------------------------------------------------------------------------- 1 | let settings = { 2 | jsc: { 3 | target: "es2016", 4 | parser: { 5 | syntax: "ecmascript", 6 | jsx: true, 7 | dynamicImport: false, 8 | numericSeparator: false, 9 | privateMethod: false, 10 | functionBind: false, 11 | exportDefaultFrom: false, 12 | exportNamespaceFrom: false, 13 | decorators: false, 14 | decoratorsBeforeExport: false, 15 | topLevelAwait: false, 16 | importMeta: false, 17 | }, 18 | }, 19 | }; 20 | 21 | let code = ` 22 | let a = 1; 23 | let b = { 24 | c: { 25 | d: 1 26 | } 27 | 28 | }; 29 | console.log(b?.c?.d); 30 | 31 | let MyComponent = () => { 32 | return (
33 |

Hello World!

34 |
); 35 | } 36 | `; 37 | 38 | const swc = import("./pkg/wasm.js"); 39 | swc.then((swc) => { 40 | console.log("SWC Loaded", swc); 41 | let result = swc.transformSync(code, settings); 42 | console.log("result from transformSync", result); 43 | console.log(result.code); 44 | document.getElementById("result").innerHTML = 45 | "" + result.code + ""; 46 | document.getElementById("source").innerHTML = "" + code + ""; 47 | }); 48 | -------------------------------------------------------------------------------- /deps/swc/bindings/binding_core_wasm/example/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "copy-files": "copyfiles ../pkg/* ./pkg", 4 | "dev-server": "webpack-dev-server", 5 | "serve": "run-s copy-files dev-server" 6 | }, 7 | "devDependencies": { 8 | "copyfiles": "^2.3.0", 9 | "npm-run-all": "^4.1.5", 10 | "webpack": "^4.25.1", 11 | "webpack-cli": "^3.1.2", 12 | "webpack-dev-server": "^3.1.10" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /deps/swc/bindings/binding_core_wasm/example/readme.txt: -------------------------------------------------------------------------------- 1 | To run this example, you first need to build swc for the web: 2 | 3 | cd swc/wasm 4 | ./scripts/build_web_release.sh 5 | 6 | Then run npm install: 7 | 8 | cd swc/wasm/example 9 | npm install 10 | 11 | Finally, start the webpack-dev-server: 12 | 13 | cd swc/wasm/example 14 | npm run serve 15 | 16 | Browse to http://localhost:8080 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /deps/swc/bindings/binding_core_wasm/example/webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require("path"); 2 | 3 | module.exports = { 4 | entry: "./index.js", 5 | output: { 6 | path: path.resolve(__dirname, "dist"), 7 | filename: "index.js", 8 | }, 9 | mode: "development", 10 | }; 11 | -------------------------------------------------------------------------------- /deps/swc/bindings/binding_core_wasm/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "devDependencies": { 3 | "jest": "^29.7.0" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /deps/swc/bindings/binding_core_wasm/scripts/test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -eu 4 | 5 | wasm-pack build --out-name wasm --release --scope=swc --target nodejs 6 | npx jest $@ -------------------------------------------------------------------------------- /deps/swc/bindings/binding_core_wasm/src/lib.rs: -------------------------------------------------------------------------------- 1 | use swc_core::binding_macros::{ 2 | build_minify, build_minify_sync, build_parse, build_parse_sync, build_print, build_print_sync, 3 | build_transform, build_transform_sync, 4 | }; 5 | use wasm_bindgen::prelude::*; 6 | mod types; 7 | 8 | /// Custom interface definitions for the @swc/wasm's public interface instead of 9 | /// auto generated one, which is not reflecting most of types in detail. 10 | #[wasm_bindgen(typescript_custom_section)] 11 | const INTERFACE_DEFINITIONS: &'static str = r#" 12 | export function minify(src: string, opts?: JsMinifyOptions): Promise; 13 | export function minifySync(code: string, opts?: JsMinifyOptions): Output; 14 | 15 | export function parse(src: string, options: ParseOptions & { 16 | isModule: false; 17 | }): Promise