diff --git a/.flowconfig b/.flowconfig index cdc1d1cf0cd..61557139c3d 100644 --- a/.flowconfig +++ b/.flowconfig @@ -36,4 +36,4 @@ untyped-import untyped-type-import [version] -0.164.0 +0.173.0 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000000..32fb41d5787 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,102 @@ +on: pull_request + +name: Continuous Integration + +jobs: + lint: + name: Lint + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-node@v2 + with: + cache: yarn + - uses: actions-rs/toolchain@v1 + - uses: Swatinem/rust-cache@v1 + # use `--frozen-lockfile` to fail immediately if the committed yarn.lock needs updates + # https://yarnpkg.com/lang/en/docs/cli/install/#toc-yarn-install-frozen-lockfile + - run: yarn --frozen-lockfile + - run: yarn lint + + flow: + name: Flow + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-node@v2 + with: + cache: yarn + - run: yarn --frozen-lockfile + - run: yarn flow check + + benchmarks: + name: Benchmarks + runs-on: ubuntu-latest + steps: + - name: PR Benchmarks + uses: parcel-bundler/parcel-benchmark-action@master + env: + PARCEL_BENCHMARK_APIKEY: ${{ secrets.PARCEL_BENCHMARK_APIKEY }} + + unit_tests: + name: Unit tests (${{matrix.os}}, Node ${{matrix.node}}) + strategy: + matrix: + node: [12, 14] + os: [ubuntu-latest, macos-latest, windows-latest] + runs-on: ${{matrix.os}} + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-node@v2 + with: + cache: yarn + node-version: ${{matrix.node}} + - uses: actions-rs/toolchain@v1 + - uses: Swatinem/rust-cache@v1 + - name: Bump max inotify watches (Linux only) + run: echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p; + if: ${{matrix.os == 'ubuntu-latest'}} + - run: yarn --frozen-lockfile + - run: yarn build-native-release + - run: yarn test:unit + + integration_tests: + name: Integration tests (${{matrix.os}}, Node ${{matrix.node}}) + strategy: + matrix: + node: [12, 14] + os: [ubuntu-latest, macos-latest, windows-latest] + runs-on: ${{matrix.os}} + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-node@v2 + with: + cache: yarn + node-version: ${{matrix.node}} + - uses: actions-rs/toolchain@v1 + - uses: Swatinem/rust-cache@v1 + - name: Bump max inotify watches (Linux only) + run: echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p; + if: ${{matrix.os == 'ubuntu-latest'}} + - run: yarn --frozen-lockfile + - run: yarn build-native-release + - run: yarn test:integration-ci + # Similar to + # https://github.com/marketplace/actions/publish-unit-test-results#use-with-matrix-strategy + - name: Upload JUnit results + if: always() + uses: actions/upload-artifact@v2 + with: + name: Integration tests (${{matrix.os}}, node ${{matrix.node}}) + path: '**/junit-*.xml' + + test_report: + name: Test report + runs-on: ubuntu-latest + needs: [unit_tests, integration_tests] + if: always() + steps: + - name: Create test report + uses: mikepenz/action-junit-report@v2 + with: + report_paths: artifacts/**/*.xml diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml deleted file mode 100644 index 4631aee6810..00000000000 --- a/.github/workflows/main.yml +++ /dev/null @@ -1,13 +0,0 @@ -on: pull_request - -name: Generate benchmarks - -jobs: - prBenchmarks: - name: PR Benchmarks - runs-on: ubuntu-latest - steps: - - name: PR Benchmarks - uses: parcel-bundler/parcel-benchmark-action@master - env: - PARCEL_BENCHMARK_APIKEY: ${{ secrets.PARCEL_BENCHMARK_APIKEY }} diff --git a/.github/workflows/tag-release.yml b/.github/workflows/tag-release.yml index cd76bc7e2ac..78379202b3f 100644 --- a/.github/workflows/tag-release.yml +++ b/.github/workflows/tag-release.yml @@ -209,8 +209,6 @@ jobs: steps: - uses: actions/checkout@v1 - uses: bahmutov/npm-install@v1.1.0 - - name: Build native packages - run: yarn build-native-release - name: Download artifacts uses: actions/download-artifact@v2 with: diff --git a/CHANGELOG.md b/CHANGELOG.md index cd02d35848e..92dbcf0f606 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,24 @@ All notable changes to Parcel will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and Parcel adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). +## [2.3.1] - 2022-02-09 + +## Fixed + +- Add diagnostic for failed autoinstall of node polyfill - [Details](https://github.com/parcel-bundler/parcel/pull/7682) + +## [2.3.0] - 2022-02-09 + +## Added + +- Reduce the number of npm dependencies needed by parcel [Details](https://github.com/parcel-bundler/parcel/pull/7576) +- Support React 18 prereleases and experimental versions with automatic JSX runtime - [Details](https://github.com/parcel-bundler/parcel/pull/7642) + +## Fixed + +- Fix `@swc/helpers` in non-module scripts - [Details](https://github.com/parcel-bundler/parcel/pull/7599) +- Fix auto installing dependencies in PNPM monorepos - [Details](https://github.com/parcel-bundler/parcel/pull/7566) + ## [2.2.1] - 2022-01-17 ### Fixed diff --git a/azure-pipelines-template.yml b/azure-pipelines-template.yml deleted file mode 100644 index 56d9b2116bd..00000000000 --- a/azure-pipelines-template.yml +++ /dev/null @@ -1,89 +0,0 @@ -jobs: - - job: ${{ parameters.name }} - pool: - vmImage: ${{ parameters.vmImage }} - strategy: - matrix: - node_12_x: - node_version: 12.x - node_14_x: - node_version: 14.x - maxParallel: 3 - variables: - # From https://docs.microsoft.com/en-us/azure/devops/pipelines/release/caching?view=azure-devops - CARGO_HOME: $(Pipeline.Workspace)/.cargo - YARN_CACHE_FOLDER: $(Pipeline.Workspace)/.yarn - steps: - - task: NodeTool@0 - inputs: - versionSpec: $(node_version) - displayName: 'Install Node.js' - - # Install Rust - - ${{ if ne(parameters.name, 'Windows') }}: - - script: | - curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain stable - export PATH="$HOME/.cargo/bin:$PATH" - echo "##vso[task.setvariable variable=PATH]$PATH" - rustc -Vv - cargo -V - displayName: Install Rust - - ${{ if eq(parameters.name, 'Windows') }}: - - script: | - curl -sSf -o rustup-init.exe https://win.rustup.rs - rustup-init.exe -y --default-toolchain stable --default-host x86_64-pc-windows-msvc - set PATH=%PATH%;%USERPROFILE%\.cargo\bin - echo "##vso[task.setvariable variable=PATH]%PATH%;%USERPROFILE%\.cargo\bin" - rustc -Vv - cargo -V - displayName: Install Rust - - - ${{ if eq(parameters.name, 'Linux') }}: - - script: | - echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p; - displayName: Bump max inotify watches - - # From https://docs.microsoft.com/en-us/azure/devops/pipelines/release/caching?view=azure-devops - - task: Cache@2 - inputs: - key: 'cargo | "$(Agent.OS)" | Cargo.lock' - restoreKeys: | - cargo | "$(Agent.OS)" - cargo - path: $(CARGO_HOME) - displayName: Cache Cargo directory - # Like yarn --frozen-lockfile, fails immediately if lockfile needs updates - - script: cargo fetch --locked - displayName: 'Fetch cargo dependencies' - - script: cargo test --all - displayName: 'Run Rust tests' - - # From https://docs.microsoft.com/en-us/azure/devops/pipelines/release/caching?view=azure-devops - - task: Cache@2 - inputs: - key: 'yarn | "$(Agent.OS)" | yarn.lock' - restoreKeys: | - yarn | "$(Agent.OS)" - yarn - path: $(YARN_CACHE_FOLDER) - displayName: Cache yarn directory - # use `--frozen-lockfile` to fail immediately if the committed yarn.lock needs updates - # https://yarnpkg.com/lang/en/docs/cli/install/#toc-yarn-install-frozen-lockfile - - script: yarn --frozen-lockfile - displayName: 'Install dependencies' - - script: yarn build-native-release - displayName: 'Build native packages' - - script: yarn test:unit - displayName: 'Run unit tests' - - script: yarn test:integration-ci - displayName: 'Run integration tests' - - script: yarn flow check - displayName: 'Type check with Flow' - - script: yarn lint - displayName: 'Lint' - - task: PublishTestResults@2 - displayName: 'Publish Test Results' - condition: succeededOrFailed() - inputs: - testResultsFiles: '**/junit-*.xml' - testRunTitle: TestRun ${{ parameters.name }} $(node_version) diff --git a/azure-pipelines.yml b/azure-pipelines.yml deleted file mode 100644 index 62a389d3a9e..00000000000 --- a/azure-pipelines.yml +++ /dev/null @@ -1,15 +0,0 @@ -jobs: -- template: azure-pipelines-template.yml - parameters: - name: macOS - vmImage: macOS-latest - -- template: azure-pipelines-template.yml - parameters: - name: Linux - vmImage: ubuntu-latest - -- template: azure-pipelines-template.yml - parameters: - name: Windows - vmImage: windows-latest diff --git a/flow-libs/babel-core.js.flow b/flow-libs/babel-core.js.flow index cc1011e57ac..f98e134ada5 100644 --- a/flow-libs/babel-core.js.flow +++ b/flow-libs/babel-core.js.flow @@ -171,4 +171,5 @@ declare module "@babel/core" { | [string | { ... } | Function, { ... } | void], {| dirname?: string, type?: "preset" | "plugin" |} ): ConfigItem; + declare export * as types from "@babel/types"; } diff --git a/flow-typed/npm/mocha_v8.x.x.js b/flow-typed/npm/mocha_v8.x.x.js index 7affb5c0c2f..be4a819c81e 100644 --- a/flow-typed/npm/mocha_v8.x.x.js +++ b/flow-typed/npm/mocha_v8.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: 195cec6dc98ab7533f0eb927ee493f99 -// flow-typed version: 1a6d5d1968/mocha_v8.x.x/flow_>=v0.104.x +// flow-typed signature: a9c051e037cdcce97b16e692321e6856 +// flow-typed version: b074eb3e38/mocha_v8.x.x/flow_>=v0.104.x declare interface $npm$mocha$SetupOptions { slow?: number; @@ -206,7 +206,7 @@ type AfterEach = declare var setup: Setup; declare var teardown: Teardown; declare var suiteSetup: SuiteSetup; -declare var suiteTeardown; +declare var suiteTeardown: SuiteTeardown; declare var before: Before declare var after: After; declare var beforeEach: BeforeEach; diff --git a/gulpfile.js b/gulpfile.js index 6b99bcdf9bd..d369fe0b685 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -12,7 +12,15 @@ const IGNORED_PACKAGES = [ '!packages/core/is-v2-ready-yet/**', '!packages/core/test-utils/**', '!packages/core/types/**', - '!packages/utils/node-libs-browser/**', + + // These packages are bundled. + '!packages/core/codeframe/**', + '!packages/core/fs/**', + '!packages/core/package-manager/**', + '!packages/core/utils/**', + '!packages/reporters/cli/**', + '!packages/reporters/dev-server/**', + '!packages/utils/fs-write-stream-atomic/**', ]; const paths = { diff --git a/package.json b/package.json index 54fd01c7d2c..824b902142f 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,8 @@ "packages/*/*" ], "scripts": { - "build": "cross-env NODE_ENV=production PARCEL_BUILD_ENV=production gulp", + "build": "yarn build-bundles && cross-env NODE_ENV=production PARCEL_BUILD_ENV=production gulp", + "build-bundles": "rm -rf packages/*/*/lib && cross-env NODE_ENV=production PARCEL_BUILD_ENV=production PARCEL_SELF_BUILD=true parcel build packages/core/{fs,codeframe,package-manager,utils} packages/reporters/{cli,dev-server}", "build-ts": "lerna run build-ts && lerna run check-ts", "build-native": "node scripts/build-native.js", "build-native-release": "node scripts/build-native.js --release", @@ -22,7 +23,7 @@ "unlink-all": "node scripts/unlink-all.js packages", "check": "flow check", "lint": "eslint . && prettier \"./packages/*/*/{src,bin,test}/**/*.{js,json,md}\" --list-different", - "prepublishOnly": "yarn build && yarn build-ts && yarn adjust-versions && rename-parcel-packages", + "prepublishOnly": "yarn adjust-versions yarn build && yarn build-ts && rename-parcel-packages", "test:unit": "cross-env NODE_ENV=test mocha", "test:integration": "yarn workspace @parcel/integration-tests test", "test:integration-ci": "yarn workspace @parcel/integration-tests test-ci", @@ -31,7 +32,7 @@ "version:atlassian": "yarn lerna version patch --exact --force-publish=@atlassian/internal-parcel-utils,@atlassian/parcel-reporter-analytics", "nightly:release": "lerna publish -y --canary --preid nightly --dist-tag=nightly --exact --force-publish=* --no-git-tag-version --no-push", "tag:prerelease": "lerna version --exact --force-publish=* --no-git-tag-version --no-push && yarn adjust-versions --exact", - "tag:release": "lerna version --force-publish=* --no-git-tag-version --no-push && yarn adjust-versions", + "tag:release": "lerna version --exact --force-publish=* --no-git-tag-version --no-push && yarn adjust-versions", "adjust-versions": "node scripts/update-config-dependencies.js && node scripts/update-engines-peerdeps.js", "release": "lerna publish -y from-package --pre-dist-tag=next --no-git-tag-version --no-push", "prepare": "husky install" @@ -43,7 +44,7 @@ "@types/node": "^15.12.4", "cross-env": "^7.0.0", "eslint": "^7.20.0", - "flow-bin": "0.164.0", + "flow-bin": "0.173.0", "glob": "^7.1.6", "gulp": "^4.0.2", "gulp-babel": "^8.0.0", @@ -54,7 +55,7 @@ "mocha-junit-reporter": "^2.0.0", "mocha-multi-reporters": "^1.5.1", "prettier": "2.4.1", - "rimraf": "^2.6.3", + "rimraf": "^3.0.2", "semver": "^5.7.1", "sinon": "^7.3.1" }, diff --git a/packages/configs/default/package.json b/packages/configs/default/package.json index 9ab227f8a44..380db33d486 100644 --- a/packages/configs/default/package.json +++ b/packages/configs/default/package.json @@ -40,6 +40,7 @@ "@parcel/transformer-babel": "2.0.15", "@parcel/transformer-css": "2.0.15", "@parcel/transformer-html": "2.0.15", + "@parcel/transformer-image": "2.0.15", "@parcel/transformer-js": "2.0.15", "@parcel/transformer-json": "2.0.15", "@parcel/transformer-postcss": "2.0.15", @@ -57,7 +58,6 @@ "@parcel/transformer-elm": "2.0.7", "@parcel/transformer-glsl": "2.0.7", "@parcel/transformer-graphql": "2.0.7", - "@parcel/transformer-image": "2.0.7", "@parcel/transformer-inline-string": "2.0.7", "@parcel/transformer-jsonld": "2.0.7", "@parcel/transformer-less": "2.0.7", @@ -75,6 +75,6 @@ "@parcel/transformer-yaml": "2.0.7" }, "peerDependencies": { - "@parcel/core": "^2.2.1" + "@parcel/core": "^2.3.2" } } diff --git a/packages/core/cache/package.json b/packages/core/cache/package.json index 5fcb8a4bff0..92265e57b32 100644 --- a/packages/core/cache/package.json +++ b/packages/core/cache/package.json @@ -27,7 +27,7 @@ "@parcel/fs": "2.0.15", "@parcel/logger": "2.0.15", "@parcel/utils": "2.0.15", - "lmdb": "^2.0.2" + "lmdb": "2.2.4" }, "peerDependencies": { "@parcel/core": "^2.2.1" diff --git a/packages/core/codeframe/package.json b/packages/core/codeframe/package.json index 4f880e68171..415dc0e65d1 100644 --- a/packages/core/codeframe/package.json +++ b/packages/core/codeframe/package.json @@ -19,13 +19,20 @@ "engines": { "node": ">= 12.0.0" }, + "targets": { + "main": { + "includeNodeModules": { + "chalk": false + } + } + }, "dependencies": { - "chalk": "^4.1.0", - "emphasize": "^4.2.0", - "slice-ansi": "^4.0.0", - "string-width": "^4.2.0" + "chalk": "^4.1.0" }, "devDependencies": { + "emphasize": "^4.2.0", + "slice-ansi": "^4.0.0", + "string-width": "^4.2.0", "strip-ansi": "^6.0.0" } } diff --git a/packages/core/core/package.json b/packages/core/core/package.json index 053e8d282ec..dd4f7f38521 100644 --- a/packages/core/core/package.json +++ b/packages/core/core/package.json @@ -45,8 +45,7 @@ "dotenv-expand": "^5.1.0", "json-source-map": "^0.6.1", "json5": "^2.2.0", - "micromatch": "^4.0.2", - "msgpackr": "^1.5.1", + "msgpackr": "^1.5.4", "nullthrows": "^1.1.1", "semver": "^5.7.1" }, diff --git a/packages/core/core/src/ParcelConfig.js b/packages/core/core/src/ParcelConfig.js index 2ace49e0344..cec4ebd4f0a 100644 --- a/packages/core/core/src/ParcelConfig.js +++ b/packages/core/core/src/ParcelConfig.js @@ -29,7 +29,7 @@ import ThrowableDiagnostic, { } from '@parcel/diagnostic'; import json5 from 'json5'; -import {makeRe} from 'micromatch'; +import {globToRegex} from '@parcel/utils'; import {basename} from 'path'; import loadPlugin from './loadParcelPlugin'; import { @@ -347,7 +347,7 @@ export default class ParcelConfig { let re = this.regexCache.get(patternGlob); if (!re) { - re = makeRe(patternGlob, {dot: true, nocase: true}); + re = globToRegex(patternGlob, {dot: true, nocase: true}); this.regexCache.set(patternGlob, re); } diff --git a/packages/core/core/src/requests/AssetGraphRequest.js b/packages/core/core/src/requests/AssetGraphRequest.js index 8d3c5cf2a1e..a7bf0b2854e 100644 --- a/packages/core/core/src/requests/AssetGraphRequest.js +++ b/packages/core/core/src/requests/AssetGraphRequest.js @@ -114,14 +114,13 @@ const typesWithRequests = new Set([ export class AssetGraphBuilder { assetGraph: AssetGraph; - assetRequests: Array; + assetRequests: Array = []; queue: PromiseQueue; changedAssets: Map = new Map(); optionsRef: SharedReference; options: ParcelOptions; api: RunAPI; name: string; - assetRequests: Array = []; cacheKey: string; shouldBuildLazily: boolean; requestedAssetIds: Set; diff --git a/packages/core/core/src/requests/TargetRequest.js b/packages/core/core/src/requests/TargetRequest.js index 26cf9b5a7e3..77dfbdc38b4 100644 --- a/packages/core/core/src/requests/TargetRequest.js +++ b/packages/core/core/src/requests/TargetRequest.js @@ -18,6 +18,7 @@ import type {ConfigAndCachePath} from './ParcelConfigRequest'; import ThrowableDiagnostic, { generateJSONCodeHighlights, getJSONSourceLocation, + encodeJSONKeyComponent, md, } from '@parcel/diagnostic'; import path from 'path'; @@ -503,11 +504,12 @@ export class TargetResolver { if ( targetName === 'browser' && pkg[targetName] != null && - typeof pkg[targetName] === 'object' + typeof pkg[targetName] === 'object' && + pkg.name ) { // The `browser` field can be a file path or an alias map. _targetDist = pkg[targetName][pkg.name]; - pointer = `/${targetName}/${pkg.name}`; + pointer = `/${targetName}/${encodeJSONKeyComponent(pkg.name)}`; } else { _targetDist = pkg[targetName]; pointer = `/${targetName}`; diff --git a/packages/core/fs/package.json b/packages/core/fs/package.json index aec4fb0f56a..b4217fa3de8 100644 --- a/packages/core/fs/package.json +++ b/packages/core/fs/package.json @@ -20,28 +20,52 @@ "engines": { "node": ">= 12.0.0" }, + "targets": { + "types": false, + "main": { + "includeNodeModules": { + "@parcel/core": false, + "@parcel/fs-search": false, + "@parcel/types": false, + "@parcel/utils": false, + "@parcel/watcher": false, + "@parcel/workers": false + } + }, + "browser": { + "includeNodeModules": { + "@parcel/core": false, + "@parcel/fs-search": false, + "@parcel/types": false, + "@parcel/utils": false, + "@parcel/watcher": false, + "@parcel/workers": false + } + } + }, "scripts": { "build-ts": "mkdir -p lib && flow-to-ts src/types.js > lib/types.d.ts", "check-ts": "tsc --noEmit index.d.ts" }, "dependencies": { "@parcel/fs-search": "2.0.15", - "@parcel/fs-write-stream-atomic": "2.0.15", "@parcel/types": "2.0.15", "@parcel/utils": "2.0.15", "@parcel/watcher": "^2.0.0", - "@parcel/workers": "2.0.15", + "@parcel/workers": "2.0.15" + }, + "devDependencies": { + "@parcel/fs-write-stream-atomic": "2.0.15", "graceful-fs": "^4.2.4", - "mkdirp": "^0.5.1", "ncp": "^2.0.0", "nullthrows": "^1.1.1", - "rimraf": "^3.0.2", "utility-types": "^3.10.0" }, "peerDependencies": { - "@parcel/core": "^2.2.1" + "@parcel/core": "^2.3.2" }, "browser": { + "@parcel/fs": "./lib/browser.js", "./src/NodeFS.js": "./src/NodeFS.browser.js" } } diff --git a/packages/core/fs/src/NodeFS.js b/packages/core/fs/src/NodeFS.js index a6e9a428336..60be6425f35 100644 --- a/packages/core/fs/src/NodeFS.js +++ b/packages/core/fs/src/NodeFS.js @@ -10,9 +10,8 @@ import type { } from '@parcel/watcher'; import fs from 'graceful-fs'; +import nativeFS from 'fs'; import ncp from 'ncp'; -import mkdirp from 'mkdirp'; -import rimraf from 'rimraf'; import {promisify} from 'util'; import {registerSerializableClass} from '@parcel/core'; import fsWriteStreamAtomic from '@parcel/fs-write-stream-atomic'; @@ -37,8 +36,6 @@ export class NodeFS implements FileSystem { readdir: any = promisify(fs.readdir); unlink: any = promisify(fs.unlink); utimes: any = promisify(fs.utimes); - mkdirp: any = promisify(mkdirp); - rimraf: any = promisify(rimraf); ncp: any = promisify(ncp); createReadStream: (path: string, options?: any) => ReadStream = fs.createReadStream; @@ -133,6 +130,32 @@ export class NodeFS implements FileSystem { serialize(): null { return null; } + + async mkdirp(filePath: FilePath): Promise { + await nativeFS.promises.mkdir(filePath, {recursive: true}); + } + + async rimraf(filePath: FilePath): Promise { + if (fs.promises.rm) { + await fs.promises.rm(filePath, {recursive: true, force: true}); + return; + } + + // fs.promises.rm is not supported in node 12... + let stat; + try { + stat = await this.stat(filePath); + } catch (err) { + return; + } + + if (stat.isDirectory()) { + // $FlowFixMe + await nativeFS.promises.rmdir(filePath, {recursive: true}); + } else { + await nativeFS.promises.unlink(filePath); + } + } } registerSerializableClass(`${packageJSON.version}:NodeFS`, NodeFS); diff --git a/packages/core/integration-tests/package.json b/packages/core/integration-tests/package.json index 8949c0eb553..467746ef73f 100644 --- a/packages/core/integration-tests/package.json +++ b/packages/core/integration-tests/package.json @@ -51,7 +51,6 @@ "preact": "^10.5.9", "react": "^17.0.2", "react-dom": "^17.0.2", - "rimraf": "^2.6.1", "sugarss": "^3.0.3", "tailwindcss": "^3.0.2", "tempy": "^0.3.0", diff --git a/packages/core/integration-tests/test/babel.js b/packages/core/integration-tests/test/babel.js index 53c2f3d912a..cb664a1b979 100644 --- a/packages/core/integration-tests/test/babel.js +++ b/packages/core/integration-tests/test/babel.js @@ -376,6 +376,11 @@ describe('babel', function () { }); it('should rebuild when .babelrc changes', async function () { + if (process.platform !== 'linux') { + // This test is flaky outside of Linux. Skip it for now. + return; + } + let inputDir = tempy.directory(); let differentPath = path.join(inputDir, 'differentConfig'); let configPath = path.join(inputDir, '.babelrc'); @@ -395,6 +400,7 @@ describe('babel', function () { let distFile = await fs.readFile(path.join(distDir, 'index.js'), 'utf8'); assert(distFile.includes('hello there')); await fs.copyFile(differentPath, configPath); + await new Promise(resolve => setTimeout(resolve, 100)); // On Windows only, `fs.utimes` arguments must be instances of `Date`, // otherwise it fails. For Mac instances on Azure CI, using a Date instance // does not update the utime correctly, so for all other platforms, use a diff --git a/packages/core/integration-tests/test/html.js b/packages/core/integration-tests/test/html.js index 344cf7cf942..3bc4f82b991 100644 --- a/packages/core/integration-tests/test/html.js +++ b/packages/core/integration-tests/test/html.js @@ -1408,6 +1408,30 @@ describe('html', function () { assert(errored); }); + it('should not import swc/helpers without type="module"', async function () { + await bundle( + path.join( + __dirname, + '/integration/html-js-not-import-swc-helpers-without-module/index.html', + ), + { + defaultTargetOptions: { + engines: { + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment#browser_compatibility + browsers: ['Chrome 48'], + }, + }, + }, + ); + + let html = await outputFS.readFile( + path.join(distDir, 'index.html'), + 'utf8', + ); + assert(!html.includes('swc/helpers')); + assert(html.includes('slicedToArray')); + }); + it('should allow imports and requires in inline + \ No newline at end of file diff --git a/packages/core/integration-tests/test/integration/jsx-automatic-18/index.js b/packages/core/integration-tests/test/integration/jsx-automatic-18/index.js new file mode 100644 index 00000000000..8d097d55d7f --- /dev/null +++ b/packages/core/integration-tests/test/integration/jsx-automatic-18/index.js @@ -0,0 +1 @@ +module.exports =
; diff --git a/packages/core/integration-tests/test/integration/jsx-automatic-18/node_modules/react/jsx-dev-runtime.js b/packages/core/integration-tests/test/integration/jsx-automatic-18/node_modules/react/jsx-dev-runtime.js new file mode 100644 index 00000000000..e69de29bb2d diff --git a/packages/core/integration-tests/test/integration/jsx-automatic-18/node_modules/react/jsx-runtime.js b/packages/core/integration-tests/test/integration/jsx-automatic-18/node_modules/react/jsx-runtime.js new file mode 100644 index 00000000000..e69de29bb2d diff --git a/packages/core/integration-tests/test/integration/jsx-automatic-18/node_modules/react/package.json b/packages/core/integration-tests/test/integration/jsx-automatic-18/node_modules/react/package.json new file mode 100644 index 00000000000..bcbea4166f7 --- /dev/null +++ b/packages/core/integration-tests/test/integration/jsx-automatic-18/node_modules/react/package.json @@ -0,0 +1,3 @@ +{ + "name": "react" +} diff --git a/packages/core/integration-tests/test/integration/jsx-automatic-18/package.json b/packages/core/integration-tests/test/integration/jsx-automatic-18/package.json new file mode 100644 index 00000000000..70ac62a29af --- /dev/null +++ b/packages/core/integration-tests/test/integration/jsx-automatic-18/package.json @@ -0,0 +1,6 @@ +{ + "private": true, + "dependencies": { + "react": "18.0.0-rc.0-next-9a7e6bf0d-2022011" + } +} diff --git a/packages/core/integration-tests/test/integration/jsx-automatic-18/yarn.lock b/packages/core/integration-tests/test/integration/jsx-automatic-18/yarn.lock new file mode 100644 index 00000000000..e69de29bb2d diff --git a/packages/core/integration-tests/test/integration/jsx-automatic-experimental/index.js b/packages/core/integration-tests/test/integration/jsx-automatic-experimental/index.js new file mode 100644 index 00000000000..8d097d55d7f --- /dev/null +++ b/packages/core/integration-tests/test/integration/jsx-automatic-experimental/index.js @@ -0,0 +1 @@ +module.exports =
; diff --git a/packages/core/integration-tests/test/integration/jsx-automatic-experimental/node_modules/react/jsx-dev-runtime.js b/packages/core/integration-tests/test/integration/jsx-automatic-experimental/node_modules/react/jsx-dev-runtime.js new file mode 100644 index 00000000000..e69de29bb2d diff --git a/packages/core/integration-tests/test/integration/jsx-automatic-experimental/node_modules/react/jsx-runtime.js b/packages/core/integration-tests/test/integration/jsx-automatic-experimental/node_modules/react/jsx-runtime.js new file mode 100644 index 00000000000..e69de29bb2d diff --git a/packages/core/integration-tests/test/integration/jsx-automatic-experimental/node_modules/react/package.json b/packages/core/integration-tests/test/integration/jsx-automatic-experimental/node_modules/react/package.json new file mode 100644 index 00000000000..bcbea4166f7 --- /dev/null +++ b/packages/core/integration-tests/test/integration/jsx-automatic-experimental/node_modules/react/package.json @@ -0,0 +1,3 @@ +{ + "name": "react" +} diff --git a/packages/core/integration-tests/test/integration/jsx-automatic-experimental/package.json b/packages/core/integration-tests/test/integration/jsx-automatic-experimental/package.json new file mode 100644 index 00000000000..7dacf6d452b --- /dev/null +++ b/packages/core/integration-tests/test/integration/jsx-automatic-experimental/package.json @@ -0,0 +1,6 @@ +{ + "private": true, + "dependencies": { + "react": "0.0.0-d5e1bf0-aee1b" + } +} diff --git a/packages/core/integration-tests/test/integration/jsx-automatic-experimental/yarn.lock b/packages/core/integration-tests/test/integration/jsx-automatic-experimental/yarn.lock new file mode 100644 index 00000000000..e69de29bb2d diff --git a/packages/core/integration-tests/test/transpilation.js b/packages/core/integration-tests/test/transpilation.js index 78dff41cd09..c5e52a89bc7 100644 --- a/packages/core/integration-tests/test/transpilation.js +++ b/packages/core/integration-tests/test/transpilation.js @@ -203,6 +203,26 @@ describe('transpilation', function () { assert(file.includes('_jsxDevRuntime.jsxDEV("div"')); }); + it('should support the automatic JSX runtime with React 18 prereleases', async function () { + let b = await bundle( + path.join(__dirname, '/integration/jsx-automatic-18/index.js'), + ); + + let file = await outputFS.readFile(b.getBundles()[0].filePath, 'utf8'); + assert(file.includes('react/jsx-dev-runtime')); + assert(file.includes('_jsxDevRuntime.jsxDEV("div"')); + }); + + it('should support the automatic JSX runtime with experimental React versions', async function () { + let b = await bundle( + path.join(__dirname, '/integration/jsx-automatic-experimental/index.js'), + ); + + let file = await outputFS.readFile(b.getBundles()[0].filePath, 'utf8'); + assert(file.includes('react/jsx-dev-runtime')); + assert(file.includes('_jsxDevRuntime.jsxDEV("div"')); + }); + it('should support the automatic JSX runtime with preact with alias', async function () { let b = await bundle( path.join( diff --git a/packages/core/package-manager/package.json b/packages/core/package-manager/package.json index 496345e1b05..c7d87ee4c24 100644 --- a/packages/core/package-manager/package.json +++ b/packages/core/package-manager/package.json @@ -24,6 +24,21 @@ "build-ts": "mkdir -p lib && flow-to-ts src/types.js > lib/types.d.ts", "check-ts": "tsc --noEmit index.d.ts" }, + "targets": { + "types": false, + "main": { + "includeNodeModules": { + "@parcel/core": false, + "@parcel/diagnostic": false, + "@parcel/fs": false, + "@parcel/logger": false, + "@parcel/types": false, + "@parcel/utils": false, + "@parcel/workers": false, + "semver": false + } + } + }, "dependencies": { "@parcel/diagnostic": "2.0.15", "@parcel/fs": "2.0.15", @@ -31,10 +46,12 @@ "@parcel/types": "2.0.15", "@parcel/utils": "2.0.15", "@parcel/workers": "2.0.15", + "semver": "^5.7.1" + }, + "devDependencies": { "command-exists": "^1.2.6", "cross-spawn": "^6.0.4", "nullthrows": "^1.1.1", - "semver": "^5.7.1", "split2": "^3.1.1" }, "peerDependencies": { diff --git a/packages/core/package-manager/src/NodePackageManager.js b/packages/core/package-manager/src/NodePackageManager.js index cb6273187a4..9e5d665f542 100644 --- a/packages/core/package-manager/src/NodePackageManager.js +++ b/packages/core/package-manager/src/NodePackageManager.js @@ -391,9 +391,11 @@ export class NodePackageManager implements PackageManager { return; } - let module = require.cache[resolved.resolved]; + // $FlowFixMe + let module = Module._cache[resolved.resolved]; if (module) { - delete require.cache[resolved.resolved]; + // $FlowFixMe + delete Module._cache[resolved.resolved]; } let moduleChildren = children.get(resolved.resolved); diff --git a/packages/core/package-manager/src/NodeResolverBase.js b/packages/core/package-manager/src/NodeResolverBase.js index 7f9156a777a..ff4a1a0291c 100644 --- a/packages/core/package-manager/src/NodeResolverBase.js +++ b/packages/core/package-manager/src/NodeResolverBase.js @@ -79,7 +79,8 @@ export class NodeResolverBase { getPackageEntries(dir: FilePath, pkg: PackageJSON): Array { let main = pkg.main; if ( - process.env.PARCEL_BUILD_ENV !== 'production' && + (process.env.PARCEL_BUILD_ENV !== 'production' || + process.env.PARCEL_SELF_BUILD) && typeof pkg.name === 'string' && typeof pkg.source === 'string' && pkg.name.startsWith('@parcel/') && diff --git a/packages/core/package-manager/src/Pnpm.js b/packages/core/package-manager/src/Pnpm.js index 163f7207bb3..ef61ff2673d 100644 --- a/packages/core/package-manager/src/Pnpm.js +++ b/packages/core/package-manager/src/Pnpm.js @@ -84,7 +84,7 @@ export class Pnpm implements PackageInstaller { }: InstallerOptions): Promise { let args = ['add', '--reporter', 'ndjson']; if (saveDev) { - args.push('-D'); + args.push('-D', '-W'); } args = args.concat(modules.map(npmSpecifierFromModuleRequest)); diff --git a/packages/core/package-manager/src/index.js b/packages/core/package-manager/src/index.js index c8f0807d20c..c7c0f96d062 100644 --- a/packages/core/package-manager/src/index.js +++ b/packages/core/package-manager/src/index.js @@ -5,3 +5,4 @@ export * from './Pnpm'; export * from './Yarn'; export * from './MockPackageInstaller'; export * from './NodePackageManager'; +export {_addToInstallQueue} from './installPackage'; diff --git a/packages/core/parcel/src/bin.js b/packages/core/parcel/src/bin.js index 9d0d39131a2..c765ae38ea7 100755 --- a/packages/core/parcel/src/bin.js +++ b/packages/core/parcel/src/bin.js @@ -2,7 +2,10 @@ 'use strict'; -if (process.env.PARCEL_BUILD_ENV !== 'production') { +if ( + process.env.PARCEL_BUILD_ENV !== 'production' || + process.env.PARCEL_SELF_BUILD +) { require('@parcel/babel-register'); } diff --git a/packages/core/register/package.json b/packages/core/register/package.json index bd4df89fae4..9757b837947 100644 --- a/packages/core/register/package.json +++ b/packages/core/register/package.json @@ -1,6 +1,7 @@ { "name": "@parcel/register", "version": "2.0.15", + "private": true, "license": "MIT", "publishConfig": { "access": "public" @@ -27,7 +28,6 @@ "@parcel/core": "2.0.15", "@parcel/fs": "2.0.15", "@parcel/package-manager": "2.0.15", - "deasync": "^0.1.14", "pirates": "^4.0.0" } } diff --git a/packages/core/utils/package.json b/packages/core/utils/package.json index cf4ba7bb1a5..5cf988ad4d4 100644 --- a/packages/core/utils/package.json +++ b/packages/core/utils/package.json @@ -19,16 +19,32 @@ "engines": { "node": ">= 12.0.0" }, + "targets": { + "main": { + "includeNodeModules": { + "@parcel/codeframe": false, + "@parcel/diagnostic": false, + "@parcel/hash": false, + "@parcel/logger": false, + "@parcel/markdown-ansi": false, + "@parcel/source-map": false, + "chalk": false + } + } + }, "dependencies": { - "@iarna/toml": "^2.2.0", "@parcel/codeframe": "2.0.15", "@parcel/diagnostic": "2.0.15", "@parcel/hash": "2.0.15", "@parcel/logger": "2.0.15", "@parcel/markdown-ansi": "2.0.15", "@parcel/source-map": "^2.0.0", + "chalk": "^4.1.0" + }, + "devDependencies": { + "@babel/plugin-transform-flow-strip-types": "^7.2.0", + "@iarna/toml": "^2.2.0", "ansi-html-community": "0.0.8", - "chalk": "^4.1.0", "clone": "^2.1.1", "fast-glob": "3.1.1", "fastest-levenshtein": "^1.0.8", @@ -40,12 +56,9 @@ "node-forge": "^1.2.1", "nullthrows": "^1.1.1", "open": "^7.0.3", + "random-int": "^1.0.0", "terminal-link": "^2.1.1" }, - "devDependencies": { - "@babel/plugin-transform-flow-strip-types": "^7.2.0", - "random-int": "^1.0.0" - }, "browser": { "./src/generateCertificate.js": false, "./src/http-server.js": false, diff --git a/packages/core/utils/src/config.js b/packages/core/utils/src/config.js index 3c0d7e73158..0ae9aad9b9e 100644 --- a/packages/core/utils/src/config.js +++ b/packages/core/utils/src/config.js @@ -5,7 +5,7 @@ import type {FileSystem} from '@parcel/fs'; import ThrowableDiagnostic from '@parcel/diagnostic'; import path from 'path'; import clone from 'clone'; -import {parse as json5} from 'json5'; +import json5 from 'json5'; import {parse as toml} from '@iarna/toml'; import LRU from 'lru-cache'; @@ -154,6 +154,6 @@ function getParser(extname) { return toml; case 'json': default: - return json5; + return json5.parse; } } diff --git a/packages/core/utils/src/glob.js b/packages/core/utils/src/glob.js index b008830a03e..b842015f6fe 100644 --- a/packages/core/utils/src/glob.js +++ b/packages/core/utils/src/glob.js @@ -5,15 +5,26 @@ import type {FileSystem} from '@parcel/fs'; import _isGlob from 'is-glob'; import fastGlob, {type FastGlobOptions} from 'fast-glob'; -import {isMatch} from 'micromatch'; +import {isMatch, makeRe, type Options} from 'micromatch'; import {normalizeSeparators} from './path'; export function isGlob(p: FilePath): any { return _isGlob(normalizeSeparators(p)); } -export function isGlobMatch(filePath: FilePath, glob: Glob): any { - return isMatch(filePath, normalizeSeparators(glob)); +export function isGlobMatch( + filePath: FilePath, + glob: Glob | Array, + opts?: Options, +): any { + glob = Array.isArray(glob) + ? glob.map(normalizeSeparators) + : normalizeSeparators(glob); + return isMatch(filePath, glob, opts); +} + +export function globToRegex(glob: Glob, opts?: Options): RegExp { + return makeRe(glob, opts); } export function globSync( diff --git a/packages/core/utils/src/index.js b/packages/core/utils/src/index.js index c5aa3849bfc..4df6ac1adf0 100644 --- a/packages/core/utils/src/index.js +++ b/packages/core/utils/src/index.js @@ -41,7 +41,7 @@ export { export {resolveConfig, resolveConfigSync, loadConfig} from './config'; export {DefaultMap, DefaultWeakMap} from './DefaultMap'; export {makeDeferredWithPromise} from './Deferred'; -export {isGlob, isGlobMatch, globSync, glob} from './glob'; +export {isGlob, isGlobMatch, globSync, glob, globToRegex} from './glob'; export {hashStream, hashObject, hashFile} from './hash'; export {SharedBuffer} from './shared-buffer'; export {fuzzySearch} from './schema'; diff --git a/packages/core/workers/src/child.js b/packages/core/workers/src/child.js index 71fad5a1488..73da6006396 100644 --- a/packages/core/workers/src/child.js +++ b/packages/core/workers/src/child.js @@ -10,7 +10,7 @@ import type { ChildImpl, } from './types'; import type {Async, IDisposable} from '@parcel/types'; -import type {SharedReference, WorkerApi} from './WorkerFarm'; +import type {SharedReference} from './WorkerFarm'; import invariant from 'assert'; import nullthrows from 'nullthrows'; @@ -39,7 +39,6 @@ export class Child { loggerDisposable: IDisposable; child: ChildImpl; profiler: ?Profiler; - workerApi: WorkerApi; handles: Map = new Map(); sharedReferences: Map = new Map(); sharedReferencesByValue: Map = new Map(); diff --git a/packages/dev/babel-preset/index.js b/packages/dev/babel-preset/index.js index f1e2a597f5a..178a6798000 100644 --- a/packages/dev/babel-preset/index.js +++ b/packages/dev/babel-preset/index.js @@ -1,30 +1,11 @@ -module.exports = () => ({ - presets: [ - [ - require('@babel/preset-env'), - { - modules: false, - targets: { - node: 12, - }, - }, - ], - require('@babel/preset-react'), - require('@babel/preset-flow'), - ], - plugins: [ - [ - require('@babel/plugin-transform-modules-commonjs'), - { - lazy: true, - }, - ], - ], - env: { - production: { +module.exports = api => { + let name = api.caller(caller => caller && caller.name); + if (name === 'parcel') { + return { + presets: [require('@babel/preset-flow')], plugins: [ - // Inline the value of PARCEL_BUILD_ENV during production builds so that - // it can be removed through dead code elimination below + // Inline the value of PARCEL_BUILD_ENV during self builds. + // Parcel does not do this itself for node targets... [ 'babel-plugin-transform-inline-environment-variables', { @@ -38,6 +19,52 @@ module.exports = () => ({ ], 'babel-plugin-minify-dead-code-elimination', ], + }; + } + + return { + presets: [ + [ + require('@babel/preset-env'), + { + modules: false, + targets: { + node: 12, + }, + }, + ], + require('@babel/preset-react'), + require('@babel/preset-flow'), + ], + plugins: [ + [ + require('@babel/plugin-transform-modules-commonjs'), + { + lazy: true, + }, + ], + ], + env: { + production: { + plugins: [ + // Inline the value of PARCEL_BUILD_ENV during production builds so that + // it can be removed through dead code elimination below + [ + 'babel-plugin-transform-inline-environment-variables', + { + include: [ + 'PARCEL_BUILD_ENV', + // Eliminate the PARCEL_SELF_BUILD environment variable to get + // rid of @babel/register in bin.js, when compiling with gulp. + ...(!process.env.PARCEL_SELF_BUILD + ? ['PARCEL_SELF_BUILD'] + : []), + ], + }, + ], + 'babel-plugin-minify-dead-code-elimination', + ], + }, }, - }, -}); + }; +}; diff --git a/packages/packagers/css/package.json b/packages/packagers/css/package.json index a684147d75b..629d848101b 100644 --- a/packages/packagers/css/package.json +++ b/packages/packagers/css/package.json @@ -23,7 +23,9 @@ "@parcel/plugin": "2.0.15", "@parcel/source-map": "^2.0.0", "@parcel/utils": "2.0.15", - "nullthrows": "^1.1.1", + "nullthrows": "^1.1.1" + }, + "devDependencies": { "postcss": "^8.4.5" } } diff --git a/packages/packagers/css/src/CSSPackager.js b/packages/packagers/css/src/CSSPackager.js index 278d83f082b..23be7bae163 100644 --- a/packages/packagers/css/src/CSSPackager.js +++ b/packages/packagers/css/src/CSSPackager.js @@ -2,6 +2,7 @@ import type {Root} from 'postcss'; import type {Asset, Dependency} from '@parcel/types'; +import typeof PostCSS from 'postcss'; import path from 'path'; import SourceMap from '@parcel/source-map'; @@ -13,7 +14,6 @@ import { replaceURLReferences, } from '@parcel/utils'; -import postcss from 'postcss'; import nullthrows from 'nullthrows'; export default (new Packager({ @@ -161,6 +161,16 @@ async function processCSSModule( asset, media, ): Promise<[Asset, string, ?Buffer]> { + let postcss: PostCSS = await options.packageManager.require( + 'postcss', + options.projectRoot + '/index', + { + range: '^8.4.5', + saveDev: true, + shouldAutoInstall: options.shouldAutoInstall, + }, + ); + let ast: Root = postcss.fromJSON(nullthrows((await asset.getAST())?.program)); let usedSymbols = bundleGraph.getUsedSymbols(asset); diff --git a/packages/reporters/cli/package.json b/packages/reporters/cli/package.json index 94f76a7bf2d..50cf3cc0d6c 100644 --- a/packages/reporters/cli/package.json +++ b/packages/reporters/cli/package.json @@ -19,17 +19,30 @@ "node": ">= 12.0.0", "parcel": "^2.0.1" }, + "targets": { + "main": { + "includeNodeModules": { + "@parcel/plugin": false, + "@parcel/types": false, + "@parcel/utils": false, + "chalk": false, + "term-size": false + } + } + }, "dependencies": { "@parcel/plugin": "2.0.15", "@parcel/types": "2.0.15", "@parcel/utils": "2.0.15", "chalk": "^4.1.0", + "term-size": "^2.2.1" + }, + "devDependencies": { "filesize": "^6.1.0", "nullthrows": "^1.1.1", "ora": "^5.2.0", "string-width": "^4.2.0", "strip-ansi": "^6.0.0", - "term-size": "^2.2.1", "wrap-ansi": "^7.0.0" } } diff --git a/packages/reporters/dev-server/package.json b/packages/reporters/dev-server/package.json index bac38d9a301..9326072267e 100644 --- a/packages/reporters/dev-server/package.json +++ b/packages/reporters/dev-server/package.json @@ -20,18 +20,26 @@ "node": ">= 12.0.0", "parcel": "^2.0.1" }, + "targets": { + "main": { + "includeNodeModules": { + "@parcel/plugin": false, + "@parcel/utils": false + } + } + }, "dependencies": { "@parcel/plugin": "2.0.15", - "@parcel/utils": "2.0.15", + "@parcel/utils": "2.0.15" + }, + "devDependencies": { + "@parcel/babel-preset": "2.0.15", + "@parcel/types": "2.0.15", "connect": "^3.7.0", "ejs": "^3.1.6", "http-proxy-middleware": "^2.0.1", "nullthrows": "^1.1.1", "serve-handler": "^6.0.0", "ws": "^7.0.0" - }, - "devDependencies": { - "@parcel/babel-preset": "2.0.15", - "@parcel/types": "2.0.15" } } diff --git a/packages/resolvers/default/src/DefaultResolver.js b/packages/resolvers/default/src/DefaultResolver.js index 5261646adfa..419cf59ad8f 100644 --- a/packages/resolvers/default/src/DefaultResolver.js +++ b/packages/resolvers/default/src/DefaultResolver.js @@ -8,7 +8,7 @@ import NodeResolver from '@parcel/node-resolver-core'; const WEBPACK_IMPORT_REGEX = /^\w+-loader(?:\?\S*)?!/; export default (new Resolver({ - resolve({dependency, options, specifier}) { + resolve({dependency, options, specifier, logger}) { if (WEBPACK_IMPORT_REGEX.test(dependency.specifier)) { throw new Error( `The import path: ${dependency.specifier} is using webpack specific loader import syntax, which isn't supported by Parcel.`, @@ -25,6 +25,10 @@ export default (new Resolver({ ? ['ts', 'tsx', 'js', 'jsx', 'json'] : [], mainFields: ['source', 'browser', 'module', 'main'], + packageManager: options.shouldAutoInstall + ? options.packageManager + : undefined, + logger, }); return resolver.resolve({ @@ -33,6 +37,7 @@ export default (new Resolver({ parent: dependency.resolveFrom, env: dependency.env, sourcePath: dependency.sourcePath, + loc: dependency.loc, }); }, }): Resolver); diff --git a/packages/resolvers/glob/package.json b/packages/resolvers/glob/package.json index 094c7979f98..da3b6857efd 100644 --- a/packages/resolvers/glob/package.json +++ b/packages/resolvers/glob/package.json @@ -23,7 +23,6 @@ "@parcel/diagnostic": "2.0.15", "@parcel/plugin": "2.0.15", "@parcel/utils": "2.0.15", - "micromatch": "^4.0.2", "nullthrows": "^1.1.1" } } diff --git a/packages/resolvers/glob/src/GlobResolver.js b/packages/resolvers/glob/src/GlobResolver.js index e3f1ee3725d..1ccf10842ba 100644 --- a/packages/resolvers/glob/src/GlobResolver.js +++ b/packages/resolvers/glob/src/GlobResolver.js @@ -1,7 +1,12 @@ // @flow import {Resolver} from '@parcel/plugin'; -import {isGlob, glob, relativePath, normalizeSeparators} from '@parcel/utils'; -import micromatch from 'micromatch'; +import { + isGlob, + glob, + globToRegex, + relativePath, + normalizeSeparators, +} from '@parcel/utils'; import path from 'path'; import nullthrows from 'nullthrows'; import ThrowableDiagnostic from '@parcel/diagnostic'; @@ -65,7 +70,7 @@ export default (new Resolver({ let code = ''; if (sourceAssetType === 'js') { - let re = micromatch.makeRe(normalized, {capture: true}); + let re = globToRegex(normalized, {capture: true}); let matches = {}; for (let [file, relative] of results) { let match = file.match(re); diff --git a/packages/shared/babel-ast-utils/package.json b/packages/shared/babel-ast-utils/package.json deleted file mode 100644 index 2e6a11c1736..00000000000 --- a/packages/shared/babel-ast-utils/package.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "name": "@parcel/babel-ast-utils", - "version": "2.0.15", - "description": "Blazing fast, zero configuration web application bundler", - "license": "MIT", - "publishConfig": { - "access": "public" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - }, - "repository": { - "type": "git", - "url": "https://github.com/parcel-bundler/parcel.git" - }, - "main": "lib/index.js", - "source": "src/index.js", - "engines": { - "node": ">= 12.0.0" - }, - "dependencies": { - "@babel/parser": "^7.0.0", - "@parcel/babylon-walk": "2.0.15", - "@parcel/source-map": "^2.0.0", - "@parcel/utils": "2.0.15", - "astring": "^1.6.2" - } -} diff --git a/packages/shared/babel-ast-utils/src/generator.js b/packages/shared/babel-ast-utils/src/generator.js deleted file mode 100644 index 0d5a989a1b6..00000000000 --- a/packages/shared/babel-ast-utils/src/generator.js +++ /dev/null @@ -1,365 +0,0 @@ -import {GENERATOR, EXPRESSIONS_PRECEDENCE} from 'astring'; - -export const expressionsPrecedence = { - ...EXPRESSIONS_PRECEDENCE, - // Babel extensions - NumericLiteral: EXPRESSIONS_PRECEDENCE.Literal, - StringLiteral: EXPRESSIONS_PRECEDENCE.Literal, - BooleanLiteral: EXPRESSIONS_PRECEDENCE.Literal, - NullLiteral: EXPRESSIONS_PRECEDENCE.Literal, - RegExpLiteral: EXPRESSIONS_PRECEDENCE.Literal, - BigIntLiteral: EXPRESSIONS_PRECEDENCE.Literal, - OptionalMemberExpression: EXPRESSIONS_PRECEDENCE.MemberExpression, - OptionalCallExpression: EXPRESSIONS_PRECEDENCE.CallExpression, - Import: EXPRESSIONS_PRECEDENCE.Identifier, - PrivateName: EXPRESSIONS_PRECEDENCE.Identifier, -}; - -// Convert Babel's AST format to ESTree on the fly. -// See https://babeljs.io/docs/en/babel-parser#output -export const generator = { - ...GENERATOR, - Program(node, state) { - // Monkeypatch state to fix sourcemap filenames. - let map = state.map; - state.map = (str, node) => { - if (node != null && node.loc != null) { - state.mapping.source = node.loc.filename; - } - map.call(state, str, node); - }; - - if (node.interpreter) { - state.write(`#!${node.interpreter.value}\n`); - } - - handleDirectives(node); - GENERATOR.Program.call(this, node, state); - }, - BlockStatement(node, state) { - handleDirectives(node); - GENERATOR.BlockStatement.call(this, node, state); - }, - NumericLiteral(node, state) { - node.type = 'Literal'; - node.raw = getRaw(node); - this.Literal(node, state, true); - }, - StringLiteral(node, state) { - node.type = 'Literal'; - node.raw = getRaw(node); - this.Literal(node, state, true); - }, - BooleanLiteral(node, state) { - node.type = 'Literal'; - this.Literal(node, state, true); - }, - NullLiteral(node, state) { - node.type = 'Literal'; - node.raw = 'null'; - node.value = null; - this.Literal(node, state, true); - }, - RegExpLiteral(node, state) { - node.type = 'Literal'; - node.raw = getRaw(node); - node.value = {}; - node.regex = { - pattern: node.pattern, - flags: node.flags, - }; - GENERATOR.Literal(node, state); - }, - BigIntLiteral(node, state) { - node.type = 'Literal'; - node.raw = getRaw(node); - this.Literal(node, state, true); - }, - ArrowFunctionExpression(node, state) { - if ( - node.body.type === 'OptionalMemberExpression' || - node.body.type === 'OptionalCallExpression' - ) { - // the ArrowFunctionExpression visitor in astring checks the type of the body - // Make sure they don't start with "O" - node.body.type = '_' + node.body.type; - } - GENERATOR.ArrowFunctionExpression.call(this, node, state); - }, - ObjectProperty(node, state) { - node.type = 'Property'; - node.kind = 'init'; - if (node.shorthand) { - let id = - node.value.type === 'Identifier' - ? node.value - : node.value.type === 'AssignmentPattern' && - node.value.left.type === 'Identifier' - ? node.value.left - : null; - if (!id || id.name !== node.key.name) { - node.shorthand = false; - } - } - this.Property(node, state, true); - }, - ObjectMethod(node, state) { - node.value = { - type: 'FunctionExpression', - id: node.id, - params: node.params, - body: node.body, - async: node.async, - generator: node.generator, - expression: node.expression, - }; - - node.type = 'Property'; - if (node.kind === 'method') { - node.kind = 'init'; - } - - this.Property(node, state, true); - }, - ClassMethod(node, state) { - node.value = { - type: 'FunctionExpression', - id: node.id, - params: node.params, - body: node.body, - async: node.async, - generator: node.generator, - expression: node.expression, - }; - - node.type = 'MethodDefinition'; - this.MethodDefinition(node, state, true); - }, - ClassPrivateMethod(node, state) { - node.value = { - type: 'FunctionExpression', - id: node.id, - params: node.params, - body: node.body, - async: node.async, - generator: node.generator, - expression: node.expression, - }; - - node.type = 'MethodDefinition'; - this.MethodDefinition(node, state, true); - }, - ClassProperty(node, state) { - if (node.static) { - state.write('static '); - } - - if (node.computed) { - state.write('['); - this[node.key.type](node.key, state); - state.write(']'); - } else { - this[node.key.type](node.key, state); - } - - if (node.value) { - state.write(' = '); - this[node.value.type](node.value, state, true); - } - - state.write(';'); - }, - ClassPrivateProperty(node, state) { - if (node.static) { - state.write('static '); - } - - this[node.key.type](node.key, state); - if (node.value) { - state.write(' = '); - this[node.value.type](node.value, state); - } - - state.write(';'); - }, - PrivateName(node, state) { - state.write('#' + node.name, node); - }, - Import(node, state) { - // astring doesn't support ImportExpression yet - state.write('import'); - }, - _OptionalMemberExpression(node, state) { - this.OptionalMemberExpression(node, state, true); - }, - OptionalMemberExpression(node, state) { - node.optional = true; - node.type = 'MemberExpression'; - GENERATOR.MemberExpression.call(this, node, state); - }, - MemberExpression(node, state) { - if (node.optional) node.optional = false; - GENERATOR.MemberExpression.call(this, node, state); - }, - _OptionalCallExpression(node, state) { - this.OptionalCallExpression(node, state, true); - }, - OptionalCallExpression(node, state) { - node.optional = true; - node.type = 'CallExpression'; - GENERATOR.CallExpression.call(this, node, state); - }, - CallExpression(node, state) { - if (node.optional) node.optional = false; - GENERATOR.CallExpression.call(this, node, state); - }, - ExportNamedDeclaration(node, state) { - if (node.source) { - let namespace = node.specifiers.find( - specifier => specifier.type === 'ExportNamespaceSpecifier', - ); - if (namespace) { - // Babel parser allows combining namespace specifiers and named specifiers - // e.g. `export * as foo, {bar} from 'other'`, but this is not supported by the spec. - if (node.specifiers.length > 1) { - throw new Error( - 'Namespace specifiers cannot be combined with named specifiers', - ); - } - - node.type = 'ExportAllDeclaration'; - node.exported = namespace.exported; - } - } - - GENERATOR[node.type].call(this, node, state); - }, - ReturnStatement(node, state) { - // Add parentheses if there are leading comments - if (node.argument?.leadingComments?.length > 0) { - let indent = state.indent.repeat(state.indentLevel); - state.write('return (' + state.lineEnd); - state.write(indent + state.indent); - state.indentLevel++; - this[node.argument.type](node.argument, state); - state.indentLevel--; - state.write(state.lineEnd); - state.write(indent + ');'); - } else { - GENERATOR.ReturnStatement.call(this, node, state); - } - }, - ThrowStatement(node, state) { - // Add parentheses if there are leading comments - if (node.argument?.leadingComments?.length > 0) { - let indent = state.indent.repeat(state.indentLevel); - state.write('throw (' + state.lineEnd); - state.write(indent + state.indent); - state.indentLevel++; - this[node.argument.type](node.argument, state); - state.indentLevel--; - state.write(state.lineEnd); - state.write(indent + ');'); - } else { - GENERATOR.ThrowStatement.call(this, node, state); - } - }, -}; - -// Make every node support comments. Important for preserving /*@__PURE__*/ comments for terser. -// TODO: contribute to astring. -for (let key in generator) { - let orig = generator[key]; - generator[key] = function (node, state, skipComments) { - // These are printed by astring itself - if (node.trailingComments) { - for (let c of node.trailingComments) { - if (c.type === 'CommentLine' || c.type === 'LineComment') { - c.type = 'LineComment'; - } else { - c.type = 'BlockComment'; - } - } - } - if ( - !skipComments && - node.leadingComments && - node.leadingComments.length > 0 - ) { - formatComments(state, node.leadingComments); - } - orig.call(this, node, state); - }; -} - -function handleDirectives(node) { - if (node.directives) { - for (var i = node.directives.length - 1; i >= 0; i--) { - var directive = node.directives[i]; - directive.type = 'ExpressionStatement'; - directive.expression = directive.value; - directive.expression.type = 'Literal'; - node.body.unshift(directive); - } - } -} - -// Copied from the astring source. -function formatComments(state, comments) { - // Writes into `state` the provided list of `comments`, with the given `indent` and `lineEnd` strings. - // Line comments will end with `"\n"` regardless of the value of `lineEnd`. - // Expects to start on a new unindented line. - const indent = state.indent.repeat(state.indentLevel); - const {length} = comments; - for (let i = 0; i < length; i++) { - const comment = comments[i]; - if (comment.type === 'CommentLine' || comment.type === 'LineComment') { - // Line comment - state.write('// ' + comment.value.trim() + state.lineEnd, { - ...comment, - type: 'LineComment', - }); - state.write(indent); - } else { - // Block comment - state.write('/*'); - reindent(state, comment.value, indent, state.lineEnd); - state.write('*/'); - - // Keep pure annotations on the same line - let value = comment.value.trim(); - if ( - !((value === '#__PURE__' || value === '@__PURE__') && i === length - 1) - ) { - state.write(state.lineEnd); - state.write(indent); - } - } - } -} - -function reindent(state, text, indent, lineEnd) { - // Writes into `state` the `text` string reindented with the provided `indent`. - const lines = text.split('\n'); - const end = lines.length - 1; - state.write(lines[0].trim()); - if (end > 0) { - state.write(lineEnd); - for (let i = 1; i < end; i++) { - state.write(indent + lines[i].trim() + lineEnd); - } - state.write(indent + lines[end].trim()); - } -} - -function getRaw(node) { - let extra = node.extra; - if ( - extra && - extra.raw != null && - extra.rawValue != null && - node.value === extra.rawValue - ) { - return extra.raw; - } -} diff --git a/packages/shared/babel-ast-utils/src/index.js b/packages/shared/babel-ast-utils/src/index.js deleted file mode 100644 index ba68ae25882..00000000000 --- a/packages/shared/babel-ast-utils/src/index.js +++ /dev/null @@ -1,209 +0,0 @@ -// @flow strict-local - -import type { - AST, - BaseAsset, - PluginOptions, - SourceLocation, - FilePath, -} from '@parcel/types'; -import type { - SourceLocation as BabelSourceLocation, - File as BabelNodeFile, -} from '@babel/types'; - -import path from 'path'; -import {parse as babelParse, type ParserPlugin} from '@babel/parser'; -import SourceMap from '@parcel/source-map'; -import {relativeUrl} from '@parcel/utils'; -import {traverseAll} from '@parcel/babylon-walk'; -import {babelErrorEnhancer} from './babelErrorUtils'; -// $FlowFixMe -import {generate as astringGenerate} from 'astring'; -// $FlowFixMe -import {generator, expressionsPrecedence} from './generator'; - -export {babelErrorEnhancer}; - -export function remapAstLocations(ast: BabelNodeFile, map: SourceMap) { - // remap ast to original mappings - // This improves sourcemap accuracy and fixes sourcemaps when scope-hoisting - traverseAll(ast.program, node => { - if (node.loc) { - if (node.loc?.start) { - let mapping = map.findClosestMapping( - node.loc.start.line, - node.loc.start.column, - ); - - if (mapping?.original) { - // $FlowFixMe - node.loc.start.line = mapping.original.line; - // $FlowFixMe - node.loc.start.column = mapping.original.column; - - // $FlowFixMe - let length = node.loc.end.column - node.loc.start.column; - - // $FlowFixMe - node.loc.end.line = mapping.original.line; - // $FlowFixMe - node.loc.end.column = mapping.original.column + length; - - // $FlowFixMe - node.loc.filename = mapping.source; - } else { - // Maintain null mappings? - node.loc = null; - } - } - } - }); -} - -export async function parse({ - asset, - code, - options, - // ATLASSIAN: allow additional plugins for the parser - plugins: additionalPlugins = [], -}: {| - asset: BaseAsset, - code: string, - options: PluginOptions, - // ATLASSIAN: allow additional plugins for the parser - plugins?: Array, -|}): Promise { - try { - const plugins = [ - 'exportDefaultFrom', - 'exportNamespaceFrom', - 'dynamicImport', - // ATLASSIAN: allow additional plugins for the parser - ...additionalPlugins, - ]; - - let program = babelParse(code, { - sourceFilename: relativeUrl(options.projectRoot, asset.filePath), - allowReturnOutsideFunction: true, - strictMode: false, - sourceType: 'module', - plugins, - }); - - let map = await asset.getMap(); - if (map) { - remapAstLocations(program, map); - } - - return { - type: 'babel', - version: '7.0.0', - program, - }; - } catch (e) { - throw await babelErrorEnhancer(e, asset); - } -} - -// astring is ~50x faster than @babel/generator. We use it with a custom -// generator to handle the Babel AST differences from ESTree. -export function generateAST({ - ast, - sourceFileName, - sourceMaps, - options, -}: {| - ast: BabelNodeFile, - sourceFileName?: FilePath, - sourceMaps?: boolean, - options: PluginOptions, -|}): {|content: string, map: SourceMap|} { - let map = new SourceMap(options.projectRoot); - let mappings = []; - let generated = astringGenerate(ast.program, { - generator, - expressionsPrecedence, - comments: true, - sourceMap: sourceMaps - ? { - file: sourceFileName, - addMapping(mapping) { - // Copy the object because astring mutates it - mappings.push({ - original: mapping.original, - generated: { - line: mapping.generated.line, - column: mapping.generated.column, - }, - name: mapping.name, - source: mapping.source, - }); - }, - } - : null, - }); - - map.addIndexedMappings(mappings); - - return { - content: generated, - map, - }; -} - -export async function generate({ - asset, - ast, - options, -}: {| - asset: BaseAsset, - ast: AST, - options: PluginOptions, -|}): Promise<{|content: string, map: ?SourceMap|}> { - let sourceFileName: string = relativeUrl(options.projectRoot, asset.filePath); - let {content, map} = generateAST({ - ast: ast.program, - sourceFileName, - sourceMaps: !!asset.env.sourceMap, - options, - }); - - let originalSourceMap = await asset.getMap(); - if (originalSourceMap) { - // The babel AST already contains the correct mappings, but not the source contents. - // We need to copy over the source contents from the original map. - let sourcesContent = originalSourceMap.getSourcesContentMap(); - for (let filePath in sourcesContent) { - let content = sourcesContent[filePath]; - if (content != null) { - map.setSourceContent(filePath, content); - } - } - } - - return {content, map}; -} - -export function convertBabelLoc( - options: PluginOptions, - loc: ?BabelSourceLocation, -): ?SourceLocation { - if (!loc) return null; - let {filename, start, end} = loc; - if (filename == null) return null; - return { - filePath: path.resolve(options.projectRoot, filename), - start: { - line: start.line, - column: start.column + 1, - }, - // - Babel's columns are exclusive, ours are inclusive (column - 1) - // - Babel has 0-based columns, ours are 1-based (column + 1) - // = +-0 - end: { - line: end.line, - column: end.column, - }, - }; -} diff --git a/packages/shared/babel-ast-utils/test/fixtures/array.js b/packages/shared/babel-ast-utils/test/fixtures/array.js deleted file mode 100644 index 92733c8b1de..00000000000 --- a/packages/shared/babel-ast-utils/test/fixtures/array.js +++ /dev/null @@ -1,4 +0,0 @@ -let a = []; -let b = [42]; -let c = [42, 7]; -let [d, ...e] = [1, 2, 3, 4, 5]; diff --git a/packages/shared/babel-ast-utils/test/fixtures/async.js b/packages/shared/babel-ast-utils/test/fixtures/async.js deleted file mode 100644 index 0cc14c0ea34..00000000000 --- a/packages/shared/babel-ast-utils/test/fixtures/async.js +++ /dev/null @@ -1,17 +0,0 @@ -async function f() {} -const g = async function () {}; -const a = { - async f() {} -}; -const h = async () => {}; -async function j() { - (await g()).a; - await g().a; - return await f(); -} -async function k() { - return await (obj = Promise.resolve(1)); -} -async function l() { - await (() => 1); -} diff --git a/packages/shared/babel-ast-utils/test/fixtures/call.js b/packages/shared/babel-ast-utils/test/fixtures/call.js deleted file mode 100644 index c0d71059a38..00000000000 --- a/packages/shared/babel-ast-utils/test/fixtures/call.js +++ /dev/null @@ -1,16 +0,0 @@ -f(); -g(a); -h(a, b); -i(a, b, ...c); -j(...a); -a.k(); -(a + b).l(); -a.m().n(); -new A(); -new A(a); -new a.B(); -new a.b.C(); -new (a().B)(); -new A().b(); -new new A()(); -new (A, B)(); diff --git a/packages/shared/babel-ast-utils/test/fixtures/class.js b/packages/shared/babel-ast-utils/test/fixtures/class.js deleted file mode 100644 index bd2d67268d4..00000000000 --- a/packages/shared/babel-ast-utils/test/fixtures/class.js +++ /dev/null @@ -1,40 +0,0 @@ -class A { - constructor() {} -} -class B extends A {} -class C extends A { - method() {} - get property() { - return this._property; - } - // /* foo */ - set property(value) { - this._property = value; - } -} -class D extends class A {} {} -class E extends class { - constructor() {} -} {} -class F extends class { - constructor() {} -} { - constructor() {} -} -class G { - [Symbol.iterator]() {} - ["method"]() {} -} -class H { - static classMethod() {} - method() {} -} -class I { - static get property() {} - static set property(value) {} -} -class J extends A { - constructor() { - super(); - } -} diff --git a/packages/shared/babel-ast-utils/test/fixtures/control.js b/packages/shared/babel-ast-utils/test/fixtures/control.js deleted file mode 100644 index cb2d14d58a1..00000000000 --- a/packages/shared/babel-ast-utils/test/fixtures/control.js +++ /dev/null @@ -1,38 +0,0 @@ -throw ( - /*comment*/ - new Error("abc") -); -if (a > b) {} else {} -if (c != d) {} -var a = b > c ? d : e; -let b = (c = 1) ? d : e; -switch (a) { - case b: - break; - case "c": - break; - case 42: - break; - case d: - if (a < b) {} - break; - default: - break; -} -while (a > b) { - if (c == d) { - break; - } -} -do { - if (e === f) { - continue; - } -} while (g < h); -label: if (a === b) { - if (b = c) { - break label; - } -} -if (a != b) {} -endingLabel: {} diff --git a/packages/shared/babel-ast-utils/test/fixtures/error.js b/packages/shared/babel-ast-utils/test/fixtures/error.js deleted file mode 100644 index c4b78eca481..00000000000 --- a/packages/shared/babel-ast-utils/test/fixtures/error.js +++ /dev/null @@ -1,13 +0,0 @@ -try { - let a = 42; -} catch (error) { - let b = error; -} -try { - let a = 42; -} catch (error) { - let b = error; -} finally { - let c = "done"; -} -throw new Error("this is an error"); diff --git a/packages/shared/babel-ast-utils/test/fixtures/export-class.js b/packages/shared/babel-ast-utils/test/fixtures/export-class.js deleted file mode 100644 index a6e68e98389..00000000000 --- a/packages/shared/babel-ast-utils/test/fixtures/export-class.js +++ /dev/null @@ -1 +0,0 @@ -export default class {} diff --git a/packages/shared/babel-ast-utils/test/fixtures/export-function.js b/packages/shared/babel-ast-utils/test/fixtures/export-function.js deleted file mode 100644 index ea9b101e1c2..00000000000 --- a/packages/shared/babel-ast-utils/test/fixtures/export-function.js +++ /dev/null @@ -1 +0,0 @@ -export default function () {} diff --git a/packages/shared/babel-ast-utils/test/fixtures/export.js b/packages/shared/babel-ast-utils/test/fixtures/export.js deleted file mode 100644 index 9487783d729..00000000000 --- a/packages/shared/babel-ast-utils/test/fixtures/export.js +++ /dev/null @@ -1,11 +0,0 @@ -export * from "module"; -export * as m from "module"; -export {name} from "module"; -export {a as b, c as d} from "module"; -let e, g; -export {e as f, g as h}; -export {}; -export default i = 42; -export var j = 42; -export let k = 42; -export function l() {} diff --git a/packages/shared/babel-ast-utils/test/fixtures/function.js b/packages/shared/babel-ast-utils/test/fixtures/function.js deleted file mode 100644 index 25386e7cf8d..00000000000 --- a/packages/shared/babel-ast-utils/test/fixtures/function.js +++ /dev/null @@ -1,53 +0,0 @@ -function f(a, b, c) { - return null; -} -var g = function (a, b, c) { - return null; -}; -function h(a, b = 1, c = 2) { - return null; -} -function i(a = 1, b, c) { - return null; -} -function j(...a) {} -function k() {} -var l = function () {}; -var m = function (a = 1, b, c) {}; -function* o() { - yield 42; -} -function* p() { - yield 42; - yield 7; - return "answer"; -} -let q = function* () {}; -let r = a => a; -let s = (a, b) => a + b; -let t = (a, b = 0) => a + b; -let u = (a, b) => {}; -let v = () => {}; -let w = () => ({}); -let x = () => { - let a = 42; - return a; -}; -let y = () => ({ - a: 1, - b: 2 -}); -let z = a => a?.b; -let za = a => a?.(); -let zb = a => 1; -function zc() { - function a() { - return ( - // comment - null - ); - console.log(2); - } - // abc - console.log(1); -} diff --git a/packages/shared/babel-ast-utils/test/fixtures/import.js b/packages/shared/babel-ast-utils/test/fixtures/import.js deleted file mode 100644 index 57903a23734..00000000000 --- a/packages/shared/babel-ast-utils/test/fixtures/import.js +++ /dev/null @@ -1,8 +0,0 @@ -import a from "module"; -import b, * as c from "module"; -import * as d from "module"; -import e, {f as g, h as i, j} from "module"; -import {k as l, m} from "module"; -import {n, o as p} from "module"; -import("module"); -const x = import("module"); diff --git a/packages/shared/babel-ast-utils/test/fixtures/literal.js b/packages/shared/babel-ast-utils/test/fixtures/literal.js deleted file mode 100644 index 658bd0b25c6..00000000000 --- a/packages/shared/babel-ast-utils/test/fixtures/literal.js +++ /dev/null @@ -1,6 +0,0 @@ -const a = Infinity; -const b = -Infinity; -const c = +Infinity; -const d = /abc/; -const e = /abc/g; -const f = /abc/gi; diff --git a/packages/shared/babel-ast-utils/test/fixtures/loop.js b/packages/shared/babel-ast-utils/test/fixtures/loop.js deleted file mode 100644 index 3514482dd56..00000000000 --- a/packages/shared/babel-ast-utils/test/fixtures/loop.js +++ /dev/null @@ -1,21 +0,0 @@ -for (let a in b) {} -for (let [a, b] in c) {} -for (let {a, b} in c) {} -for (let {a: b, c} in d) {} -for (let a of b) {} -for (var [a, b] of c) {} -for (let {a, b} in c) {} -for (let {a: b, c} in d) {} -for (let i = 0, {length} = list; i < length; i++) {} -for (; ; ) {} -for (function () { - const i = 0; -}; ; ) {} -for (() => { - const i = 0; -}; ; ) {} -async function test() { - for await (const x of xs) { - x(); - } -} diff --git a/packages/shared/babel-ast-utils/test/fixtures/number.js b/packages/shared/babel-ast-utils/test/fixtures/number.js deleted file mode 100644 index 262df88d3a6..00000000000 --- a/packages/shared/babel-ast-utils/test/fixtures/number.js +++ /dev/null @@ -1,3 +0,0 @@ -let a; -a = 1n; -a = 1; diff --git a/packages/shared/babel-ast-utils/test/fixtures/object.js b/packages/shared/babel-ast-utils/test/fixtures/object.js deleted file mode 100644 index c1c6731ab83..00000000000 --- a/packages/shared/babel-ast-utils/test/fixtures/object.js +++ /dev/null @@ -1,30 +0,0 @@ -let a = {}; -let b = { - "1": "one", - "2": "two", - "3": "three" -}; -let c = { - [42]: "answer", - [7]: "lucky" -}; -let d = { - a: 1, - b: 2, - c: 3 -}; -let e = d.a; -let f = d["c"]; -let g = { - m() {}, - ['n'](a) {}, - o(a) { - return a; - } -}; -let h = ({}).toString(); -let i = { - ...d, - a -}; -a?.['b']?.[0]?.(1); diff --git a/packages/shared/babel-ast-utils/test/fixtures/operators.js b/packages/shared/babel-ast-utils/test/fixtures/operators.js deleted file mode 100644 index cfadff3c64c..00000000000 --- a/packages/shared/babel-ast-utils/test/fixtures/operators.js +++ /dev/null @@ -1,33 +0,0 @@ -let a, b, c, d; -a = a || (a = 2); -a ||= 2; -a = a && (a = 2); -a &&= 2; -a = a ?? (a = 2); -a ??= 2; -b = 1 + 2; -b = 1 - 2; -b = 1 / 2; -b = 1 * 2; -c = 2 ** 1; -c = 1 % 2; -d = 1 << 2; -d = 1 >> 2; -d = 1 >>> 2; -d = 1 & 3; -d = 1 ^ 3; -d = 1 | 3; -a == b; -a === b; -a != b; -a !== b; -a > b; -a >= b; -a < b; -a <= b; -++a; -a++; -+a; --a; ---a; -a--; diff --git a/packages/shared/babel-ast-utils/test/fixtures/precedence.js b/packages/shared/babel-ast-utils/test/fixtures/precedence.js deleted file mode 100644 index abfcb6e2377..00000000000 --- a/packages/shared/babel-ast-utils/test/fixtures/precedence.js +++ /dev/null @@ -1,34 +0,0 @@ -var a, b, c, d, e, f, g, x, y, z; -a = 1 + 2 * 3 / 5; -b = (1 + 2) * 3 / 5; -c = (1 + 2) * (3 - 5); -d = x | y ^ z; -e = (x | y) ^ z; -f = "a" + (1 + 2) + "b"; -g = "a" + (1 - 2) + "b"; -a = true || false && null; -b = c == d || e != f; -c = x instanceof y || x instanceof z; -d = x == y && y != z; -a = !false; -b = !x instanceof Number; -c = !(x instanceof Number); -d = typeof a === 'boolean'; -e = !typeof a === 'boolean'; -f = !(typeof a === 'boolean'); -a = (1.1).toString(); -a = (1).toString(); -b = new A().toString(); -c = new x.A().toString(); -d = new x.y().z(); -var r = (/ab+c/i).exec('abc'); -a = b ** 2 * 3; -c = (d ** 2) ** 3; -e = f ** 2 ** 3; -e = (+2) ** 3; -e = 2 ** +3; -f = a + (b = 3); -g = 1 && (() => {}); -g = (() => {}) && 1; -g = (1, + +2); -g = (1, + +(2 + 3)); diff --git a/packages/shared/babel-ast-utils/test/fixtures/sequence.js b/packages/shared/babel-ast-utils/test/fixtures/sequence.js deleted file mode 100644 index 7e1dd060e88..00000000000 --- a/packages/shared/babel-ast-utils/test/fixtures/sequence.js +++ /dev/null @@ -1,4 +0,0 @@ -let a = (x => (x, x * 2), 3); -let b = ((x, y) => (x, x * y), 1); -let c = (x => x * x)(2); -let d = (1, 2, 3); diff --git a/packages/shared/babel-ast-utils/test/fixtures/template.js b/packages/shared/babel-ast-utils/test/fixtures/template.js deleted file mode 100644 index 28777d2e6df..00000000000 --- a/packages/shared/babel-ast-utils/test/fixtures/template.js +++ /dev/null @@ -1,10 +0,0 @@ -let a; -let b = `this is a template`; -let c = `this is a template\ -with multiple -lines`; -let d = f`template with function`; -let e = f`template with ${some} ${variables}`; -let f = f`template with ${some}${variables}${attached}`; -let g = f()`template with function call before`; -let h = f().g`template with more complex function call`; diff --git a/packages/shared/babel-ast-utils/test/fixtures/valid-only.js b/packages/shared/babel-ast-utils/test/fixtures/valid-only.js deleted file mode 100644 index c24133a9e13..00000000000 --- a/packages/shared/babel-ast-utils/test/fixtures/valid-only.js +++ /dev/null @@ -1,10 +0,0 @@ -// These are currently not correctly reproduced, but should still -// remain syntactically valid. - -if (1) { - a(); -} -// /* */ -else { - b(); -} diff --git a/packages/shared/babel-ast-utils/test/fixtures/variable.js b/packages/shared/babel-ast-utils/test/fixtures/variable.js deleted file mode 100644 index d1668abd6d2..00000000000 --- a/packages/shared/babel-ast-utils/test/fixtures/variable.js +++ /dev/null @@ -1,11 +0,0 @@ -var a; -let b = 42; -const c = 21 * 2; -let {e} = d; -var f, g = 42, h = false; -let {i, j: k} = l; -let [m, n] = c; -var {a: [o, {p}]} = d; -let {q = 42} = f; -const {g: r = 42} = i; -const {s, ...t} = r; diff --git a/packages/shared/babel-ast-utils/test/index.js b/packages/shared/babel-ast-utils/test/index.js deleted file mode 100644 index 3919e0efba8..00000000000 --- a/packages/shared/babel-ast-utils/test/index.js +++ /dev/null @@ -1,42 +0,0 @@ -import fs from 'fs'; -import path from 'path'; -import assert from 'assert'; -import {parse as babelParse} from '@babel/parser'; -import {generateAST} from '../src'; - -const FIXTURES_FOLDER = path.join(__dirname, 'fixtures'); -const files = fs.readdirSync(FIXTURES_FOLDER).sort(); -const options = { - allowReturnOutsideFunction: true, - strictMode: false, - sourceType: 'module', -}; - -describe('astring babel generator', () => { - files.forEach(filename => { - it(filename, function () { - const code = fs.readFileSync( - path.join(FIXTURES_FOLDER, filename), - 'utf8', - ); - const ast = babelParse(code, options); - let {content} = generateAST({ - ast, - sourceFileName: '/foo/bar.js', - sourceMaps: false, - originalSourceMap: null, - options: {projectRoot: '/foo'}, - }); - if (filename === 'valid-only.js') { - babelParse(content), options; - } else { - assert.equal( - content, - code, - filename.substring(0, filename.length - 3), - 'Generates code with the expected format', - ); - } - }); - }); -}); diff --git a/packages/transformers/babel/package.json b/packages/transformers/babel/package.json index b5a07607a0d..5be95e49418 100644 --- a/packages/transformers/babel/package.json +++ b/packages/transformers/babel/package.json @@ -20,18 +20,11 @@ "parcel": "^2.0.1" }, "dependencies": { - "@babel/core": "^7.12.0", - "@babel/generator": "^7.9.0", - "@babel/helper-compilation-targets": "^7.8.4", - "@babel/plugin-transform-flow-strip-types": "^7.0.0", - "@babel/traverse": "^7.0.0", - "@parcel/babel-ast-utils": "2.0.15", "@parcel/diagnostic": "2.0.15", "@parcel/plugin": "2.0.15", "@parcel/source-map": "^2.0.0", "@parcel/utils": "2.0.15", "browserslist": "^4.6.6", - "core-js": "^3.2.1", "json5": "^2.2.0", "nullthrows": "^1.1.1", "semver": "^5.7.0" @@ -39,6 +32,7 @@ "devDependencies": { "@babel/core": "^7.12.0", "@babel/preset-env": "^7.0.0", + "@babel/types": "^7.12.0", "@parcel/types": "2.0.15" } } diff --git a/packages/transformers/babel/src/BabelTransformer.js b/packages/transformers/babel/src/BabelTransformer.js index 40e1fcc93d5..c3db3c56956 100644 --- a/packages/transformers/babel/src/BabelTransformer.js +++ b/packages/transformers/babel/src/BabelTransformer.js @@ -1,11 +1,10 @@ // @flow strict-local -import {babelErrorEnhancer} from '@parcel/babel-ast-utils'; +import {babelErrorEnhancer} from './babelErrorUtils'; import {Transformer} from '@parcel/plugin'; import {relativeUrl} from '@parcel/utils'; import SourceMap from '@parcel/source-map'; import semver from 'semver'; -import generate from '@babel/generator'; import babel7 from './babel7'; import {load} from './config'; @@ -48,6 +47,22 @@ export default (new Transformer({ options.projectRoot, asset.filePath, ); + + const babelCorePath = await options.packageManager.resolve( + '@babel/core', + asset.filePath, + { + range: '^7.12.0', + saveDev: true, + shouldAutoInstall: options.shouldAutoInstall, + }, + ); + + const {default: generate} = await options.packageManager.require( + '@babel/generator', + babelCorePath.resolved, + ); + let {code, rawMappings} = generate(ast.program, { sourceFileName, sourceMaps: !!asset.env.sourceMap, diff --git a/packages/transformers/babel/src/astConverter.js b/packages/transformers/babel/src/astConverter.js deleted file mode 100644 index 2b100413c68..00000000000 --- a/packages/transformers/babel/src/astConverter.js +++ /dev/null @@ -1,102 +0,0 @@ -import traverse from '@babel/traverse'; - -// Convert between babel 7 and babel 6 AST -// More info on the AST Changes: https://babeljs.io/docs/en/v7-migration-api#ast-changes -export function babel7toBabel6(ast) { - const visitor = { - ArrowFunctionExpression: node => { - node.expression = node.body.type !== 'BlockStatement'; - }, - ExistsTypeAnnotation: node => { - node.type = 'ExistentialTypeParam'; - }, - NumberLiteralTypeAnnotation: node => { - node.type = 'NumericLiteralTypeAnnotation'; - }, - ObjectTypeIndexer: node => { - node.end++; - node.loc.end.column++; - }, - ForOfStatement: node => { - node.type = 'ForAwaitStatement'; - delete node.await; - }, - SpreadElement: (node, path) => { - if ( - path.parentPath.isObjectExpression() || - path.parentPath.isArrayExpression() - ) { - node.type = 'SpreadProperty'; - } - }, - RestElement: (node, path) => { - if ( - path.parentPath.isObjectPattern() || - path.parentPath.isArrayPattern() - ) { - node.type = 'RestProperty'; - } - }, - }; - - traverse(ast, { - enter(path) { - if (path.node.variance && path.node.variance.type === 'Variance') { - path.node.variance = path.node.variance.kind; - } - - let visitorFunc = visitor[path.node.type]; - if (visitorFunc) { - visitorFunc(path.node, path); - } - }, - }); - - return ast; -} - -export function babel6toBabel7(ast) { - const visitor = { - ArrowFunctionExpression: node => { - delete node.expression; - }, - ExistentialTypeParam: node => { - node.type = 'ExistsTypeAnnotation'; - }, - NumericLiteralTypeAnnotation: node => { - node.type = 'NumberLiteralTypeAnnotation'; - }, - ObjectTypeIndexer: node => { - node.end--; - node.loc.end.column--; - }, - ForAwaitStatement: node => { - node.type = 'ForOfStatement'; - node.await = true; - }, - SpreadProperty: node => { - node.type = 'SpreadElement'; - }, - RestProperty: node => { - node.type = 'RestElement'; - }, - }; - - traverse(ast, { - enter(path) { - if (path.node.variance && typeof path.node.variance === 'string') { - path.node.variance = { - type: 'VarianceNode', - kind: path.node.variance, - }; - } - - let visitorFunc = visitor[path.node.type]; - if (visitorFunc) { - visitorFunc(path.node); - } - }, - }); - - return ast; -} diff --git a/packages/transformers/babel/src/babel7.js b/packages/transformers/babel/src/babel7.js index 74382df053f..ab526eb00d9 100644 --- a/packages/transformers/babel/src/babel7.js +++ b/packages/transformers/babel/src/babel7.js @@ -1,11 +1,11 @@ // @flow import type {MutableAsset, AST, PluginOptions} from '@parcel/types'; +import typeof * as BabelCore from '@babel/core'; import invariant from 'assert'; -import * as internalBabelCore from '@babel/core'; import {relativeUrl} from '@parcel/utils'; -import {remapAstLocations} from '@parcel/babel-ast-utils'; +import {remapAstLocations} from './remapAstLocations'; import packageJson from '../package.json'; @@ -23,13 +23,15 @@ export default async function babel7( opts: Babel7TransformOptions, ): Promise { let {asset, options, babelOptions, additionalPlugins = []} = opts; - const babelCore = babelOptions.internal - ? internalBabelCore - : await options.packageManager.require('@babel/core', asset.filePath, { - range: '^7.12.0', - saveDev: true, - shouldAutoInstall: options.shouldAutoInstall, - }); + const babelCore: BabelCore = await options.packageManager.require( + '@babel/core', + asset.filePath, + { + range: '^7.12.0', + saveDev: true, + shouldAutoInstall: options.shouldAutoInstall, + }, + ); let config = { ...babelOptions.config, @@ -77,7 +79,7 @@ export default async function babel7( if (res.ast) { let map = await asset.getMap(); if (map) { - remapAstLocations(res.ast, map); + remapAstLocations(babelCore.types, res.ast, map); } } } diff --git a/packages/shared/babel-ast-utils/src/babelErrorUtils.js b/packages/transformers/babel/src/babelErrorUtils.js similarity index 100% rename from packages/shared/babel-ast-utils/src/babelErrorUtils.js rename to packages/transformers/babel/src/babelErrorUtils.js diff --git a/packages/transformers/babel/src/config.js b/packages/transformers/babel/src/config.js index 13e0352ce98..15f858400e0 100644 --- a/packages/transformers/babel/src/config.js +++ b/packages/transformers/babel/src/config.js @@ -7,16 +7,15 @@ import type {BabelConfig} from './types'; import json5 from 'json5'; import path from 'path'; -import * as internalBabelCore from '@babel/core'; import {hashObject, relativePath, resolveConfig} from '@parcel/utils'; import {md, generateJSONCodeHighlights} from '@parcel/diagnostic'; +import {BABEL_CORE_RANGE} from './constants'; import isJSX from './jsx'; import getFlowOptions from './flow'; import {enginesToBabelTargets} from './utils'; const TYPESCRIPT_EXTNAME_RE = /\.tsx?$/; -const BABEL_TRANSFORMER_DIR = path.dirname(__dirname); const JS_EXTNAME_RE = /^\.(js|cjs|mjs)$/; const BABEL_CONFIG_FILENAMES = [ '.babelrc', @@ -31,8 +30,6 @@ const BABEL_CONFIG_FILENAMES = [ 'babel.config.cjs', ]; -const BABEL_CORE_RANGE = '^7.12.0'; - type BabelConfigResult = {| internal: boolean, config: BabelConfig, @@ -234,19 +231,6 @@ async function buildDefaultBabelConfig( syntaxPlugins.push('jsx'); } - babelOptions.presets = (babelOptions.presets || []).map(preset => - internalBabelCore.createConfigItem(preset, { - type: 'preset', - dirname: BABEL_TRANSFORMER_DIR, - }), - ); - babelOptions.plugins = (babelOptions.plugins || []).map(plugin => - internalBabelCore.createConfigItem(plugin, { - type: 'plugin', - dirname: BABEL_TRANSFORMER_DIR, - }), - ); - definePluginDependencies(config, babelOptions, options); return { internal: true, diff --git a/packages/transformers/babel/src/constants.js b/packages/transformers/babel/src/constants.js index 1ec6046b46c..60a923111ce 100644 --- a/packages/transformers/babel/src/constants.js +++ b/packages/transformers/babel/src/constants.js @@ -1,3 +1,3 @@ // @flow strict-local -export const BABEL_RANGE = '^7.0.0'; +export const BABEL_CORE_RANGE = '^7.12.0'; diff --git a/packages/transformers/babel/src/flow.js b/packages/transformers/babel/src/flow.js index a90dee380c3..5dd47e9ce3d 100644 --- a/packages/transformers/babel/src/flow.js +++ b/packages/transformers/babel/src/flow.js @@ -2,6 +2,10 @@ import type {Config, PluginOptions, PackageJSON} from '@parcel/types'; import type {BabelConfig} from './types'; +import typeof * as BabelCore from '@babel/core'; + +import {BABEL_CORE_RANGE} from './constants'; +import path from 'path'; /** * Generates a babel config for stripping away Flow types. @@ -28,9 +32,35 @@ export default async function getFlowOptions( return null; } + const babelCore: BabelCore = await options.packageManager.require( + '@babel/core', + config.searchPath, + { + range: BABEL_CORE_RANGE, + saveDev: true, + shouldAutoInstall: options.shouldAutoInstall, + }, + ); + + await options.packageManager.require( + '@babel/plugin-transform-flow-strip-types', + config.searchPath, + { + range: '^7.0.0', + saveDev: true, + shouldAutoInstall: options.shouldAutoInstall, + }, + ); + return { plugins: [ - ['@babel/plugin-transform-flow-strip-types', {requireDirective: true}], + babelCore.createConfigItem( + ['@babel/plugin-transform-flow-strip-types', {requireDirective: true}], + { + type: 'plugin', + dirname: path.dirname(config.searchPath), + }, + ), ], }; } diff --git a/packages/transformers/babel/src/remapAstLocations.js b/packages/transformers/babel/src/remapAstLocations.js new file mode 100644 index 00000000000..db650f293ce --- /dev/null +++ b/packages/transformers/babel/src/remapAstLocations.js @@ -0,0 +1,70 @@ +// @flow strict-local + +import type {File as BabelNodeFile} from '@babel/types'; +import type SourceMap from '@parcel/source-map'; +import type {Node} from '@babel/types'; +import typeof * as BabelTypes from '@babel/types'; + +export function remapAstLocations( + t: BabelTypes, + ast: BabelNodeFile, + map: SourceMap, +) { + // remap ast to original mappings + // This improves sourcemap accuracy and fixes sourcemaps when scope-hoisting + traverseAll(t, ast.program, node => { + if (node.loc) { + if (node.loc?.start) { + let mapping = map.findClosestMapping( + node.loc.start.line, + node.loc.start.column, + ); + + if (mapping?.original) { + // $FlowFixMe + node.loc.start.line = mapping.original.line; + // $FlowFixMe + node.loc.start.column = mapping.original.column; + + // $FlowFixMe + let length = node.loc.end.column - node.loc.start.column; + + // $FlowFixMe + node.loc.end.line = mapping.original.line; + // $FlowFixMe + node.loc.end.column = mapping.original.column + length; + + // $FlowFixMe + node.loc.filename = mapping.source; + } else { + // Maintain null mappings? + node.loc = null; + } + } + } + }); +} + +function traverseAll( + t: BabelTypes, + node: Node, + visitor: (node: Node) => void, +): void { + if (!node) { + return; + } + + visitor(node); + + for (let key of t.VISITOR_KEYS[node.type] || []) { + // $FlowFixMe + let subNode: Node | Array = node[key]; + if (Array.isArray(subNode)) { + for (let i = 0; i < subNode.length; i++) { + traverseAll(t, subNode[i], visitor); + } + } else { + traverseAll(t, subNode, visitor); + } + } +} diff --git a/packages/transformers/babel/src/utils.js b/packages/transformers/babel/src/utils.js index 91ca1aee462..37f05372225 100644 --- a/packages/transformers/babel/src/utils.js +++ b/packages/transformers/babel/src/utils.js @@ -5,7 +5,22 @@ import type {Targets as BabelTargets} from '@babel/preset-env'; import invariant from 'assert'; import semver from 'semver'; -import {TargetNames} from '@babel/helper-compilation-targets/lib/options'; + +// Copied from @babel/helper-compilation-targets/lib/options.js +const TargetNames = { + node: 'node', + chrome: 'chrome', + opera: 'opera', + edge: 'edge', + firefox: 'firefox', + safari: 'safari', + ie: 'ie', + ios: 'ios', + android: 'android', + electron: 'electron', + samsung: 'samsung', + rhino: 'rhino', +}; // List of browsers to exclude when the esmodule target is specified. // Based on https://caniuse.com/#feat=es6-module diff --git a/packages/transformers/css/package.json b/packages/transformers/css/package.json index 993e465128d..503bf615050 100644 --- a/packages/transformers/css/package.json +++ b/packages/transformers/css/package.json @@ -26,8 +26,10 @@ "@parcel/utils": "2.0.15", "nullthrows": "^1.1.1", "postcss": "^8.4.5", - "postcss-modules": "^4.3.0", "postcss-value-parser": "^4.2.0", "semver": "^5.7.1" + }, + "devDependencies": { + "postcss-modules": "^4.3.0" } } diff --git a/packages/transformers/css/src/CSSTransformer.js b/packages/transformers/css/src/CSSTransformer.js index 9ce5e67a600..8aff146b660 100644 --- a/packages/transformers/css/src/CSSTransformer.js +++ b/packages/transformers/css/src/CSSTransformer.js @@ -1,7 +1,7 @@ // @flow import type {Root} from 'postcss'; -import type {FilePath, MutableAsset} from '@parcel/types'; +import type {FilePath, MutableAsset, PluginOptions} from '@parcel/types'; import {hashString} from '@parcel/hash'; import SourceMap from '@parcel/source-map'; @@ -10,8 +10,6 @@ import {createDependencyLocation, remapSourceLocation} from '@parcel/utils'; import postcss from 'postcss'; import nullthrows from 'nullthrows'; import valueParser from 'postcss-value-parser'; -import postcssModules from 'postcss-modules'; -import FileSystemLoader from 'postcss-modules/build/css-loader-core/loader'; import semver from 'semver'; import path from 'path'; @@ -274,10 +272,20 @@ async function compileCSSModules(asset, env, program, resolve, options) { }); } + let postcssModules = await options.packageManager.require( + 'postcss-modules', + asset.filePath, + { + range: '^4.3.0', + saveDev: true, + shouldAutoInstall: options.shouldAutoInstall, + }, + ); + let {root} = await postcss([ postcssModules({ getJSON: (filename, json) => (cssModules = json), - Loader: createLoader(asset, resolve), + Loader: await createLoader(asset, resolve, options), generateScopedName: (name, filename) => `${name}_${hashString( path.relative(options.projectRoot, filename), @@ -329,10 +337,15 @@ async function compileCSSModules(asset, env, program, resolve, options) { return assets; } -function createLoader( +async function createLoader( asset: MutableAsset, resolve: (from: FilePath, to: string) => Promise, + options: PluginOptions, ) { + let {default: FileSystemLoader} = await options.packageManager.require( + 'postcss-modules/build/css-loader-core/loader', + asset.filePath, + ); return class ParcelFileSystemLoader extends FileSystemLoader { async fetch(composesPath, relativeTo) { let importPath = composesPath.replace(/^["']|["']$/g, ''); diff --git a/packages/transformers/js/core/src/hoist.rs b/packages/transformers/js/core/src/hoist.rs index 3d3eb58f331..02e17bce0b1 100644 --- a/packages/transformers/js/core/src/hoist.rs +++ b/packages/transformers/js/core/src/hoist.rs @@ -693,31 +693,6 @@ impl<'a> Fold for Hoist<'a> { } } } - Expr::Unary(ref unary) => { - // typeof require -> "function" - // typeof module -> "object" - if unary.op == UnaryOp::TypeOf { - if let Expr::Ident(ident) = &*unary.arg { - if ident.sym == js_word!("require") && !self.collect.decls.contains(&id!(ident)) { - return Expr::Lit(Lit::Str(Str { - kind: StrKind::Synthesized, - has_escape: false, - span: unary.span, - value: js_word!("function"), - })); - } - - if ident.sym == js_word!("module") && !self.collect.decls.contains(&id!(ident)) { - return Expr::Lit(Lit::Str(Str { - kind: StrKind::Synthesized, - has_escape: false, - span: unary.span, - value: js_word!("object"), - })); - } - } - } - } _ => {} } diff --git a/packages/transformers/js/core/src/lib.rs b/packages/transformers/js/core/src/lib.rs index 4022a0467de..3e9c161f629 100644 --- a/packages/transformers/js/core/src/lib.rs +++ b/packages/transformers/js/core/src/lib.rs @@ -18,6 +18,7 @@ mod fs; mod global_replacer; mod hoist; mod modules; +mod typeof_replacer; mod utils; use std::collections::{HashMap, HashSet}; @@ -49,6 +50,7 @@ use fs::inline_fs; use global_replacer::GlobalReplacer; use hoist::{hoist, CollectResult, HoistResult}; use modules::esm2cjs; +use typeof_replacer::*; use utils::{CodeHighlight, Diagnostic, DiagnosticSeverity, SourceLocation, SourceType}; use crate::hoist::Collect; @@ -223,9 +225,15 @@ pub fn transform(config: Config) -> Result { let should_inline_fs = config.inline_fs && config.source_type != SourceType::Script && code.contains("readFileSync"); + let should_import_swc_helpers = match config.source_type { + SourceType::Module => true, + SourceType::Script => false, + }; swc_common::GLOBALS.set(&Globals::new(), || { helpers::HELPERS.set( - &helpers::Helpers::new(/* external helpers from @swc/helpers */ true), + &helpers::Helpers::new( + /* external helpers from @swc/helpers */ should_import_swc_helpers, + ), || { let mut react_options = react::Options::default(); if config.is_jsx { @@ -315,6 +323,10 @@ pub fn transform(config: Config) -> Result { let mut diagnostics = vec![]; let module = { let mut passes = chain!( + Optional::new( + TypeofReplacer { decls: &decls }, + config.source_type != SourceType::Script + ), // Inline process.env and process.browser Optional::new( EnvReplacer { diff --git a/packages/transformers/js/core/src/typeof_replacer.rs b/packages/transformers/js/core/src/typeof_replacer.rs new file mode 100644 index 00000000000..f76c1fa8bf7 --- /dev/null +++ b/packages/transformers/js/core/src/typeof_replacer.rs @@ -0,0 +1,52 @@ +use std::collections::HashSet; + +use swc_atoms::JsWord; +use swc_ecmascript::ast::{Expr, Lit, Str, StrKind, UnaryOp}; +use swc_ecmascript::visit::{Fold, FoldWith}; + +use crate::id; +use crate::utils::IdentId; + +pub struct TypeofReplacer<'a> { + pub decls: &'a HashSet, +} + +impl<'a> Fold for TypeofReplacer<'a> { + fn fold_expr(&mut self, node: Expr) -> Expr { + if let Expr::Unary(ref unary) = node { + // typeof require -> "function" + // typeof module -> "object" + if unary.op == UnaryOp::TypeOf { + if let Expr::Ident(ident) = &*unary.arg { + if ident.sym == js_word!("require") && !self.decls.contains(&id!(ident)) { + return Expr::Lit(Lit::Str(Str { + kind: StrKind::Synthesized, + has_escape: false, + span: unary.span, + value: js_word!("function"), + })); + } + let exports: JsWord = "exports".into(); + if ident.sym == exports && !self.decls.contains(&id!(ident)) { + return Expr::Lit(Lit::Str(Str { + kind: StrKind::Synthesized, + has_escape: false, + span: unary.span, + value: js_word!("object"), + })); + } + + if ident.sym == js_word!("module") && !self.decls.contains(&id!(ident)) { + return Expr::Lit(Lit::Str(Str { + kind: StrKind::Synthesized, + has_escape: false, + span: unary.span, + value: js_word!("object"), + })); + } + } + } + } + node.fold_children_with(self) + } +} diff --git a/packages/transformers/js/package.json b/packages/transformers/js/package.json index 788a8df2dec..6a263d889eb 100644 --- a/packages/transformers/js/package.json +++ b/packages/transformers/js/package.json @@ -38,7 +38,6 @@ "@swc/helpers": "^0.2.11", "browserslist": "^4.6.6", "detect-libc": "^1.0.3", - "micromatch": "^4.0.2", "nullthrows": "^1.1.1", "regenerator-runtime": "^0.13.7", "self-published": "npm:@parcel/transformer-js@2.0.0-nightly.986", diff --git a/packages/transformers/js/src/JSTransformer.js b/packages/transformers/js/src/JSTransformer.js index f7126d1cd12..2f075fe4078 100644 --- a/packages/transformers/js/src/JSTransformer.js +++ b/packages/transformers/js/src/JSTransformer.js @@ -10,8 +10,7 @@ import browserslist from 'browserslist'; import semver from 'semver'; import nullthrows from 'nullthrows'; import ThrowableDiagnostic, {encodeJSONKeyComponent} from '@parcel/diagnostic'; -import {validateSchema, remapSourceLocation} from '@parcel/utils'; -import {isMatch} from 'micromatch'; +import {validateSchema, remapSourceLocation, isGlobMatch} from '@parcel/utils'; import WorkerFarm from '@parcel/workers'; const JSX_EXTENSIONS = { @@ -23,7 +22,7 @@ const JSX_PRAGMA = { react: { pragma: 'React.createElement', pragmaFrag: 'React.Fragment', - automatic: '>= 17.0.0', + automatic: '>= 17.0.0 || >= 0.0.0-0 < 0.0.0', }, preact: { pragma: 'h', @@ -221,7 +220,9 @@ export default (new Transformer({ automaticVersion && !compilerOptions?.jsxFactory && minReactLibVersion != null && - semver.satisfies(minReactLibVersion, automaticVersion); + semver.satisfies(minReactLibVersion, automaticVersion, { + includePrerelease: true, + }); if (automaticJSXRuntime) { jsxImportSource = reactLib; @@ -350,7 +351,7 @@ export default (new Transformer({ } } else if (Array.isArray(config?.inlineEnvironment)) { for (let key in options.env) { - if (isMatch(key, config.inlineEnvironment)) { + if (isGlobMatch(key, config.inlineEnvironment)) { env[key] = String(options.env[key]); } } diff --git a/packages/transformers/postcss/package.json b/packages/transformers/postcss/package.json index d8a9f29e6ac..17692cae2ac 100644 --- a/packages/transformers/postcss/package.json +++ b/packages/transformers/postcss/package.json @@ -25,7 +25,6 @@ "@parcel/utils": "2.0.15", "clone": "^2.1.1", "nullthrows": "^1.1.1", - "postcss-modules": "^4.3.0", "postcss-value-parser": "^4.2.0", "semver": "^5.7.1" }, diff --git a/packages/transformers/postcss/src/PostCSSTransformer.js b/packages/transformers/postcss/src/PostCSSTransformer.js index a60f5785226..fd341c2be60 100644 --- a/packages/transformers/postcss/src/PostCSSTransformer.js +++ b/packages/transformers/postcss/src/PostCSSTransformer.js @@ -5,12 +5,10 @@ import type {FilePath, Asset, MutableAsset, PluginOptions} from '@parcel/types'; import {hashString} from '@parcel/hash'; import {glob} from '@parcel/utils'; import {Transformer} from '@parcel/plugin'; -import FileSystemLoader from 'postcss-modules/build/css-loader-core/loader'; import nullthrows from 'nullthrows'; import path from 'path'; import semver from 'semver'; import valueParser from 'postcss-value-parser'; -import postcssModules from 'postcss-modules'; import typeof * as Postcss from 'postcss'; import {load} from './loadConfig'; @@ -79,10 +77,22 @@ export default (new Transformer({ let cssModules: ?{|[string]: string|} = null; if (config.hydrated.modules) { asset.meta.cssModulesCompiled = true; + + // TODO: should this be resolved from the project root? + let postcssModules = await options.packageManager.require( + 'postcss-modules', + asset.filePath, + { + range: '^4.3.0', + saveDev: true, + shouldAutoInstall: options.shouldAutoInstall, + }, + ); + plugins.push( postcssModules({ getJSON: (filename, json) => (cssModules = json), - Loader: createLoader(asset, resolve), + Loader: await createLoader(asset, resolve, options), generateScopedName: (name, filename) => `${name}_${hashString( path.relative(options.projectRoot, filename), @@ -196,10 +206,15 @@ export default (new Transformer({ }, }): Transformer); -function createLoader( +async function createLoader( asset: MutableAsset, resolve: (from: FilePath, to: string) => Promise, + options: PluginOptions, ) { + let {default: FileSystemLoader} = await options.packageManager.require( + 'postcss-modules/build/css-loader-core/loader', + asset.filePath, + ); return class ParcelFileSystemLoader extends FileSystemLoader { async fetch(composesPath, relativeTo) { let importPath = composesPath.replace(/^["']|["']$/g, ''); diff --git a/packages/utils/babylon-walk/LICENSE.md b/packages/utils/babylon-walk/LICENSE.md deleted file mode 100755 index 258e4b99d20..00000000000 --- a/packages/utils/babylon-walk/LICENSE.md +++ /dev/null @@ -1,7 +0,0 @@ -Copyright (c) 2016 Tiancheng "Timothy" Gu - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/packages/utils/babylon-walk/README.md b/packages/utils/babylon-walk/README.md deleted file mode 100755 index 25c02f9301e..00000000000 --- a/packages/utils/babylon-walk/README.md +++ /dev/null @@ -1,135 +0,0 @@ -# babylon-walk - -Lightweight AST traversal tools for [Babylon] ASTs. - -Babylon is the parser used by the [Babel] project, which supplies the wonderful [babel-traverse] module for walking Babylon ASTs. Problem is, babel-traverse is very heavyweight, as it is designed to supply utilities to make all sorts of AST transformations possible. For simple AST walking without transformation, babel-traverse brings a lot of overhead. - -This module loosely implements the API of Acorn parser's [walk module], which is a lightweight AST walker for the ESTree AST format. - -In my tests, babylon-walk's ancestor walker (the most complex walker provided by this module) is about 8 times faster than babel-traverse, if the visitors are cached and the same AST is used for all runs. It is about 16 times faster if a fresh AST is used every run. - -[![Dependency Status](https://img.shields.io/david/pugjs/babylon-walk.svg)](https://david-dm.org/pugjs/babylon-walk) -[![NPM version](https://img.shields.io/npm/v/babylon-walk.svg)](https://www.npmjs.com/package/babylon-walk) - -[babylon]: https://github.com/babel/babylon -[babel]: https://babeljs.io/ -[babel-traverse]: https://github.com/thejameskyle/babel-handbook/blob/master/translations/en/plugin-handbook.md#toc-babel-traverse -[walk module]: https://github.com/ternjs/acorn#distwalkjs - -## Installation - -```sh -$ npm install babylon-walk -``` - -## API - -```js -var walk = require('babylon-walk'); -``` - -### walk.simple(node, visitors, state) - -Do a simple walk over the AST. `node` should be the AST node to walk, and `visitors` an object containing Babel [visitors]. Each visitor function will be called as `(node, state)`, where `node` is the AST node, and `state` is the same `state` passed to `walk.simple`. - -When `walk.simple` is called with a fresh set of visitors, it will first "explode" the visitors (e.g. expanding `Visitor(node, state) {}` to `Visitor() { enter(node, state) {} }`). This exploding process can take some time, so it is recommended to [cache your visitors] and communicate state leveraging the `state` parameter. (One difference between the linked article and babylon-walk is that the state is only accessible through the `state` variable, never as `this`.) - -All [babel-types] aliases (e.g. `Expression`) and the union syntax (e.g. `'Identifier|AssignmentPattern'(node, state) {}`) work. - -### walk.ancestor(node, visitors, state) - -Do a simple walk over the AST, but memoizing the ancestors of the node and making them available to the visitors. `node` should be the AST node to walk, and `visitors` an object containing Babel [visitors]. Each visitor function will be called as `(node, state, ancestors)`, where `node` is the AST node, `state` is the same `state` passed to `walk.ancestor`, and `ancestors` is an array of ancestors to the node (with the outermost node being `[0]` and the current node being `[ancestors.length - 1]`). If `state` is not specified in the call to `walk.ancestor`, the `state` parameter will be set to `ancestors`. - -When `walk.ancestor` is called with a fresh set of visitors, it will first "explode" the visitors (e.g. expanding `Visitor(node, state) {}` to `Visitor() { enter(node, state) {} }`). This exploding process can take some time, so it is recommended to [cache your visitors] and communicate state leveraging the `state` parameter. (One difference between the linked article and babylon-walk is that the state is only accessible through the `state` variable, never as `this`.) - -All [babel-types] aliases (e.g. `Expression`) and the union syntax (e.g. `'Identifier|AssignmentPattern'(node, state) {}`) work. - -### walk.recursive(node, visitors, state) - -Do a recursive walk over the AST, where the visitors are responsible for continuing the walk on the child nodes of their target node. `node` should be the AST node to walk, and `visitors` an object containing Babel [visitors]. Each visitor function will be called as `(node, state, c)`, where `node` is the AST node, `state` is the same `state` passed to `walk.recursive`, and `c` is a function that takes a single node as argument and continues walking _that_ node. If no visitor for a node is provided, the default walker algorithm will still be used. - -When `walk.recursive` is called with a fresh set of visitors, it will first "explode" the visitors (e.g. expanding `Visitor(node, state) {}` to `Visitor() { enter(node, state) {} }`). This exploding process can take some time, so it is recommended to [cache your visitors] and communicate state leveraging the `state` parameter. (One difference between the linked article and babylon-walk is that the state is only accessible through the `state` variable, never as `this`.) - -Unlike other babylon-walk walkers, `walk.recursive` does not call the `exit` visitor, only the `enter` (the default) visitor, of a specific node type. - -All [babel-types] aliases (e.g. `Expression`) and the union syntax (e.g. `'Identifier|AssignmentPattern'(node, state) {}`) work. - -In the following example, we are trying to count the number of functions in the outermost scope. This means, that we can simply walk all the statements and increment a counter if it is a function declaration or expression, and then stop walking. Note that we do not specify a visitor for the `Program` node, and the default algorithm for walking `Program` nodes is used (which is what we want). Also of note is how I bring the `visitors` object outside of `countFunctions` so that the object can be cached to improve performance. - -```js -import * as t from 'babel-types'; -import {parse} from 'babylon'; -import * as walk from 'babylon-walk'; - -const visitors = { - Statement(node, state, c) { - if (t.isVariableDeclaration(node)) { - for (let declarator of node.declarations) { - // Continue walking the declarator - c(declarator); - } - } else if (t.isFunctionDeclaration(node)) { - state.counter++; - } - }, - - VariableDeclarator(node, state) { - if (t.isFunction(node.init)) { - state.counter++; - } - }, -}; - -function countFunctions(node) { - const state = { - counter: 0, - }; - walk.recursive(node, visitors, state); - return state.counter; -} - -const ast = parse(` - // Counts - var a = () => {}; - - // Counts - function b() { - // Doesn't count - function c() { - } - } - - // Counts - const c = function d() {}; -`); - -countFunctions(ast); -// = 3 -``` - -### walk.traverse(node, visitors, state) - -Visitors get called as `(path, state)`. Every `Path` has these methods (similar to `@babel/traverse`): - -- `skip()` -- `replaceWith(node)` -- `remove()` - -[babel-types]: https://github.com/babel/babel/tree/master/packages/babel-types -[cache your visitors]: https://github.com/thejameskyle/babel-handbook/blob/master/translations/en/plugin-handbook.md#toc-optimizing-nested-visitors -[visitors]: https://github.com/thejameskyle/babel-handbook/blob/master/translations/en/plugin-handbook.md#toc-visitors - -## Caveat - -For those of you migrating from Acorn to Babylon, there are a few things to be aware of. - -1. The visitor caching suggestions do not apply to Acorn's walk module, but do for babylon-walk. - -2. babylon-walk does not provide any of the other functions Acorn's walk module provides (e.g. `make`, `findNode*`). - -3. babylon-walk does not use a `base` variable. The walker algorithm is the same as what babel-traverse uses. - - That means certain nodes that are not walked by Acorn, such as the `property` property of a non-computed `MemberExpression`, are walked by babylon-walk. - -## License - -MIT diff --git a/packages/utils/babylon-walk/package.json b/packages/utils/babylon-walk/package.json deleted file mode 100755 index f018db75a03..00000000000 --- a/packages/utils/babylon-walk/package.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "name": "@parcel/babylon-walk", - "version": "2.0.15", - "license": "MIT", - "publishConfig": { - "access": "public" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - }, - "description": "Lightweight Babylon AST traversal", - "repository": { - "type": "git", - "url": "https://github.com/parcel-bundler/parcel.git", - "directory": "packages/utils/babylon-walk" - }, - "main": "lib/index.js", - "source": "src/index.js", - "engines": { - "node": ">= 12.0.0" - }, - "author": "Timothy Gu ", - "dependencies": { - "@babel/types": "^7.12.13", - "lodash.clone": "^4.5.0" - } -} diff --git a/packages/utils/babylon-walk/src/explode.js b/packages/utils/babylon-walk/src/explode.js deleted file mode 100755 index 9699e9811ea..00000000000 --- a/packages/utils/babylon-walk/src/explode.js +++ /dev/null @@ -1,191 +0,0 @@ -// @flow -// Copied from babel-traverse, but with virtual types handling removed -// https://github.com/babel/babel/blob/07b3dc18a09f2217b38a3a63c8613add6df1b47d/packages/babel-traverse/src/visitors.js -import type {SimpleVisitors, VisitorsExploded} from './index'; - -// import * as messages from 'babel-messages'; -import * as t from '@babel/types'; -import clone from 'lodash.clone'; - -/** - * explode() will take a visitor object with all of the various shorthands - * that we support, and validates & normalizes it into a common format, ready - * to be used in traversal - * - * The various shorthands are: - * * `Identifier() { ... }` -> `Identifier: { enter() { ... } }` - * * `"Identifier|NumericLiteral": { ... }` -> `Identifier: { ... }, NumericLiteral: { ... }` - * * Aliases in `babel-types`: e.g. `Property: { ... }` -> `ObjectProperty: { ... }, ClassProperty: { ... }` - * - * Other normalizations are: - * * `enter` and `exit` functions are wrapped in arrays, to ease merging of - * visitors - */ -export default function explode( - visitor: SimpleVisitors, -): VisitorsExploded { - // $FlowFixMe - if (visitor._exploded) return visitor; - // $FlowFixMe - visitor._exploded = true; - - // normalise pipes - for (let nodeType in visitor) { - if (shouldIgnoreKey(nodeType)) continue; - - let parts = nodeType.split('|'); - if (parts.length === 1) continue; - - let fns = visitor[nodeType]; - delete visitor[nodeType]; - - for (let part of parts) { - visitor[part] = fns; - } - } - - // verify data structure - verify(visitor); - - // make sure there's no __esModule type since this is because we're using loose mode - // and it sets __esModule to be enumerable on all modules :( - delete visitor.__esModule; - - // ensure visitors are objects - ensureEntranceObjects(visitor); - - // ensure enter/exit callbacks are arrays - ensureCallbackArrays(visitor); - - // add aliases - for (let nodeType in visitor) { - if (shouldIgnoreKey(nodeType)) continue; - - let fns = visitor[nodeType]; - - let aliases = t.FLIPPED_ALIAS_KEYS[nodeType]; - - let deprecratedKey = t.DEPRECATED_KEYS[nodeType]; - if (deprecratedKey) { - throw new Error( - `Visitor defined for ${nodeType} but it has been renamed to ${deprecratedKey}`, - ); - } - - if (!aliases) continue; - - // clear it from the visitor - delete visitor[nodeType]; - - for (let alias of aliases) { - let existing = visitor[alias]; - if (existing) { - mergePair(existing, fns); - } else { - visitor[alias] = clone(fns); - } - } - } - - for (let nodeType in visitor) { - if (shouldIgnoreKey(nodeType)) continue; - - ensureCallbackArrays(visitor[nodeType]); - } - - // $FlowFixMe - return visitor; -} - -export function verify(visitor: any) { - if (visitor._verified) return; - - if (typeof visitor === 'function') { - // throw new Error(messages.get("traverseVerifyRootFunction")); - throw new Error( - "You passed `traverse()` a function when it expected a visitor object, are you sure you didn't mean `{ enter: Function }`?", - ); - } - - for (let nodeType in visitor) { - if (nodeType === 'enter' || nodeType === 'exit') { - validateVisitorMethods(nodeType, visitor[nodeType]); - } - - if (shouldIgnoreKey(nodeType)) continue; - - if (t.TYPES.indexOf(nodeType) < 0) { - // throw new Error(messages.get("traverseVerifyNodeType", nodeType)); - throw new Error( - `You gave us a visitor for the node type ${nodeType} but it's not a valid type`, - ); - } - - let visitors = visitor[nodeType]; - if (typeof visitors === 'object') { - for (let visitorKey in visitors) { - if (visitorKey === 'enter' || visitorKey === 'exit') { - // verify that it just contains functions - validateVisitorMethods( - `${nodeType}.${visitorKey}`, - visitors[visitorKey], - ); - } else { - // throw new Error(messages.get("traverseVerifyVisitorProperty", nodeType, visitorKey)); - throw new Error( - `You passed \`traverse()\` a visitor object with the property ${nodeType} that has the invalid property ${visitorKey}`, - ); - } - } - } - } - - visitor._verified = true; -} - -function validateVisitorMethods(path, val) { - let fns = [].concat(val); - for (let fn of fns) { - if (typeof fn !== 'function') { - throw new TypeError( - `Non-function found defined in ${path} with type ${typeof fn}`, - ); - } - } -} - -function ensureEntranceObjects(obj: any) { - for (let key in obj) { - if (shouldIgnoreKey(key)) continue; - - let fns = obj[key]; - if (typeof fns === 'function') { - obj[key] = {enter: fns}; - } - } -} - -function ensureCallbackArrays(obj: any) { - if (obj.enter && !Array.isArray(obj.enter)) obj.enter = [obj.enter]; - if (obj.exit && !Array.isArray(obj.exit)) obj.exit = [obj.exit]; -} - -function shouldIgnoreKey(key) { - // internal/hidden key - if (key[0] === '_') return true; - - // ignore function keys - if (key === 'enter' || key === 'exit' || key === 'shouldSkip') return true; - - // ignore other options - if (key === 'blacklist' || key === 'noScope' || key === 'skipKeys') - return true; - - return false; -} - -function mergePair(dest: any, src: any) { - for (let key in src) { - dest[key] = [].concat(dest[key] || [], src[key]); - } -} diff --git a/packages/utils/babylon-walk/src/index.js b/packages/utils/babylon-walk/src/index.js deleted file mode 100755 index 8f82f484f97..00000000000 --- a/packages/utils/babylon-walk/src/index.js +++ /dev/null @@ -1,137 +0,0 @@ -// @flow -import type {Node} from '@babel/types'; -import type {SimpleVisitors, VisitorsExploded} from './types'; - -import * as t from '@babel/types'; -import explode from './explode.js'; -import traverse from './traverse'; - -export * from './traverse2'; -export * from './traverse-all'; -export * from './scope'; -export * from './types'; - -export function simple( - node: Node, - _visitors: SimpleVisitors<(any, T) => void>, - state: T, -) { - if (!node) return; - - const visitors: VisitorsExploded<(any, T) => void> = explode(_visitors); - - (function c(node) { - if (!node) return; - - const {enter, exit} = visitors[node.type] || {}; - - if (enter) { - for (let visitor of enter) { - visitor(node, state); - } - } - - for (let key of t.VISITOR_KEYS[node.type] || []) { - // $FlowFixMe - let subNode = node[key]; - if (Array.isArray(subNode)) { - for (let subSubNode of subNode) { - c(subSubNode); - } - } else { - c(subNode); - } - } - - if (exit) { - for (let visitor of exit) { - visitor(node, state); - } - } - })(node); -} - -export function ancestor( - node: Node, - _visitors: SimpleVisitors<(any, T, Array) => void>, - state: T, -) { - if (!node) return; - - const visitors = explode<(any, T, Array) => void>(_visitors); - let ancestors = []; - - (function c(node) { - if (!node) return; - - const {enter, exit} = visitors[node.type] || {}; - - let isNew = node != ancestors[ancestors.length - 1]; - if (isNew) ancestors.push(node); - - if (enter) { - for (let visitor of enter) { - // $FlowFixMe - visitor(node, state || ancestors, ancestors); - } - } - - for (let key of t.VISITOR_KEYS[node.type] || []) { - // $FlowFixMe - let subNode = node[key]; - if (Array.isArray(subNode)) { - for (let subSubNode of subNode) { - c(subSubNode); - } - } else { - c(subNode); - } - } - - if (exit) { - for (let visitor of exit) { - // $FlowFixMe - visitor(node, state || ancestors, ancestors); - } - } - - if (isNew) ancestors.pop(); - })(node); -} - -export function recursive( - node: Node, - _visitors: SimpleVisitors<(any, T, recurse: (Node) => void) => void>, - state: T, -) { - if (!node) return; - - const visitors = - explode<(any, T, recurse: (Node) => void) => void>(_visitors); - - (function c(node) { - if (!node) return; - - const {enter} = visitors[node.type] || {}; - - if (enter && enter.length) { - for (let visitor of enter) { - visitor(node, state, c); - } - } else { - for (let key of t.VISITOR_KEYS[node.type] || []) { - // $FlowFixMe - let subNode = node[key]; - if (Array.isArray(subNode)) { - for (let subSubNode of subNode) { - c(subSubNode); - } - } else { - c(subNode); - } - } - } - })(node); -} - -export {traverse}; diff --git a/packages/utils/babylon-walk/src/scope.js b/packages/utils/babylon-walk/src/scope.js deleted file mode 100644 index f8a10c9f6a2..00000000000 --- a/packages/utils/babylon-walk/src/scope.js +++ /dev/null @@ -1,231 +0,0 @@ -// @flow - -import type {Identifier, Node} from '@babel/types'; -import type {Visitors} from './types'; -import * as t from '@babel/types'; -import invariant from 'assert'; -import { - isClassDeclaration, - isFunctionDeclaration, - isIdentifier, - isImportDeclaration, - isVariableDeclaration, -} from '@babel/types'; - -export type ScopeType = 'program' | 'function' | 'arrow_function' | 'block'; -export type BindingType = 'var' | 'let' | 'const'; -export class Scope { - type: ScopeType; - names: Set = new Set(); - bindings: Map = new Map(); - references: Map> = new Map(); - parent: ?Scope; - program: Scope; - renames: Map = new Map(); - inverseRenames: Map = new Map(); - - constructor(type: ScopeType, parent: ?Scope) { - this.type = type; - this.parent = parent; - this.program = parent ? parent.program : this; - } - - has(name: string): boolean { - if (this.names.has(name)) { - return true; - } - - if (this.parent) { - return this.parent.has(name); - } - - return false; - } - - add(name: string) { - this.names.add(name); - } - - generateUid(name: string = 'temp'): string { - name = t - .toIdentifier(name) - .replace(/^_+/, '') - .replace(/[0-9]+$/g, ''); - - let uid; - let i = 0; - do { - uid = '_' + name + (i > 1 ? i : ''); - i++; - } while (this.program.names.has(uid)); - - this.program.names.add(uid); - return uid; - } - - addBinding(name: string, decl: Node, type: BindingType | 'param') { - if ( - type === 'var' && - this.type !== 'function' && - this.type !== 'arrow_function' && - this.parent - ) { - this.parent.addBinding(name, decl, type); - } else { - if (type === 'param') type = 'var'; - this.names.add(name); - this.bindings.set(name, decl); - this.program.names.add(name); - } - } - - getBinding(name: string): ?Node { - return this.bindings.get(name) ?? this.parent?.getBinding(name); - } - - addReference(identifier: Identifier) { - let references = this.references.get(identifier.name); - if (!references) { - references = new Set(); - this.references.set(identifier.name, references); - } - - references.add(identifier); - } - - rename(from: string, to: string) { - // If already renamed, update the original to the final name. - let renamed = this.inverseRenames.get(from); - if (renamed) { - this.renames.set(renamed, to); - } else { - this.renames.set(from, to); - this.inverseRenames.set(to, from); - } - } - - exit() { - // Rename declarations in this scope. - for (let [from, to] of this.renames) { - if (!this.names.has(from) && this.parent) { - this.parent.rename(from, to); - } - - let references = this.references.get(from); - if (!references) { - continue; - } - - for (let id of references) { - id.name = to; - } - } - - // Propagate unknown references to the parent scope. - let parent = this.parent; - if (parent) { - for (let [name, ids] of this.references) { - if (!this.names.has(name)) { - for (let id of ids) { - parent.addReference(id); - } - } - } - } - } -} - -export type ScopeState = {| - scope: Scope, -|}; - -export let scopeVisitor: Visitors = { - Program(node, state) { - if (!state.scope) { - state.scope = new Scope('program'); - } - }, - Scopable: { - enter(node, state, ancestors) { - if ( - !t.isScope(node, ancestors[ancestors.length - 2]) || - t.isProgram(node) || - t.isFunction(node) - ) { - return; - } - - state.scope = new Scope('block', state.scope); - }, - exit(node, state, ancestors) { - if (!t.isScope(node, ancestors[ancestors.length - 2])) { - return; - } - - state.scope.exit(); - if (state.scope.parent) { - state.scope = state.scope.parent; - } - }, - }, - Declaration: { - exit(node, {scope}) { - if (t.isFunction(node) || t.isExportDeclaration(node)) { - return; - } - - // Register declarations with the scope. - if (isVariableDeclaration(node)) { - for (let decl of node.declarations) { - let ids = t.getBindingIdentifiers(decl); - for (let id in ids) { - scope.addBinding(id, decl, node.kind); - } - } - } else { - let type: BindingType; - if (isClassDeclaration(node)) { - type = 'let'; - } else if (isImportDeclaration(node)) { - type = 'const'; - } else { - invariant(false); - } - let ids = t.getBindingIdentifiers(node); - for (let id in ids) { - scope.addBinding(id, node, type); - } - } - }, - }, - Function(node, state) { - // Add function name to outer scope - let name; - if (isFunctionDeclaration(node) && isIdentifier(node.id)) { - name = node.id.name; - state.scope.addBinding(name, node, 'var'); - } - - // Create new scope - let type = t.isArrowFunctionExpression(node) - ? 'arrow_function' - : 'function'; - state.scope = new Scope(type, state.scope); - - // Add inner bindings to inner scope - let inner = t.getBindingIdentifiers(node); - for (let id in inner) { - if (id !== name) { - state.scope.addBinding(id, inner[id], 'param'); - } - } - }, - Identifier(node, state, ancestors) { - let parent = ancestors[ancestors.length - 2]; - if (!t.isReferenced(node, parent, ancestors[ancestors.length - 3])) { - return; - } - - state.scope.addReference(node); - }, -}; diff --git a/packages/utils/babylon-walk/src/traverse-all.js b/packages/utils/babylon-walk/src/traverse-all.js deleted file mode 100644 index ef58932e505..00000000000 --- a/packages/utils/babylon-walk/src/traverse-all.js +++ /dev/null @@ -1,24 +0,0 @@ -// @flow -import type {Node} from '@babel/types'; - -import * as t from '@babel/types'; - -export function traverseAll(node: Node, visitor: (node: Node) => void): void { - if (!node) { - return; - } - - visitor(node); - - for (let key of t.VISITOR_KEYS[node.type] || []) { - // $FlowFixMe - let subNode: Node | Array = node[key]; - if (Array.isArray(subNode)) { - for (let i = 0; i < subNode.length; i++) { - traverseAll(subNode[i], visitor); - } - } else { - traverseAll(subNode, visitor); - } - } -} diff --git a/packages/utils/babylon-walk/src/traverse.js b/packages/utils/babylon-walk/src/traverse.js deleted file mode 100644 index 86963d2a29b..00000000000 --- a/packages/utils/babylon-walk/src/traverse.js +++ /dev/null @@ -1,98 +0,0 @@ -// @flow -import type {Node} from '@babel/types'; -import type {SimpleVisitors, VisitorsExploded} from './index'; - -import * as t from '@babel/types'; -import invariant from 'assert'; -import explode from './explode.js'; - -class Path { - node: Node; - parent: Node; - listkey: ?string; - key: number | string; - _skipped: boolean = false; - _removed: boolean = false; - - constructor( - node: Node, - parent: Node, - listkey: ?string, - key: number | string, - ) { - this.node = node; - this.parent = parent; - this.listkey = listkey; - this.key = key; - } - replaceWith(n: Node) { - this.node = n; - - // $FlowFixMe - let p = this.listkey ? this.parent[this.listkey] : this.parent; - // $FlowFixMe - p[this.key] = this.node; - } - skip() { - this._skipped = true; - } - remove() { - this._removed = true; - invariant(this.listkey && typeof this.key === 'number'); - // $FlowFixMe - this.parent[this.listkey].splice(this.key, 1); - } -} - -export default function traverse( - node: Node, - visitors: SimpleVisitors<(Path, T) => void>, - state: T, -) { - traverseWalk(explode(visitors), state, node, null, null, null); -} - -function traverseWalk( - visitors: VisitorsExploded<(Path, T) => void>, - state: T, - node: Node, - parent: ?Node, - listkey, - key, -) { - if (!node || (visitors.shouldSkip && visitors.shouldSkip(node) === true)) { - return; - } - - const {enter, exit} = visitors[node.type] || {}; - - // $FlowFixMe - const path = new Path(node, parent, listkey, key); - - if (enter) { - for (let visitor of enter) { - visitor(path, state); - if (path._skipped || path._removed) return path._removed; - } - } - - for (let key of t.VISITOR_KEYS[node.type] || []) { - // $FlowFixMe - let subNode: Node | Array = node[key]; - if (Array.isArray(subNode)) { - for (let i = 0; i < subNode.length; i++) { - if (traverseWalk(visitors, state, subNode[i], node, key, i) === true) { - i--; - } - } - } else { - traverseWalk(visitors, state, subNode, node, null, key); - } - } - - if (exit) { - for (let visitor of exit) { - visitor(path, state); - } - } -} diff --git a/packages/utils/babylon-walk/src/traverse2.js b/packages/utils/babylon-walk/src/traverse2.js deleted file mode 100644 index 7b011e79efe..00000000000 --- a/packages/utils/babylon-walk/src/traverse2.js +++ /dev/null @@ -1,162 +0,0 @@ -// @flow -import type {Node} from '@babel/types'; -import type {VisitorFunc, Visitors, VisitorsExploded} from './types'; - -import * as t from '@babel/types'; -import explode from './explode.js'; - -export const SKIP: symbol = Symbol('traverse.SKIP'); -export const REMOVE: symbol = Symbol('traverse.REMOVE'); - -export function traverse2( - node: Node, - visitors: Visitors | VisitorsExploded>, - state: T, -) { - let ancestors = []; - let revisit = []; - traverseWalk(explode((visitors: any)), ancestors, revisit, state, node); - - for (let fn of revisit) { - fn(); - } -} - -function traverseWalk( - visitors: VisitorsExploded>, - ancestors: Node[], - revisit: any[], - state: T, - node: Node, -) { - if (!node || (visitors.shouldSkip && visitors.shouldSkip(node) === true)) { - return; - } - - let isNew = node != ancestors[ancestors.length - 1]; - if (isNew) ancestors.push(node); - - const {enter, exit} = visitors[node.type] || {}; - - if (enter) { - for (let visitor of enter) { - let res = visitor(node, state, ancestors); - if (res != null) { - if (isNew) ancestors.pop(); - return res; - } - } - } - - for (let key of t.VISITOR_KEYS[node.type] || []) { - // $FlowFixMe - let subNode: Node | Array = node[key]; - if (Array.isArray(subNode)) { - let revisitDiff = 0; - for (let i = 0; i < subNode.length; i++) { - let res = traverseWalk(visitors, ancestors, revisit, state, subNode[i]); - if (res === REMOVE) { - subNode.splice(i, 1); - i--; - } else if (res !== SKIP && res != null) { - if (typeof res === 'function') { - revisit.push(() => { - let index = i + revisitDiff; - let r = replaceArray(subNode, index, res()); - revisitDiff += r - index; - }); - } else { - i = replaceArray(subNode, i, res); - } - } - } - } else { - let res = traverseWalk(visitors, ancestors, revisit, state, subNode); - if (res === REMOVE) { - if (isNew) ancestors.pop(); - return REMOVE; - } else if (res !== SKIP && res != null) { - if (typeof res === 'function') { - revisit.push(() => { - let n = res(); - if (n != null) { - // $FlowFixMe - node[key] = n; - } - }); - } else { - // $FlowFixMe - node[key] = res; - } - } - } - } - - if (exit) { - for (let visitor of exit) { - let res = visitor(node, state, ancestors); - if (res != null) { - if (isNew) ancestors.pop(); - return res; - } - } - } - - if (isNew) ancestors.pop(); -} - -function replaceArray(subNode, i, res) { - if (res === REMOVE) { - subNode.splice(i, 1); - i--; - } else if (Array.isArray(res)) { - subNode.splice(i, 1, ...res); - if (res.length === 0) { - i--; - } else if (res.length > 1) { - i += res.length - 1; - } - } else if (res != null) { - // $FlowFixMe - subNode[i] = res; - } - - return i; -} - -export function mergeVisitors( - a: Visitors, - b: Visitors, -): VisitorsExploded> { - let res: VisitorsExploded> = {}; - // $FlowFixMe - res._exploded = true; - - for (let visitor of [a, b]) { - let {shouldSkip, ...exploded} = explode((visitor: any)); - for (let type in exploded) { - if (!res[type]) { - res[type] = {}; - } - - if (exploded[type].enter) { - res[type].enter = [...(res[type].enter || []), ...exploded[type].enter]; - } - - if (exploded[type].exit) { - res[type].exit = [...(res[type].exit || []), ...exploded[type].exit]; - } - } - - if (shouldSkip) { - if (res.shouldSkip) { - let prev = res.shouldSkip; - res.shouldSkip = node => prev(node) || shouldSkip(node); - } else { - res.shouldSkip = shouldSkip; - } - } - } - - return res; -} diff --git a/packages/utils/babylon-walk/src/types.js b/packages/utils/babylon-walk/src/types.js deleted file mode 100644 index 2f54bff4e7f..00000000000 --- a/packages/utils/babylon-walk/src/types.js +++ /dev/null @@ -1,337 +0,0 @@ -// @flow -import * as t from '@babel/types'; - -export type VisitorFunc = ( - N, - S, - Array, -) => - | void - | t.Node - | Array - | symbol - | (() => void | t.Node | Array | symbol); -type SingleVisitor = - | VisitorFunc - | {| - enter?: VisitorFunc, - exit?: VisitorFunc, - |}; - -export type Visitors = { - shouldSkip?: t.Node => boolean, - ReferencedIdentifier?: SingleVisitor, - Function?: SingleVisitor, - Class?: SingleVisitor, - ArrayExpression?: SingleVisitor, - AssignmentExpression?: SingleVisitor, - BinaryExpression?: SingleVisitor, - InterpreterDirective?: SingleVisitor, - Directive?: SingleVisitor, - DirectiveLiteral?: SingleVisitor, - BlockStatement?: SingleVisitor, - BreakStatement?: SingleVisitor, - CallExpression?: SingleVisitor, - CatchClause?: SingleVisitor, - ConditionalExpression?: SingleVisitor, - ContinueStatement?: SingleVisitor, - DebuggerStatement?: SingleVisitor, - DoWhileStatement?: SingleVisitor, - EmptyStatement?: SingleVisitor, - ExpressionStatement?: SingleVisitor, - File?: SingleVisitor, - ForInStatement?: SingleVisitor, - ForStatement?: SingleVisitor, - FunctionDeclaration?: SingleVisitor, - FunctionExpression?: SingleVisitor, - Identifier?: SingleVisitor, - IfStatement?: SingleVisitor, - LabeledStatement?: SingleVisitor, - StringLiteral?: SingleVisitor, - NumericLiteral?: SingleVisitor, - NullLiteral?: SingleVisitor, - BooleanLiteral?: SingleVisitor, - RegExpLiteral?: SingleVisitor, - LogicalExpression?: SingleVisitor, - MemberExpression?: SingleVisitor, - NewExpression?: SingleVisitor, - Program?: SingleVisitor, - ObjectExpression?: SingleVisitor, - ObjectMethod?: SingleVisitor, - ObjectProperty?: SingleVisitor, - RestElement?: SingleVisitor, - ReturnStatement?: SingleVisitor, - SequenceExpression?: SingleVisitor, - ParenthesizedExpression?: SingleVisitor, - SwitchCase?: SingleVisitor, - SwitchStatement?: SingleVisitor, - ThisExpression?: SingleVisitor, - ThrowStatement?: SingleVisitor, - TryStatement?: SingleVisitor, - UnaryExpression?: SingleVisitor, - UpdateExpression?: SingleVisitor, - VariableDeclaration?: SingleVisitor, - VariableDeclarator?: SingleVisitor, - WhileStatement?: SingleVisitor, - WithStatement?: SingleVisitor, - AssignmentPattern?: SingleVisitor, - ArrayPattern?: SingleVisitor, - ArrowFunctionExpression?: SingleVisitor, - ClassBody?: SingleVisitor, - ClassExpression?: SingleVisitor, - ClassDeclaration?: SingleVisitor, - ExportAllDeclaration?: SingleVisitor, - ExportDefaultDeclaration?: SingleVisitor, - ExportNamedDeclaration?: SingleVisitor, - ExportSpecifier?: SingleVisitor, - ForOfStatement?: SingleVisitor, - ImportDeclaration?: SingleVisitor, - ImportDefaultSpecifier?: SingleVisitor, - ImportNamespaceSpecifier?: SingleVisitor, - ImportSpecifier?: SingleVisitor, - MetaProperty?: SingleVisitor, - ClassMethod?: SingleVisitor, - ObjectPattern?: SingleVisitor, - SpreadElement?: SingleVisitor, - Super?: SingleVisitor, - TaggedTemplateExpression?: SingleVisitor, - TemplateElement?: SingleVisitor, - TemplateLiteral?: SingleVisitor, - YieldExpression?: SingleVisitor, - AnyTypeAnnotation?: SingleVisitor, - ArrayTypeAnnotation?: SingleVisitor, - BooleanTypeAnnotation?: SingleVisitor, - BooleanLiteralTypeAnnotation?: SingleVisitor< - t.BooleanLiteralTypeAnnotation, - S, - >, - NullLiteralTypeAnnotation?: SingleVisitor, - ClassImplements?: SingleVisitor, - DeclareClass?: SingleVisitor, - DeclareFunction?: SingleVisitor, - DeclareInterface?: SingleVisitor, - DeclareModule?: SingleVisitor, - DeclareModuleExports?: SingleVisitor, - DeclareTypeAlias?: SingleVisitor, - DeclareOpaqueType?: SingleVisitor, - DeclareVariable?: SingleVisitor, - DeclareExportDeclaration?: SingleVisitor, - DeclareExportAllDeclaration?: SingleVisitor, - DeclaredPredicate?: SingleVisitor, - ExistsTypeAnnotation?: SingleVisitor, - FunctionTypeAnnotation?: SingleVisitor, - FunctionTypeParam?: SingleVisitor, - GenericTypeAnnotation?: SingleVisitor, - InferredPredicate?: SingleVisitor, - InterfaceExtends?: SingleVisitor, - InterfaceDeclaration?: SingleVisitor, - InterfaceTypeAnnotation?: SingleVisitor, - IntersectionTypeAnnotation?: SingleVisitor, - MixedTypeAnnotation?: SingleVisitor, - EmptyTypeAnnotation?: SingleVisitor, - NullableTypeAnnotation?: SingleVisitor, - NumberLiteralTypeAnnotation?: SingleVisitor, - NumberTypeAnnotation?: SingleVisitor, - ObjectTypeAnnotation?: SingleVisitor, - ObjectTypeInternalSlot?: SingleVisitor, - ObjectTypeCallProperty?: SingleVisitor, - ObjectTypeIndexer?: SingleVisitor, - ObjectTypeProperty?: SingleVisitor, - ObjectTypeSpreadProperty?: SingleVisitor, - OpaqueType?: SingleVisitor, - QualifiedTypeIdentifier?: SingleVisitor, - StringLiteralTypeAnnotation?: SingleVisitor, - StringTypeAnnotation?: SingleVisitor, - ThisTypeAnnotation?: SingleVisitor, - TupleTypeAnnotation?: SingleVisitor, - TypeofTypeAnnotation?: SingleVisitor, - TypeAlias?: SingleVisitor, - TypeAnnotation?: SingleVisitor, - TypeCastExpression?: SingleVisitor, - TypeParameter?: SingleVisitor, - TypeParameterDeclaration?: SingleVisitor, - TypeParameterInstantiation?: SingleVisitor, - UnionTypeAnnotation?: SingleVisitor, - Variance?: SingleVisitor, - VoidTypeAnnotation?: SingleVisitor, - EnumDeclaration?: SingleVisitor, - EnumBooleanBody?: SingleVisitor, - EnumNumberBody?: SingleVisitor, - EnumStringBody?: SingleVisitor, - EnumSymbolBody?: SingleVisitor, - EnumBooleanMember?: SingleVisitor, - EnumNumberMember?: SingleVisitor, - EnumStringMember?: SingleVisitor, - EnumDefaultedMember?: SingleVisitor, - JSXAttribute?: SingleVisitor, - JSXClosingElement?: SingleVisitor, - JSXElement?: SingleVisitor, - JSXEmptyExpression?: SingleVisitor, - JSXExpressionContainer?: SingleVisitor, - JSXSpreadChild?: SingleVisitor, - JSXIdentifier?: SingleVisitor, - JSXMemberExpression?: SingleVisitor, - JSXNamespacedName?: SingleVisitor, - JSXOpeningElement?: SingleVisitor, - JSXSpreadAttribute?: SingleVisitor, - JSXText?: SingleVisitor, - JSXFragment?: SingleVisitor, - JSXOpeningFragment?: SingleVisitor, - JSXClosingFragment?: SingleVisitor, - Noop?: SingleVisitor, - Placeholder?: SingleVisitor, - V8IntrinsicIdentifier?: SingleVisitor, - ArgumentPlaceholder?: SingleVisitor, - AwaitExpression?: SingleVisitor, - BindExpression?: SingleVisitor, - ClassProperty?: SingleVisitor, - OptionalMemberExpression?: SingleVisitor, - PipelineTopicExpression?: SingleVisitor, - PipelineBareFunction?: SingleVisitor, - PipelinePrimaryTopicReference?: SingleVisitor< - t.PipelinePrimaryTopicReference, - S, - >, - OptionalCallExpression?: SingleVisitor, - ClassPrivateProperty?: SingleVisitor, - ClassPrivateMethod?: SingleVisitor, - Import?: SingleVisitor, - Decorator?: SingleVisitor, - DoExpression?: SingleVisitor, - ExportDefaultSpecifier?: SingleVisitor, - ExportNamespaceSpecifier?: SingleVisitor, - PrivateName?: SingleVisitor, - BigIntLiteral?: SingleVisitor, - TSParameterProperty?: SingleVisitor, - TSDeclareFunction?: SingleVisitor, - TSDeclareMethod?: SingleVisitor, - TSQualifiedName?: SingleVisitor, - TSCallSignatureDeclaration?: SingleVisitor, - TSConstructSignatureDeclaration?: SingleVisitor< - t.TSConstructSignatureDeclaration, - S, - >, - TSPropertySignature?: SingleVisitor, - TSMethodSignature?: SingleVisitor, - TSIndexSignature?: SingleVisitor, - TSAnyKeyword?: SingleVisitor, - TSBooleanKeyword?: SingleVisitor, - TSBigIntKeyword?: SingleVisitor, - TSNeverKeyword?: SingleVisitor, - TSNullKeyword?: SingleVisitor, - TSNumberKeyword?: SingleVisitor, - TSObjectKeyword?: SingleVisitor, - TSStringKeyword?: SingleVisitor, - TSSymbolKeyword?: SingleVisitor, - TSUndefinedKeyword?: SingleVisitor, - TSUnknownKeyword?: SingleVisitor, - TSVoidKeyword?: SingleVisitor, - TSThisType?: SingleVisitor, - TSFunctionType?: SingleVisitor, - TSConstructorType?: SingleVisitor, - TSTypeReference?: SingleVisitor, - TSTypePredicate?: SingleVisitor, - TSTypeQuery?: SingleVisitor, - TSTypeLiteral?: SingleVisitor, - TSArrayType?: SingleVisitor, - TSTupleType?: SingleVisitor, - TSOptionalType?: SingleVisitor, - TSRestType?: SingleVisitor, - TSUnionType?: SingleVisitor, - TSIntersectionType?: SingleVisitor, - TSConditionalType?: SingleVisitor, - TSInferType?: SingleVisitor, - TSParenthesizedType?: SingleVisitor, - TSTypeOperator?: SingleVisitor, - TSIndexedAccessType?: SingleVisitor, - TSMappedType?: SingleVisitor, - TSLiteralType?: SingleVisitor, - TSExpressionWithTypeArguments?: SingleVisitor< - t.TSExpressionWithTypeArguments, - S, - >, - TSInterfaceDeclaration?: SingleVisitor, - TSInterfaceBody?: SingleVisitor, - TSTypeAliasDeclaration?: SingleVisitor, - TSAsExpression?: SingleVisitor, - TSTypeAssertion?: SingleVisitor, - TSEnumDeclaration?: SingleVisitor, - TSEnumMember?: SingleVisitor, - TSModuleDeclaration?: SingleVisitor, - TSModuleBlock?: SingleVisitor, - TSImportType?: SingleVisitor, - TSImportEqualsDeclaration?: SingleVisitor, - TSExternalModuleReference?: SingleVisitor, - TSNonNullExpression?: SingleVisitor, - TSExportAssignment?: SingleVisitor, - TSNamespaceExportDeclaration?: SingleVisitor< - t.TSNamespaceExportDeclaration, - S, - >, - TSTypeAnnotation?: SingleVisitor, - TSTypeParameterInstantiation?: SingleVisitor< - t.TSTypeParameterInstantiation, - S, - >, - TSTypeParameterDeclaration?: SingleVisitor, - TSTypeParameter?: SingleVisitor, - Expression?: SingleVisitor, - Binary?: SingleVisitor, - Scopable?: SingleVisitor, - BlockParent?: SingleVisitor, - Block?: SingleVisitor, - Statement?: SingleVisitor, - Terminatorless?: SingleVisitor, - CompletionStatement?: SingleVisitor, - Conditional?: SingleVisitor, - Loop?: SingleVisitor, - While?: SingleVisitor, - ExpressionWrapper?: SingleVisitor, - For?: SingleVisitor, - ForXStatement?: SingleVisitor, - FunctionParent?: SingleVisitor, - Pureish?: SingleVisitor, - Declaration?: SingleVisitor, - PatternLike?: SingleVisitor, - LVal?: SingleVisitor, - TSEntityName?: SingleVisitor, - Literal?: SingleVisitor, - Immutable?: SingleVisitor, - UserWhitespacable?: SingleVisitor, - Method?: SingleVisitor, - ObjectMember?: SingleVisitor, - Property?: SingleVisitor, - UnaryLike?: SingleVisitor, - Pattern?: SingleVisitor, - ModuleDeclaration?: SingleVisitor, - ExportDeclaration?: SingleVisitor, - ModuleSpecifier?: SingleVisitor, - Flow?: SingleVisitor, - FlowType?: SingleVisitor, - FlowBaseAnnotation?: SingleVisitor, - FlowDeclaration?: SingleVisitor, - FlowPredicate?: SingleVisitor, - EnumBody?: SingleVisitor, - EnumMember?: SingleVisitor, - JSX?: SingleVisitor, - Private?: SingleVisitor, - TSTypeElement?: SingleVisitor, - TSType?: SingleVisitor, - [string]: SingleVisitor, - ... -}; - -export type SimpleVisitors = { - [string]: F | {|enter?: F, exit?: F|}, - shouldSkip?: t.Node => boolean, - ... -}; - -export type VisitorsExploded = { - [string]: {| - enter?: Array, - exit?: Array, - |}, - shouldSkip?: t.Node => boolean, - ... -}; diff --git a/packages/utils/create-react-app/package.json b/packages/utils/create-react-app/package.json index 602fa211a65..892042cc796 100644 --- a/packages/utils/create-react-app/package.json +++ b/packages/utils/create-react-app/package.json @@ -4,7 +4,7 @@ "bin": { "parcel-create-react-app": "src/bin.js" }, - "main": "lib/bin.js", + "main": "src/bin.js", "repository": { "type": "git", "url": "https://github.com/parcel-bundler/parcel.git", diff --git a/packages/utils/fs-write-stream-atomic/index.js b/packages/utils/fs-write-stream-atomic/index.js index e2198a90ac1..849ea300260 100644 --- a/packages/utils/fs-write-stream-atomic/index.js +++ b/packages/utils/fs-write-stream-atomic/index.js @@ -1,5 +1,5 @@ var fs = require('graceful-fs'); -var Writable = require('readable-stream').Writable; +var Writable = require('stream').Writable; var util = require('util'); var MurmurHash3 = require('imurmurhash'); var iferr = require('iferr'); @@ -64,25 +64,25 @@ function WriteStreamAtomic(path, options) { // data has been written to our target stream. So we suppress // finish from being emitted here, and only emit it after our // target stream is closed and we've moved everything around. -WriteStreamAtomic.prototype.emit = function(event) { +WriteStreamAtomic.prototype.emit = function (event) { if (event === 'finish') return this.__atomicStream.end(); return Writable.prototype.emit.apply(this, arguments); }; -WriteStreamAtomic.prototype._write = function(buffer, encoding, cb) { +WriteStreamAtomic.prototype._write = function (buffer, encoding, cb) { var flushed = this.__atomicStream.write(buffer, encoding); if (flushed) return cb(); this.__atomicStream.once('drain', cb); }; function handleOpen(writeStream) { - return function(fd) { + return function (fd) { writeStream.emit('open', fd); }; } function handleClose(writeStream) { - return function() { + return function () { if (writeStream.__atomicClosed) return; writeStream.__atomicClosed = true; if (writeStream.__atomicChown) { @@ -127,13 +127,13 @@ function handleClose(writeStream) { var targetFileHash = crypto.createHash('sha512'); fs.createReadStream(writeStream.__atomicTmp) - .on('data', function(data, enc) { + .on('data', function (data, enc) { tmpFileHash.update(data, enc); }) .on('error', fileHashError) .on('end', fileHashComplete); fs.createReadStream(writeStream.__atomicTarget) - .on('data', function(data, enc) { + .on('data', function (data, enc) { targetFileHash.update(data, enc); }) .on('error', fileHashError) @@ -157,7 +157,7 @@ function handleClose(writeStream) { } function cleanup(err) { - fs.unlink(writeStream.__atomicTmp, function() { + fs.unlink(writeStream.__atomicTmp, function () { if (err) { writeStream.emit('error', err); writeStream.emit('close'); @@ -175,14 +175,14 @@ function handleClose(writeStream) { // Delay the close to provide the same temporal separation a physical // file operation would have– that is, the close event is emitted only // after the async close operation completes. - setImmediate(function() { + setImmediate(function () { writeStream.emit('close'); }); } } function handleError(writeStream) { - return function(er) { + return function (er) { cleanupSync(); writeStream.emit('error', er); writeStream.__atomicClosed = true; diff --git a/packages/utils/fs-write-stream-atomic/package.json b/packages/utils/fs-write-stream-atomic/package.json index 7deae898eb7..97337389326 100644 --- a/packages/utils/fs-write-stream-atomic/package.json +++ b/packages/utils/fs-write-stream-atomic/package.json @@ -21,8 +21,7 @@ "dependencies": { "graceful-fs": "^4.1.2", "iferr": "^1.0.2", - "imurmurhash": "^0.1.4", - "readable-stream": "1 || 2" + "imurmurhash": "^0.1.4" }, "author": "Isaac Z. Schlueter (http://blog.izs.me/)", "license": "ISC" diff --git a/packages/utils/node-libs-browser/LICENSE b/packages/utils/node-libs-browser/LICENSE deleted file mode 100755 index b6f8f4003c1..00000000000 --- a/packages/utils/node-libs-browser/LICENSE +++ /dev/null @@ -1,22 +0,0 @@ -(The MIT License) - -Copyright (c) 2012 Tobias Koppers - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -'Software'), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/packages/utils/node-libs-browser/index.js b/packages/utils/node-libs-browser/index.js deleted file mode 100755 index 86d67d50214..00000000000 --- a/packages/utils/node-libs-browser/index.js +++ /dev/null @@ -1,40 +0,0 @@ -exports.assert = require.resolve('assert/'); -exports.async_hooks = null; -exports.buffer = require.resolve('buffer/'); -exports.child_process = null; -exports.cluster = null; -exports.console = require.resolve('console-browserify'); -exports.constants = require.resolve('constants-browserify'); -exports.crypto = require.resolve('crypto-browserify'); -exports.dgram = null; -exports.dns = null; -exports.domain = require.resolve('domain-browser'); -exports.events = require.resolve('events/'); -exports.fs = null; -exports.http = require.resolve('stream-http'); -exports.http2 = null; -exports.https = require.resolve('https-browserify'); -exports.inspector = null; -exports.module = null; -exports.net = null; -exports.os = require.resolve('os-browserify/browser.js'); -exports.path = require.resolve('path-browserify'); -exports.perf_hooks = null; -exports.process = require.resolve('process/browser.js'); -exports.punycode = require.resolve('punycode/'); -exports.querystring = require.resolve('querystring-es3/'); -exports.readline = null; -exports.repl = null; -exports.stream = require.resolve('stream-browserify'); -exports.string_decoder = require.resolve('string_decoder/'); -exports.sys = require.resolve('util/util.js'); -exports.timers = require.resolve('timers-browserify'); -exports.tls = null; -exports.trace_events = null; -exports.tty = require.resolve('tty-browserify'); -exports.url = require.resolve('url/'); -exports.util = require.resolve('util/util.js'); -exports.v8 = null; -exports.vm = require.resolve('vm-browserify'); -exports.worker_threads = null; -exports.zlib = require.resolve('browserify-zlib'); diff --git a/packages/utils/node-libs-browser/package.json b/packages/utils/node-libs-browser/package.json deleted file mode 100755 index 9bfed494328..00000000000 --- a/packages/utils/node-libs-browser/package.json +++ /dev/null @@ -1,46 +0,0 @@ -{ - "name": "@parcel/node-libs-browser", - "version": "2.0.15", - "author": "Tobias Koppers @sokra", - "description": "The node core libs for in browser usage.", - "license": "MIT", - "publishConfig": { - "access": "public" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - }, - "repository": { - "type": "git", - "url": "https://github.com/parcel-bundler/parcel.git" - }, - "main": "index.js", - "engines": { - "node": ">= 12.0.0" - }, - "dependencies": { - "assert": "^2.0.0", - "browserify-zlib": "^0.2.0", - "buffer": "^5.5.0", - "console-browserify": "^1.2.0", - "constants-browserify": "^1.0.0", - "crypto-browserify": "^3.12.0", - "domain-browser": "^3.5.0", - "events": "^3.1.0", - "https-browserify": "^1.0.0", - "os-browserify": "^0.3.0", - "path-browserify": "^1.0.0", - "process": "^0.11.10", - "punycode": "^1.4.1", - "querystring-es3": "^0.2.1", - "stream-browserify": "^3.0.0", - "stream-http": "^3.1.0", - "string_decoder": "^1.3.0", - "timers-browserify": "^2.0.11", - "tty-browserify": "^0.0.1", - "url": "^0.11.0", - "util": "^0.12.3", - "vm-browserify": "^1.1.2" - } -} diff --git a/packages/utils/node-resolver-core/package.json b/packages/utils/node-resolver-core/package.json index a39a93ed4ea..4dcc6b7ee75 100644 --- a/packages/utils/node-resolver-core/package.json +++ b/packages/utils/node-resolver-core/package.json @@ -20,9 +20,31 @@ }, "dependencies": { "@parcel/diagnostic": "2.0.15", - "@parcel/node-libs-browser": "2.0.15", "@parcel/utils": "2.0.15", - "micromatch": "^4.0.4", "nullthrows": "^1.1.1" + }, + "devDependencies": { + "assert": "^2.0.0", + "browserify-zlib": "^0.2.0", + "buffer": "^5.5.0", + "console-browserify": "^1.2.0", + "constants-browserify": "^1.0.0", + "crypto-browserify": "^3.12.0", + "domain-browser": "^3.5.0", + "events": "^3.1.0", + "https-browserify": "^1.0.0", + "os-browserify": "^0.3.0", + "path-browserify": "^1.0.0", + "process": "^0.11.10", + "punycode": "^1.4.1", + "querystring-es3": "^0.2.1", + "stream-browserify": "^3.0.0", + "stream-http": "^3.1.0", + "string_decoder": "^1.3.0", + "timers-browserify": "^2.0.11", + "tty-browserify": "^0.0.1", + "url": "^0.11.0", + "util": "^0.12.3", + "vm-browserify": "^1.1.2" } } diff --git a/packages/utils/node-resolver-core/src/NodeResolver.js b/packages/utils/node-resolver-core/src/NodeResolver.js index 6bf886c6900..796aca7569c 100644 --- a/packages/utils/node-resolver-core/src/NodeResolver.js +++ b/packages/utils/node-resolver-core/src/NodeResolver.js @@ -6,8 +6,11 @@ import type { ResolveResult, Environment, SpecifierType, + PluginLogger, + SourceLocation, } from '@parcel/types'; import type {FileSystem} from '@parcel/fs'; +import type {PackageManager} from '@parcel/package-manager'; import invariant from 'assert'; import path from 'path'; @@ -18,12 +21,13 @@ import { findAlternativeNodeModules, findAlternativeFiles, loadConfig, + globToRegex, + isGlobMatch, } from '@parcel/utils'; import ThrowableDiagnostic, { generateJSONCodeHighlights, md, } from '@parcel/diagnostic'; -import micromatch from 'micromatch'; import builtins, {empty} from './builtins'; import nullthrows from 'nullthrows'; import _Module from 'module'; @@ -37,6 +41,8 @@ type Options = {| projectRoot: FilePath, extensions: Array, mainFields: Array, + packageManager?: PackageManager, + logger?: PluginLogger, aliasField?: string, |}; type ResolvedFile = {| @@ -66,6 +72,7 @@ type ResolverContext = {| invalidateOnFileCreate: Array, invalidateOnFileChange: Set, specifierType: SpecifierType, + loc: ?SourceLocation, |}; /** @@ -88,6 +95,8 @@ export default class NodeResolver { mainFields: Array; packageCache: Map; rootPackage: InternalPackageJSON | null; + packageManager: ?PackageManager; + logger: ?PluginLogger; // ATLASSIAN: Allow a custom fieldname to be specified so that we can have different aliases for different builds (i.e. SSR and client side builds) aliasField: string; @@ -100,6 +109,8 @@ export default class NodeResolver { this.projectRoot = opts.projectRoot; this.packageCache = new Map(); this.rootPackage = null; + this.packageManager = opts.packageManager; + this.logger = opts.logger; // ATLASSIAN: Allow a custom fieldname to be specified so that we can have different aliases for different builds (i.e. SSR and client side builds) this.aliasField = opts.aliasField ? opts.aliasField : 'alias'; } @@ -110,17 +121,20 @@ export default class NodeResolver { specifierType, env, sourcePath, + loc, }: {| filename: FilePath, parent: ?FilePath, specifierType: SpecifierType, env: Environment, sourcePath?: ?FilePath, + loc?: ?SourceLocation, |}): Promise { let ctx = { invalidateOnFileCreate: [], invalidateOnFileChange: new Set(), specifierType, + loc, }; // Get file extensions to search @@ -214,6 +228,7 @@ export default class NodeResolver { ctx: ResolverContext, sourcePath: ?FilePath, |}): Promise { + let specifier = filename; let sourceFile = parent || path.join(this.projectRoot, 'index'); let query; @@ -257,19 +272,19 @@ export default class NodeResolver { let builtin = this.findBuiltin(filename, env); if (builtin === null) { return null; + } else if (builtin === empty) { + return {filePath: empty}; + } else if (builtin !== undefined) { + filename = builtin; } - if (!this.shouldIncludeNodeModule(env, filename)) { + if (this.shouldIncludeNodeModule(env, filename) === false) { if (sourcePath && env.isLibrary && !builtin) { await this.checkExcludedDependency(sourcePath, filename, ctx); } return null; } - if (builtin) { - return builtin; - } - // Resolve the module in node_modules let resolved: ?Module; try { @@ -278,6 +293,70 @@ export default class NodeResolver { // ignore } + // Auto install node builtin polyfills if not already available + if (resolved === undefined && builtin != null) { + let packageName = builtin.split('/')[0]; + let packageManager = this.packageManager; + if (packageManager) { + this.logger?.warn({ + message: md`Auto installing polyfill for Node builtin module "${specifier}"...`, + codeFrames: [ + { + filePath: ctx.loc?.filePath ?? sourceFile, + codeHighlights: ctx.loc + ? [ + { + message: 'used here', + start: ctx.loc.start, + end: ctx.loc.end, + }, + ] + : [], + }, + ], + documentationURL: + 'https://parceljs.org/features/node-emulation/#polyfilling-%26-excluding-builtin-node-modules', + }); + + await packageManager.resolve(builtin, this.projectRoot + '/index', { + saveDev: true, + shouldAutoInstall: true, + }); + + // Re-resolve + try { + resolved = this.findNodeModulePath(filename, sourceFile, ctx); + } catch (err) { + // ignore + } + } else { + throw new ThrowableDiagnostic({ + diagnostic: { + message: md`Node builtin polyfill "${packageName}" is not installed, but auto install is disabled.`, + codeFrames: [ + { + filePath: ctx.loc?.filePath ?? sourceFile, + codeHighlights: ctx.loc + ? [ + { + message: 'used here', + start: ctx.loc.start, + end: ctx.loc.end, + }, + ] + : [], + }, + ], + documentationURL: + 'https://parceljs.org/features/node-emulation/#polyfilling-%26-excluding-builtin-node-modules', + hints: [ + md`Install the "${packageName}" package with your package manager, and run Parcel again.`, + ], + }, + }); + } + } + if (resolved === undefined && process.versions.pnp != null && parent) { try { let [moduleName, subPath] = this.getModuleParts(filename); @@ -345,7 +424,7 @@ export default class NodeResolver { shouldIncludeNodeModule( {includeNodeModules}: Environment, name: string, - ): boolean { + ): ?boolean { if (includeNodeModules === false) { return false; } @@ -362,8 +441,6 @@ export default class NodeResolver { return !!include; } } - - return true; } async checkExcludedDependency( @@ -597,7 +674,7 @@ export default class NodeResolver { return resolvedFile; } - findBuiltin(filename: string, env: Environment): ?Module { + findBuiltin(filename: string, env: Environment): ?string { const isExplicitNode = filename.startsWith('node:'); if (isExplicitNode || builtins[filename]) { if (env.isNode()) { @@ -607,7 +684,16 @@ export default class NodeResolver { if (isExplicitNode) { filename = filename.substr(5); } - return {filePath: builtins[filename] || empty}; + + // By default, exclude node builtins from libraries unless explicitly opted in. + if ( + env.isLibrary && + this.shouldIncludeNodeModule(env, filename) !== true + ) { + return null; + } + + return builtins[filename] || empty; } if (env.isElectron() && filename === 'electron') { @@ -1093,7 +1179,7 @@ export default class NodeResolver { if (filename.startsWith('./')) { filename = filename.slice(2); } - let re = micromatch.makeRe(key, {capture: true}); + let re = globToRegex(key, {capture: true}); if (re.test(filename)) { alias = filename.replace(re, val); break; @@ -1190,7 +1276,7 @@ export default class NodeResolver { glob = glob.substr(2); } - return micromatch.isMatch(relative, glob, {dot: true}); + return isGlobMatch(relative, glob, {dot: true}); } case 'object': return pkg.sideEffects.some(sideEffects => diff --git a/packages/utils/node-resolver-core/src/builtins.js b/packages/utils/node-resolver-core/src/builtins.js index 9bc5b16470d..d733e527811 100644 --- a/packages/utils/node-resolver-core/src/builtins.js +++ b/packages/utils/node-resolver-core/src/builtins.js @@ -1,6 +1,5 @@ // @flow strict-local // $FlowFixMe this is untyped -import polyfills from '@parcel/node-libs-browser'; import {builtinModules} from 'module'; export const empty: string = require.resolve('./_empty.js'); @@ -11,9 +10,29 @@ let builtins: {[string]: any, ...} = Object.create(null); for (let key of builtinModules) { builtins[key] = empty; } -// load the polyfill where available -for (let key in polyfills) { - builtins[key] = polyfills[key] || empty; -} + +builtins.assert = 'assert/'; +builtins.buffer = 'buffer/'; +builtins.console = 'console-browserify'; +builtins.constants = 'constants-browserify'; +builtins.crypto = 'crypto-browserify'; +builtins.domain = 'domain-browser'; +builtins.events = 'events/'; +builtins.http = 'stream-http'; +builtins.https = 'https-browserify'; +builtins.os = 'os-browserify/browser.js'; +builtins.path = 'path-browserify'; +builtins.process = 'process/browser.js'; +builtins.punycode = 'punycode/'; +builtins.querystring = 'querystring-es3/'; +builtins.stream = 'stream-browserify'; +builtins.string_decoder = 'string_decoder/'; +builtins.sys = 'util/util.js'; +builtins.timers = 'timers-browserify'; +builtins.tty = 'tty-browserify'; +builtins.url = 'url/'; +builtins.util = 'util/util.js'; +builtins.vm = 'vm-browserify'; +builtins.zlib = 'browserify-zlib'; export default builtins; diff --git a/packages/utils/node-resolver-core/test/resolver.js b/packages/utils/node-resolver-core/test/resolver.js index b3f52708e68..d2ddb27ccdd 100644 --- a/packages/utils/node-resolver-core/test/resolver.js +++ b/packages/utils/node-resolver-core/test/resolver.js @@ -297,8 +297,8 @@ describe('resolver', function () { aboveFilePath: path.join(rootDir, 'foo.js'), }, { - fileName: 'package.json', - aboveFilePath: require.resolve('browserify-zlib'), + fileName: 'node_modules/browserify-zlib', + aboveFilePath: path.join(rootDir, 'foo.js'), }, ], invalidateOnFileChange: [ @@ -329,8 +329,8 @@ describe('resolver', function () { aboveFilePath: path.join(rootDir, 'foo.js'), }, { - fileName: 'package.json', - aboveFilePath: require.resolve('browserify-zlib'), + fileName: 'node_modules/browserify-zlib', + aboveFilePath: path.join(rootDir, 'foo.js'), }, ], invalidateOnFileChange: [ diff --git a/rust-toolchain b/rust-toolchain new file mode 100644 index 00000000000..2bf5ad0447d --- /dev/null +++ b/rust-toolchain @@ -0,0 +1 @@ +stable diff --git a/scripts/update-config-dependencies.js b/scripts/update-config-dependencies.js index 290d90949bf..f71faa192fc 100644 --- a/scripts/update-config-dependencies.js +++ b/scripts/update-config-dependencies.js @@ -1,7 +1,6 @@ const fs = require('fs'); const path = require('path'); const exec = require('child_process').execSync; -const semver = require('semver'); let packages = JSON.parse( exec( @@ -22,8 +21,7 @@ for (let config of configs) { throw new Error(`Unknown parcel dependency ${dep}`); } - pkg.parcelDependencies[dep] = - (semver.parse(version).prerelease.length === 0 ? '^' : '') + version; + pkg.parcelDependencies[dep] = version; } fs.writeFileSync(configPkgPath, JSON.stringify(pkg, null, 2) + '\n'); diff --git a/yarn.lock b/yarn.lock index 0a33439f447..fa13bbcd27a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -126,7 +126,7 @@ "@babel/helper-explode-assignable-expression" "^7.12.13" "@babel/types" "^7.12.13" -"@babel/helper-compilation-targets@^7.13.0", "@babel/helper-compilation-targets@^7.13.13", "@babel/helper-compilation-targets@^7.13.8", "@babel/helper-compilation-targets@^7.16.7", "@babel/helper-compilation-targets@^7.8.4": +"@babel/helper-compilation-targets@^7.13.0", "@babel/helper-compilation-targets@^7.13.13", "@babel/helper-compilation-targets@^7.13.8", "@babel/helper-compilation-targets@^7.16.7": version "7.16.7" resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.16.7.tgz#06e66c5f299601e6c7da350049315e83209d551b" integrity sha512-mGojBwIWcwGD6rfqgRXVlVYmPAv7eOpIemUG3dGnDdCY4Pae70ROij3XmfrH6Fa1h1aiDylpglbZyktfzyo/hA== @@ -330,7 +330,12 @@ chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/parser@^7.0.0", "@babel/parser@^7.12.7", "@babel/parser@^7.16.4", "@babel/parser@^7.16.7", "@babel/parser@^7.16.8", "@babel/parser@^7.6.0", "@babel/parser@^7.9.6": +"@babel/parser@^7.0.0": + version "7.17.3" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.17.3.tgz#b07702b982990bf6fdc1da5049a23fece4c5c3d0" + integrity sha512-7yJPvPV+ESz2IUTPbOL+YkIGyCqOyNIzdguKQuJGnH7bg1WTIifuM21YqokFt/THWh1AkCRn9IgoykTRCBVpzA== + +"@babel/parser@^7.12.7", "@babel/parser@^7.16.4", "@babel/parser@^7.16.7", "@babel/parser@^7.16.8", "@babel/parser@^7.6.0", "@babel/parser@^7.9.6": version "7.16.8" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.16.8.tgz#61c243a3875f7d0b0962b0543a33ece6ff2f1f17" integrity sha512-i7jDUfrVBWc+7OKcBzEe5n7fbv3i2fWtxKzzCvOjnzSxMfWMigAhtfJ7qzZNGFNMsCCd67+uz553dYKWXPvCKw== @@ -673,7 +678,7 @@ "@babel/helper-builder-binary-assignment-operator-visitor" "^7.12.13" "@babel/helper-plugin-utils" "^7.12.13" -"@babel/plugin-transform-flow-strip-types@^7.0.0", "@babel/plugin-transform-flow-strip-types@^7.13.0", "@babel/plugin-transform-flow-strip-types@^7.2.0": +"@babel/plugin-transform-flow-strip-types@^7.13.0", "@babel/plugin-transform-flow-strip-types@^7.2.0": version "7.13.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.13.0.tgz#58177a48c209971e8234e99906cb6bd1122addd3" integrity sha512-EXAGFMJgSX8gxWD7PZtW/P6M+z74jpx3wm/+9pn+c2dOawPpBkUX7BrfyPvo6ZpXbgRIEuwgwDb/MGlKvu2pOg== @@ -1046,7 +1051,7 @@ "@babel/parser" "^7.16.7" "@babel/types" "^7.16.7" -"@babel/traverse@^7.0.0", "@babel/traverse@^7.12.9", "@babel/traverse@^7.13.0", "@babel/traverse@^7.14.5", "@babel/traverse@^7.16.7": +"@babel/traverse@^7.12.9", "@babel/traverse@^7.13.0", "@babel/traverse@^7.14.5", "@babel/traverse@^7.16.7": version "7.16.8" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.16.8.tgz#bab2f2b09a5fe8a8d9cad22cbfe3ba1d126fef9c" integrity sha512-xe+H7JlvKsDQwXRsBhSnq1/+9c+LlQcCK3Tn/l5sbx02HYns/cn7ibp9+RV1sIUqu7hKg91NWsgHurO9dowITQ== @@ -1078,7 +1083,7 @@ debug "^4.1.0" globals "^11.1.0" -"@babel/types@^7.12.1", "@babel/types@^7.12.13", "@babel/types@^7.12.7", "@babel/types@^7.13.0", "@babel/types@^7.13.12", "@babel/types@^7.13.14", "@babel/types@^7.14.5", "@babel/types@^7.15.6", "@babel/types@^7.16.7", "@babel/types@^7.16.8", "@babel/types@^7.4.4", "@babel/types@^7.6.1", "@babel/types@^7.9.0", "@babel/types@^7.9.6": +"@babel/types@^7.12.0", "@babel/types@^7.12.1", "@babel/types@^7.12.13", "@babel/types@^7.12.7", "@babel/types@^7.13.0", "@babel/types@^7.13.12", "@babel/types@^7.13.14", "@babel/types@^7.14.5", "@babel/types@^7.15.6", "@babel/types@^7.16.7", "@babel/types@^7.16.8", "@babel/types@^7.4.4", "@babel/types@^7.6.1", "@babel/types@^7.9.0", "@babel/types@^7.9.6": version "7.16.8" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.16.8.tgz#0ba5da91dd71e0a4e7781a30f22770831062e3c1" integrity sha512-smN2DQc5s4M7fntyjGtyIPbRJv6wW4rU/94fmYJ7PKQuZkC0qGMHXJbg6sNGt12JmVr4k5YaptI/XtiLJBnmIg== @@ -3407,9 +3412,9 @@ astral-regex@^2.0.0: integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== astring@^1.6.2: - version "1.6.2" - resolved "https://registry.yarnpkg.com/astring/-/astring-1.6.2.tgz#6e02d56a5b2a97c09ecb52e8aff8c7e634a21e2b" - integrity sha512-STGFbQN/qccrGAxqsnFkqAeVNTCvgN5uiD+vd75DNDvsoYZkDtYwW1rZvM/8xY1lMtOfisqh+MBU4ilsbLhd2g== + version "1.8.1" + resolved "https://registry.yarnpkg.com/astring/-/astring-1.8.1.tgz#a91c4afd4af3523e11f31242a3d5d9af62bb6cc6" + integrity sha512-Aj3mbwVzj7Vve4I/v2JYOPFkCGM2YS7OqQTNSxmUR+LECRpokuPgAYghePgr6SALDo5bD5DlfbSaYjOzGJZOLQ== async-done@^1.2.0, async-done@^1.2.2: version "1.3.2" @@ -5017,14 +5022,6 @@ dateformat@^3.0.0: resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae" integrity sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q== -deasync@^0.1.14: - version "0.1.19" - resolved "https://registry.yarnpkg.com/deasync/-/deasync-0.1.19.tgz#e7ea89fcc9ad483367e8a48fe78f508ca86286e8" - integrity sha512-oh3MRktfnPlLysCPpBpKZZzb4cUC/p0aA3SyRGp15lN30juJBTo/CiD0d4fR+f1kBtUQoJj1NE9RPNWQ7BQ9Mg== - dependencies: - bindings "^1.5.0" - node-addon-api "^1.7.1" - debug@*, debug@4, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1: version "4.3.3" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664" @@ -6499,10 +6496,10 @@ flatted@^3.1.0: resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.1.1.tgz#c4b489e80096d9df1dfc97c79871aea7c617c469" integrity sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA== -flow-bin@0.164.0: - version "0.164.0" - resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.164.0.tgz#dc2a1f1cd59670e7d95320232a673c6e31b11ff3" - integrity sha512-cSAA0LLa1SlQ1YmNCYpJ19ES39WYrqjfxX8Oqhbvn6+DET8Cs+EnVkJWHVSkfK8zUupbxvSt7pDoFXePYbcJRA== +flow-bin@0.173.0: + version "0.173.0" + resolved "https://packages.atlassian.com/api/npm/npm-remote/flow-bin/-/flow-bin-0.173.0.tgz#4eb4b0143ffcef3ef3ee64638554a8dff6b89735" + integrity sha512-CIvShSnB4I7SsfkE9S7ECpUCkBNqDQGDWr+0uzulKGYEBnCYwFzITE1T84weLmINQwO1dR6ntsH0LlWLoGCquQ== flush-write-stream@^1.0.0, flush-write-stream@^1.0.2: version "1.1.1" @@ -8669,16 +8666,16 @@ listr2@^3.2.2: through "^2.3.8" wrap-ansi "^7.0.0" -lmdb@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/lmdb/-/lmdb-2.0.2.tgz#bdd78a686a4423cf2aaea38fb2acebbd1aca9f02" - integrity sha512-B0f4UePBHHsqVRrYJgNnlzDuhjjaCvyqugV3ZY7YO+9kLcoK/Fqm5yi4icTVIr+ijeVleN69puyx/2KSKVvtQw== +lmdb@2.2.4, lmdb@^2.0.2: + version "2.2.4" + resolved "https://registry.yarnpkg.com/lmdb/-/lmdb-2.2.4.tgz#6494d5a1d1db152e0be759edcfa06893e4cbdb53" + integrity sha512-gto+BB2uEob8qRiTlOq+R3uX0YNHsX9mjxj9Sbdue/LIKqu6IlZjrsjKeGyOMquc/474GEqFyX2pdytpydp0rQ== dependencies: - msgpackr "^1.5.0" + msgpackr "^1.5.4" nan "^2.14.2" node-gyp-build "^4.2.3" - ordered-binary "^1.1.0" - weak-lru-cache "^1.1.0" + ordered-binary "^1.2.4" + weak-lru-cache "^1.2.2" load-json-file@^1.0.0: version "1.1.0" @@ -9417,10 +9414,10 @@ msgpackr-extract@^1.0.14: nan "^2.14.2" node-gyp-build "^4.2.3" -msgpackr@^1.5.0, msgpackr@^1.5.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/msgpackr/-/msgpackr-1.5.1.tgz#2a8e39d25458406034b8cb50dc7d6a7abd3dfff2" - integrity sha512-I1CXFG8BYYSeIhtDlHpUVMsdDiyvP9JAh1d9QoBnkPx3ETPeH/1lR14hweM9GETs09wCWlaOyhtXxIc9boxAAA== +msgpackr@^1.5.4: + version "1.5.4" + resolved "https://registry.yarnpkg.com/msgpackr/-/msgpackr-1.5.4.tgz#2b6ea6cb7d79c0ad98fc76c68163c48eda50cf0d" + integrity sha512-Z7w5Jg+2Q9z9gJxeM68d7tSuWZZGnFIRhZnyqcZCa/1dKkhOCNvR1TUV3zzJ3+vj78vlwKRzUgVDlW4jiSOeDA== optionalDependencies: msgpackr-extract "^1.0.14" @@ -9559,11 +9556,6 @@ node-abi@^2.21.0: dependencies: semver "^5.4.1" -node-addon-api@^1.7.1: - version "1.7.1" - resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-1.7.1.tgz#cf813cd69bb8d9100f6bdca6755fc268f54ac492" - integrity sha512-2+DuKodWvwRTrCfKOeR24KIc5unKjOh8mz17NCzVnHWfjAdDqbfbjqh7gUT+BkXBRQM52+xCHciKWonJ3CbJMQ== - node-addon-api@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-3.2.1.tgz#81325e0a2117789c0128dab65e7e38f07ceba161" @@ -10017,10 +10009,10 @@ ora@^5.2.0: strip-ansi "^6.0.0" wcwidth "^1.0.1" -ordered-binary@^1.1.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/ordered-binary/-/ordered-binary-1.1.3.tgz#11dbc0a4cb7f8248183b9845e031b443be82571e" - integrity sha512-tDTls+KllrZKJrqRXUYJtIcWIyoQycP7cVN7kzNNnhHKF2bMKHflcAQK+pF2Eb1iVaQodHxqZQr0yv4HWLGBhQ== +ordered-binary@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/ordered-binary/-/ordered-binary-1.2.4.tgz#51d3a03af078a0bdba6c7bc8f4fedd1f5d45d83e" + integrity sha512-A/csN0d3n+igxBPfUrjbV5GC69LWj2pjZzAAeeHXLukQ4+fytfP4T1Lg0ju7MSPSwq7KtHkGaiwO8URZN5IpLg== ordered-read-streams@^1.0.0: version "1.0.1" @@ -11890,7 +11882,7 @@ rimraf@2.6.3, rimraf@~2.6.2: dependencies: glob "^7.1.3" -rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.2, rimraf@^2.6.3: +rimraf@^2.5.4, rimraf@^2.6.2, rimraf@^2.6.3: version "2.7.1" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== @@ -14115,10 +14107,10 @@ wcwidth@^1.0.0, wcwidth@^1.0.1: dependencies: defaults "^1.0.3" -weak-lru-cache@^1.1.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/weak-lru-cache/-/weak-lru-cache-1.1.3.tgz#8a691884501b611d2b5aeac1ee5a011b2a97d9a8" - integrity sha512-5LDIv+sr6uzT94Hhcq7Qv7gt3jxol4iMWUqOgJSLYbB5oO7bTSMqIBtKsytm8N2BufYOdJw86/qu+SDfbo/wKQ== +weak-lru-cache@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/weak-lru-cache/-/weak-lru-cache-1.2.2.tgz#fdbb6741f36bae9540d12f480ce8254060dccd19" + integrity sha512-DEAoo25RfSYMuTGc9vPJzZcZullwIqRDSI9LOy+fkCJPi6hykCnfKaXTuPBDuXAUcqHXyOgFtHNp/kB2FjYHbw== web-namespaces@^1.0.0: version "1.1.3"