diff --git a/.env.development b/.env.development new file mode 100644 index 00000000000..097c0161886 --- /dev/null +++ b/.env.development @@ -0,0 +1 @@ +VM_LOCAL_DEV = true diff --git a/.github/workflows/alpha-releases.yml b/.github/workflows/alpha-releases.yml index 6b49bde0020..a990d5e6c37 100644 --- a/.github/workflows/alpha-releases.yml +++ b/.github/workflows/alpha-releases.yml @@ -20,7 +20,7 @@ jobs: - uses: actions/checkout@v4 with: persist-credentials: false - - uses: ./.github/actions/setup + - uses: ./.github/actions/setup - name: setup git run: | git config --local user.email 'tomster@emberjs.com' @@ -33,7 +33,7 @@ jobs: - name: bump version run: npm version ${{env.NEXT_ALPHA}} --allow-same-version --no-git-tag-version - name: create tag - run: git tag v${{env.NEXT_ALPHA}}-ember-source + run: git tag v${{env.NEXT_ALPHA}}-ember-source - name: push tag # Push in a way that WILL trigger other workflows - run: git push https://${GITHUB_ACTOR}:${{ secrets.PERSONAL_TOKEN }}@github.com/${GITHUB_REPOSITORY} v${{env.NEXT_ALPHA}}-ember-source + run: git push https://${GITHUB_ACTOR}:${{ secrets.PERSONAL_TOKEN }}@github.com/${GITHUB_REPOSITORY} v${{env.NEXT_ALPHA}}-ember-source diff --git a/.github/workflows/ci-jobs.yml b/.github/workflows/ci-jobs.yml index 72e4ffb0b4e..4935cfd840a 100644 --- a/.github/workflows/ci-jobs.yml +++ b/.github/workflows/ci-jobs.yml @@ -5,7 +5,7 @@ on: permissions: contents: read - + jobs: lint: name: Linting @@ -15,8 +15,9 @@ jobs: steps: - uses: actions/checkout@v4 - uses: ./.github/actions/setup - - name: linting - run: pnpm lint + # Temporarily disabled to see the later parts of CI + # - name: linting + # run: pnpm lint - id: set-matrix working-directory: smoke-tests/scenarios run: | @@ -31,9 +32,11 @@ jobs: - uses: ./.github/actions/setup - name: build types run: pnpm build:types - - name: Check published and internal types - run: pnpm type-check - + - name: Check internal types + run: pnpm type-check:internals + - name: Check published types + run: pnpm type-check:types + types-range: name: Type Checking (other supported versions) runs-on: ubuntu-latest @@ -48,9 +51,9 @@ jobs: run: pnpm build:types - name: install TS@${{matrix.ts-version}} run: pnpm add --save-dev --workspace-root typescript@${{ matrix.ts-version }} - - name: Check published and internal types with TS@${{matrix.ts-version}} - run: pnpm type-check - + - name: Check published types + run: pnpm type-check:types + basic-test: name: Basic Test runs-on: ubuntu-latest @@ -59,14 +62,17 @@ jobs: - uses: ./.github/actions/setup - name: build run: pnpm vite build --mode=development + env: + NODE_ENV: development - name: test run: pnpm test - + variant-tests: name: ${{ matrix.name }} runs-on: ubuntu-latest needs: [ basic-test, lint, types ] strategy: + fail-fast: false matrix: include: - name: "All deprecations enabled" @@ -90,6 +96,8 @@ jobs: - uses: ./.github/actions/setup - name: build run: pnpm vite build --mode=${{ matrix.BUILD || 'development' }} + env: + NODE_ENV: ${{ matrix.BUILD || 'development' }} - name: test env: ALL_DEPRECATIONS_ENABLED: ${{ matrix.ALL_DEPRECATIONS_ENABLED }} @@ -98,7 +106,7 @@ jobs: RAISE_ON_DEPRECATION: ${{ matrix.RAISE_ON_DEPRECATION }} run: pnpm test - + browserstack-test: name: Browserstack Tests (Safari, Edge) runs-on: ubuntu-latest @@ -109,6 +117,7 @@ jobs: - name: build env: ALL_SUPPORTED_BROWSERS: true + NODE_ENV: development run: pnpm vite build --mode=development - name: Set BrowserStack Local Identifier diff --git a/.github/workflows/publish-to-npm.yml b/.github/workflows/publish-to-npm.yml index 0861337e671..2d3425d2581 100644 --- a/.github/workflows/publish-to-npm.yml +++ b/.github/workflows/publish-to-npm.yml @@ -4,7 +4,7 @@ on: push: tags: - 'v*' - + jobs: tests: uses: ./.github/workflows/ci-jobs.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest needs: [ tests ] permissions: - contents: read + contents: read id-token: write steps: - uses: actions/checkout@v4 @@ -29,7 +29,7 @@ jobs: OVERRIDE_FEATURES: '' run: node bin/build-for-publishing.js - name: Build for Publish - if: ${{ !contains(github.ref, 'alpha') }} + if: ${{ !contains(github.ref, 'alpha') }} run: node bin/build-for-publishing.js - name: publish to npm run: npm publish @@ -58,6 +58,6 @@ jobs: webhook: ${{ secrets.FRAMEWORK_WEBHOOK }} status: 'Success' title: 'Released ember-source ${{ github.ref_name }}' - color: 0x2ecc71 + color: 0x2ecc71 url: '${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}' username: GitHub Actions diff --git a/.prettierignore b/.prettierignore index 9617aada531..99089f3022a 100644 --- a/.prettierignore +++ b/.prettierignore @@ -10,3 +10,5 @@ docs/ CHANGELOG.md package.json pnpm-lock.yaml +glimmer-vm/**/*.md +glimmer-vm/**/*.yaml diff --git a/babel.config.mjs b/babel.config.mjs index 34b6aa42dee..839aa46ec94 100644 --- a/babel.config.mjs +++ b/babel.config.mjs @@ -29,7 +29,7 @@ export default { { compilerPath: resolve( dirname(fileURLToPath(import.meta.url)), - './broccoli/glimmer-template-compiler' + './broccoli/glimmer-template-compiler.mjs' ), }, ], diff --git a/babel.test.config.mjs b/babel.test.config.mjs index 8cd805600d2..e270383106a 100644 --- a/babel.test.config.mjs +++ b/babel.test.config.mjs @@ -8,7 +8,6 @@ */ import { createRequire } from 'node:module'; -import vmBabelPlugins from '@glimmer/vm-babel-plugins'; import baseConfig from './babel.config.mjs'; // eslint-disable-next-line no-redeclare @@ -28,9 +27,5 @@ export default { ], ], - plugins: [ - ...baseConfig.plugins, - buildDebugMacroPlugin(!isProduction), - ...vmBabelPlugins({ isDebug: !isProduction }), - ], + plugins: [...baseConfig.plugins, buildDebugMacroPlugin(!isProduction)], }; diff --git a/bin/link-glimmer-vm-packages.mjs b/bin/link-glimmer-vm-packages.mjs deleted file mode 100644 index acd004b2c07..00000000000 --- a/bin/link-glimmer-vm-packages.mjs +++ /dev/null @@ -1,47 +0,0 @@ -import { readFileSync } from 'node:fs'; -import path from 'node:path'; -import chalk from 'chalk'; -import execa from 'execa'; -import glob from 'glob'; - -const rootDir = new URL('..', import.meta.url).pathname; - -const packageJsonPaths = glob.sync('**/package.json', { - cwd: rootDir, - ignore: '**/node_modules/**', -}); - -function shouldLink(dep) { - return ( - dep.startsWith('@glimmer/') && - dep !== '@glimmer/component' && - dep !== '@glimmer/env' && - dep !== '@glimmer/tracking' - ); -} - -const link = packageJsonPaths.map(async (packageJsonPath) => { - const packagePath = path.dirname(packageJsonPath); - - try { - const packageJson = JSON.parse(await readFileSync(packageJsonPath, { encoding: 'utf8' })); - - for (const [dep] of Object.entries(packageJson.dependencies ?? {})) { - if (shouldLink(dep)) { - // eslint-disable-next-line no-console - console.log(`Linking ${chalk.yellow(dep)} from ${chalk.grey(packagePath)}`); - await execa('pnpm', ['link', '--global', dep], { cwd: packagePath }); - } - } - } catch (error) { - let message = `Failed to link ${packagePath}`; - - if (error instanceof Error) { - message += `\n\n${error.stack}`; - } - - throw new Error(message); - } -}); - -await Promise.all(link); diff --git a/bin/minify-assets.mjs b/bin/minify-assets.mjs index b17761e82f1..c0dadeaedc1 100644 --- a/bin/minify-assets.mjs +++ b/bin/minify-assets.mjs @@ -48,7 +48,7 @@ import nodeGzip from 'node-gzip'; import { join } from 'node:path'; import { readFileSync, writeFileSync } from 'node:fs'; import { minify } from 'terser'; -import { transformSync } from '@babel/core'; +import { transformAsync } from '@babel/core'; import * as brotli from 'brotli'; import { partial } from 'filesize'; const size = partial({ standard: 'jedec' }); @@ -94,10 +94,12 @@ for (const pkg of packages) { for (let file of jsFiles) { let source = readFileSync(file, 'utf8'); - let transformed = transformSync(source, { - ...babelOptions, - filename: file, - }).code; + let transformed = ( + await transformAsync(source, { + ...babelOptions, + filename: file, + }) + ).code; let result = await minify(transformed, { module: true, mangle: false, diff --git a/bin/unlink-all.mjs b/bin/unlink-all.mjs deleted file mode 100644 index f46d64cb602..00000000000 --- a/bin/unlink-all.mjs +++ /dev/null @@ -1,18 +0,0 @@ -import chalk from 'chalk'; -import execa from 'execa'; -import glob from 'glob'; -import path from 'node:path'; - -const rootDir = new URL('..', import.meta.url).pathname; - -const packageJsonPaths = glob.sync('**/package.json', { - cwd: rootDir, - ignore: '**/node_modules/**', -}); - -for (const packageJsonPath of packageJsonPaths) { - const packagePath = path.dirname(packageJsonPath); - // eslint-disable-next-line no-console - console.log(`Unlinking ${chalk.grey(packagePath)}`); - await execa('pnpm', ['unlink'], { stdio: 'inherit', cwd: packagePath }); -} diff --git a/bin/use-vm-tarballs.mjs b/bin/use-vm-tarballs.mjs deleted file mode 100644 index ca7ceccb404..00000000000 --- a/bin/use-vm-tarballs.mjs +++ /dev/null @@ -1,36 +0,0 @@ -/** - * Scans the root folder and sets overrides - * for the package.json - * - * This script exists temporarily while when work on merging - * the glimmer-vm repo in to this one. - * - * Once the merge happens, we should delete this file. - */ -import fs from 'node:fs/promises'; -import { join } from 'node:path'; -import * as glob from 'glob'; - -const tgzs = glob.default.sync('*.tgz', { ignore: 'node_modules/**' }); - -const PARSE = /glimmer-(?.+)-(?(\d+\.?)+)\.tgz/; - -const overrides = {}; - -for (let file of tgzs) { - let match = file.match(PARSE); - let { name } = match.groups; - - overrides[`@glimmer/${name}`] = `file:./${file}`; -} - -let manifestPath = join(process.cwd(), 'package.json'); -let manifestBuffer = await fs.readFile(manifestPath); -let manifest = JSON.parse(manifestBuffer.toString()); - -manifest.pnpm ||= {}; -manifest.pnpm.overrides ||= {}; - -Object.assign(manifest.pnpm.overrides, overrides); - -await fs.writeFile(manifestPath, JSON.stringify(manifest, null, 2)); diff --git a/broccoli/glimmer-template-compiler.js b/broccoli/glimmer-template-compiler.js deleted file mode 100644 index f8df7810fdf..00000000000 --- a/broccoli/glimmer-template-compiler.js +++ /dev/null @@ -1,4 +0,0 @@ -'use strict'; - -require('@swc-node/register'); -module.exports = require('../packages/ember-template-compiler/minimal.ts'); diff --git a/broccoli/glimmer-template-compiler.mjs b/broccoli/glimmer-template-compiler.mjs new file mode 100644 index 00000000000..46939f003d1 --- /dev/null +++ b/broccoli/glimmer-template-compiler.mjs @@ -0,0 +1,8 @@ +import '@swc-node/register/esm-register'; + +// this needs to be async because otherwise the esm-register above hasn't taken +// effect yet. +const minimal = await import('../packages/ember-template-compiler/minimal.ts'); + +const { precompile, _buildCompileOptions, _preprocess, _print } = minimal; +export { precompile, _buildCompileOptions, _preprocess, _print }; diff --git a/eslint.config.mjs b/eslint.config.mjs index 869e8311463..c2c3002d9a4 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -25,6 +25,9 @@ export default [ '**/smoke-tests/', '**/types/', '**/type-tests/', + 'glimmer-vm/repo-metadata/', + 'glimmer-vm/**/rollup.config.mjs', + 'glimmer-vm/packages/@glimmer/vm-babel-plugins/', ], }, pluginJs.configs.recommended, @@ -130,6 +133,17 @@ export default [ '@typescript-eslint/no-unsafe-declaration-merging': 'off', }, }, + { + files: ['glimmer-vm/**/*.ts'], + languageOptions: { + ecmaVersion: 5, + sourceType: 'module', + parserOptions: { + project: './tsconfig-vm.json', + tsconfigRootDir: __dirname, + }, + }, + }, { // TODO: files: ['packages/**/*.[jt]s'], files: ['packages/**/*.js'], @@ -208,6 +222,7 @@ export default [ 'broccoli/**/*.js', '**/ember-cli-build.js', '**/*.cjs', + 'glimmer-vm/server/**/*.js', ], }, { diff --git a/glimmer-vm/.editorconfig b/glimmer-vm/.editorconfig new file mode 100644 index 00000000000..28ea59ea5cf --- /dev/null +++ b/glimmer-vm/.editorconfig @@ -0,0 +1,25 @@ +# EditorConfig helps developers define and maintain consistent +# coding styles between different editors and IDEs +# editorconfig.org + +root = true + + +[*] +max_line_length = 100 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true +indent_style = space +indent_size = 2 + +[*.json] +max_line_length = 80 + +[*.hbs] +insert_final_newline = false + +[*.{diff,md}] +trim_trailing_whitespace = false +max_line_length = 80 diff --git a/glimmer-vm/.env b/glimmer-vm/.env new file mode 100644 index 00000000000..5f4193d478c --- /dev/null +++ b/glimmer-vm/.env @@ -0,0 +1 @@ +NODE_OPTIONS="--no-warnings" diff --git a/glimmer-vm/.env.testing b/glimmer-vm/.env.testing new file mode 100644 index 00000000000..c0d6652113c --- /dev/null +++ b/glimmer-vm/.env.testing @@ -0,0 +1 @@ +NODE_ENV=development diff --git a/glimmer-vm/.gitattributes b/glimmer-vm/.gitattributes new file mode 100644 index 00000000000..3402a2bd543 --- /dev/null +++ b/glimmer-vm/.gitattributes @@ -0,0 +1,5 @@ +guides/workspace/demos/auto-import.gif filter=lfs diff=lfs merge=lfs -text +guides/workspace/demos/fixme.png filter=lfs diff=lfs merge=lfs -text +guides/workspace/demos/dependency-links.png filter=lfs diff=lfs merge=lfs -text +guides/workspace/demos/dependi-outdated.png filter=lfs diff=lfs merge=lfs -text +guides/workspace/demos/dependi-update.png filter=lfs diff=lfs merge=lfs -text diff --git a/glimmer-vm/.github/workflows/ci.yml b/glimmer-vm/.github/workflows/ci.yml new file mode 100644 index 00000000000..c4e259a75ce --- /dev/null +++ b/glimmer-vm/.github/workflows/ci.yml @@ -0,0 +1,143 @@ +name: CI + +on: + workflow_dispatch: + push: + branches: + - main + - next + - 'release-*' + - 'v*' + pull_request: {} + schedule: + - cron: '0 3 * * *' # daily, at 3am + +env: + TURBO_API: http://127.0.0.1:9080 + TURBO_TOKEN: this-is-not-a-secret + TURBO_TEAM: myself + +jobs: + install_dependencies: + name: 'Setup' + runs-on: 'ubuntu-latest' + + steps: + - uses: wyvox/action@v1 + with: + pnpm-args: '--ignore-scripts' + node-version: 22.13.0 + repo-token: ${{ secrets.GITHUB_TOKEN }} + - run: pnpm turbo prepack + + lint: + name: Linting + runs-on: ubuntu-latest + needs: ['install_dependencies'] + timeout-minutes: 10 + + steps: + - uses: wyvox/action@v1 + with: + pnpm-args: '--ignore-scripts' + node-version: 22.13.0 + repo-token: ${{ secrets.GITHUB_TOKEN }} + - run: pnpm lint:all + + + verify: + name: Verify + runs-on: ubuntu-latest + needs: ['install_dependencies'] + timeout-minutes: 10 + + steps: + - uses: wyvox/action@v1 + with: + pnpm-args: '--ignore-scripts' + node-version: 22.13.0 + repo-token: ${{ secrets.GITHUB_TOKEN }} + - run: pnpm lint:fix + - run: pnpm repo:update:conventions + - run: pnpm repo:update:metadata + - uses: wyvox/action-no-git-diff@v1 + + + test-node: + name: Node + runs-on: ubuntu-latest + needs: ['install_dependencies'] + timeout-minutes: 5 + + steps: + - uses: wyvox/action@v1 + with: + node-version: 22.13.0 + repo-token: ${{ secrets.GITHUB_TOKEN }} + - run: pnpm test:node + + test-smoke: + name: Smoke + runs-on: ubuntu-latest + needs: ['install_dependencies'] + timeout-minutes: 5 + + steps: + - uses: wyvox/action@v1 + with: + node-version: 22.13.0 + repo-token: ${{ secrets.GITHUB_TOKEN }} + - working-directory: ./smoke-tests/node + run: | + pnpm test:setup + pnpm test:node + + test-chrome: + name: Chrome + runs-on: ubuntu-latest + needs: ['install_dependencies'] + timeout-minutes: 10 + + steps: + - name: install puppeteer libraries + run: | + sudo apt-get update + sudo apt-get install -yq libgbm1 libatk1.0-0 libc6 \ + libcups2 libdbus-1-3 libexpat1 libfontconfig1 libgcc1 \ + libgdk-pixbuf2.0-0 libglib2.0-0 libgtk-3-0 libnspr4 libpango-1.0-0 \ + libpangocairo-1.0-0 libstdc++6 libx11-6 libx11-xcb1 libxcb1 libxcomposite1 \ + libxcursor1 libxdamage1 libxext6 libxfixes3 libxi6 libxrandr2 libxrender1 \ + libxss1 libxtst6 ca-certificates fonts-liberation libnss3 lsb-release \ + xdg-utils wget libcairo2 + - uses: wyvox/action@v1 + with: + node-version: 22.13.0 + repo-token: ${{ secrets.GITHUB_TOKEN }} + - run: pnpm test + + test-types: + name: Types + runs-on: ubuntu-latest + needs: ['install_dependencies'] + timeout-minutes: 10 + + steps: + - uses: wyvox/action@v1 + with: + node-version: 22.13.0 + repo-token: ${{ secrets.GITHUB_TOKEN }} + - run: pnpm lint:types + + floating-dependencies: + name: Floating Dependencies + runs-on: ubuntu-latest + needs: ['install_dependencies'] + timeout-minutes: 10 + + steps: + - uses: wyvox/action@v1 + with: + pnpm-args: '--no-lockfile' + node-version: 22.13.0 + repo-token: ${{ secrets.GITHUB_TOKEN }} + - run: pnpm test diff --git a/glimmer-vm/.github/workflows/perf.yml b/glimmer-vm/.github/workflows/perf.yml new file mode 100644 index 00000000000..1432209596f --- /dev/null +++ b/glimmer-vm/.github/workflows/perf.yml @@ -0,0 +1,74 @@ +name: PerformanceCheck + +on: + workflow_dispatch: + inputs: + BRANCH: + description: Branch to checkout + required: false + default: 'main' + type: string + # Don't run on every merge to main, because many merges + # may not even be vm related, but infra, or GH Actions + pull_request: + types: [ labeled ] + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +env: + FIDELITY: 100 + THROTTLE: 4 + FORK_NAME: ${{ github.event.pull_request.head.repo.full_name }} + +jobs: + master-krausest-comparison: + if: ${{ github.event.label.name == 'perf' }} + name: Glimmer Krausest Benchmark + runs-on: ubuntu-latest + timeout-minutes: 70 + permissions: + pull-requests: write + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + ref: ${{ inputs.BRANCH }} + + - uses: marceloprado/has-changed-path@v1.0.1 + id: did-change + with: + paths: packages/ + + - uses: wyvox/action-setup-pnpm@v3 + if: steps.did-change.outputs.changed == 'true' + with: + node-version: '22' + + - name: Setup Benchmark Directory + if: steps.did-change.outputs.changed == 'true' + run: pnpm run benchmark:setup + + - name: RUN + if: steps.did-change.outputs.changed == 'true' + run: pnpm run benchmark:run + + - name: Remove unused artifacts + if: steps.did-change.outputs.changed == 'true' + run: rm -rf ./tracerbench-results/traces && rm -rf ./tracerbench-results/traces.zip + + - name: Upload Tracerbench Artifacts + if: steps.did-change.outputs.changed == 'true' && (failure() || success()) + uses: actions/upload-artifact@v3 + with: + name: Trace Artifacts + path: tracerbench-results + + - name: Write message + if: steps.did-change.outputs.changed == 'true' + uses: mshick/add-pr-comment@v2 + with: + message-path: "tracerbench-results/msg.txt" + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/glimmer-vm/.github/workflows/plan-release.yml b/glimmer-vm/.github/workflows/plan-release.yml new file mode 100644 index 00000000000..4a90aa1c8ce --- /dev/null +++ b/glimmer-vm/.github/workflows/plan-release.yml @@ -0,0 +1,100 @@ +name: Plan Release +on: + workflow_dispatch: + push: + branches: + - main + - master + pull_request_target: # This workflow has permissions on the repo, do NOT run code from PRs in this workflow. See https://securitylab.github.com/research/github-actions-preventing-pwn-requests/ + types: + - labeled + - unlabeled + +concurrency: + group: plan-release # only the latest one of these should ever be running + cancel-in-progress: true + +jobs: + is-this-a-release: + name: "Is this a release?" + runs-on: ubuntu-latest + outputs: + command: ${{ steps.check-release.outputs.command }} + + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 2 + ref: 'main' + # This will only cause the `is-this-a-release` job to have a "command" of `release` + # when the .release-plan.json file was changed on the last commit. + - id: check-release + run: if git diff --name-only HEAD HEAD~1 | grep -w -q ".release-plan.json"; then echo "command=release"; fi >> $GITHUB_OUTPUT + + create-prepare-release-pr: + name: Create Prepare Release PR + runs-on: ubuntu-latest + timeout-minutes: 5 + needs: is-this-a-release + permissions: + contents: write + issues: read + pull-requests: write + # only run on push event or workflow dispatch if plan wasn't updated (don't create a release plan when we're releasing) + # only run on labeled event if the PR has already been merged + if: ((github.event_name == 'push' || github.event_name == 'workflow_dispatch') && needs.is-this-a-release.outputs.command != 'release') || (github.event_name == 'pull_request_target' && github.event.pull_request.merged == true) + + steps: + - uses: actions/checkout@v4 + # We need to download lots of history so that + # github-changelog can discover what's changed since the last release + with: + fetch-depth: 0 + ref: 'main' + - uses: wyvox/action-setup-pnpm@v3 + with: + # We have to keep ignore-scripts so that we skip post-install. + # Post-install won't pass on CI and is meant for local smoke tests + args: '--ignore-scripts' + node-version: 22.13.0 + - name: "Generate Explanation and Prep Changelogs" + id: explanation + run: | + # Original content here + set +e + pnpm release-plan prepare 2> >(tee -a release-plan-stderr.txt >&2) + + if [ $? -ne 0 ]; then + release_plan_output=$(cat release-plan-stderr.txt) + else + release_plan_output=$(jq .description .release-plan.json -r) + rm release-plan-stderr.txt + + if [ $(jq '.solution | length' .release-plan.json) -eq 1 ]; then + new_version=$(jq -r '.solution[].newVersion' .release-plan.json) + echo "new_version=v$new_version" >> $GITHUB_OUTPUT + fi + fi + echo 'text<> $GITHUB_OUTPUT + echo "$release_plan_output" >> $GITHUB_OUTPUT + echo 'EOF' >> $GITHUB_OUTPUT + + # Don't forget to-re-add these when we update release-plan + pnpm repo:update:conventions + pnpm repo:update:metadata + + env: + GITHUB_AUTH: ${{ secrets.GITHUB_TOKEN }} + + - uses: peter-evans/create-pull-request@v7 + with: + commit-message: "Prepare Release ${{ steps.explanation.outputs.new_version}} using 'release-plan'" + labels: "internal" + branch: release-preview + title: Prepare Release ${{ steps.explanation.outputs.new_version }} + body: | + This PR is a preview of the release that [release-plan](https://github.com/embroider-build/release-plan) has prepared. To release you should just merge this PR 👍 + + ----------------------------------------- + + ${{ steps.explanation.outputs.text }} diff --git a/glimmer-vm/.github/workflows/publish.yml b/glimmer-vm/.github/workflows/publish.yml new file mode 100644 index 00000000000..b446ddf7d55 --- /dev/null +++ b/glimmer-vm/.github/workflows/publish.yml @@ -0,0 +1,41 @@ +# For every push to the primary branch with .release-plan.json modified, +# runs release-plan. + +name: Publish Stable + +on: + workflow_dispatch: + push: + branches: + - main + - master + paths: + - '.release-plan.json' + +concurrency: + group: publish-${{ github.head_ref || github.ref }} + cancel-in-progress: true + +jobs: + publish: + name: "NPM Publish" + runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write + id-token: write + attestations: write + + steps: + - uses: actions/checkout@v4 + - uses: wyvox/action-setup-pnpm@v3 + with: + args: '--ignore-scripts' + node-version: 22.13.0 + # This creates an .npmrc that reads the NODE_AUTH_TOKEN environment variable + node-registry-url: 'https://registry.npmjs.org' + - name: Publish to NPM + run: NPM_CONFIG_PROVENANCE=true pnpm release-plan publish + env: + GITHUB_AUTH: ${{ secrets.GITHUB_TOKEN }} + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/glimmer-vm/.github/workflows/size.yml b/glimmer-vm/.github/workflows/size.yml new file mode 100644 index 00000000000..2b1556bfad4 --- /dev/null +++ b/glimmer-vm/.github/workflows/size.yml @@ -0,0 +1,156 @@ +name: Size + +on: + workflow_dispatch: + inputs: + BRANCH: + description: Branch to checkout + required: false + default: 'main' + type: string + pull_request: {} + +env: + TURBO_API: http://127.0.0.1:9080 + TURBO_TOKEN: this-is-not-a-secret + TURBO_TEAM: myself + +jobs: + compare_sizes: + name: 'Compare Sizes and Comment' + runs-on: 'ubuntu-latest' + + steps: + - name: '[DEBUG] Dump GitHub context' + env: + GITHUB_CONTEXT: ${{ toJson(github) }} + run: echo "$GITHUB_CONTEXT" + + - uses: wyvox/action@v1 + with: + pnpm-args: '--ignore-scripts' + repo-token: ${{ secrets.GITHUB_TOKEN }} + ref: ${{ inputs.BRANCH }} + + - run: pnpm turbo prepack + - run: sudo snap install dust + + - name: "Get sizes for development outputs" + id: dev + run: | + cd packages/\@glimmer + dust --ignore_hidden \ + --reverse --apparent-size \ + --filter ".+\/dist\/dev\/index.js$" \ + --no-percent-bars --only-dir --depth 1 > out.txt + + echo 'sizes<> $GITHUB_OUTPUT + while IFS= read -r line; do + echo "$line" >> $GITHUB_OUTPUT + done <<< $(cat out.txt) + echo 'EOF' >> $GITHUB_OUTPUT + cat out.txt + + - name: "Get sizes for production outputs" + id: prod + run: | + cd packages/\@glimmer + dust --ignore_hidden \ + --reverse --apparent-size \ + --filter ".+\/dist\/prod\/index.js$" \ + --no-percent-bars --only-dir --depth 1 > out.txt + + echo 'sizes<> $GITHUB_OUTPUT + while IFS= read -r line; do + echo "$line" >> $GITHUB_OUTPUT + done <<< $(cat out.txt) + echo 'EOF' >> $GITHUB_OUTPUT + cat out.txt + + - name: "Get sizes from the main branch" + run: | + git remote -v + git fetch origin + git checkout main + git clean -Xfd + pnpm install + pnpm turbo prepack + + - name: "[Main] Get sizes for development outputs" + id: main-dev + run: | + cd packages/\@glimmer + dust --ignore_hidden \ + --reverse --apparent-size \ + --filter ".+\/dist\/dev\/index.js$" \ + --no-percent-bars --only-dir --depth 1 > out.txt + + echo 'sizes<> $GITHUB_OUTPUT + while IFS= read -r line; do + echo "$line" >> $GITHUB_OUTPUT + done <<< $(cat out.txt) + echo 'EOF' >> $GITHUB_OUTPUT + cat out.txt + + - name: "[Main] Get sizes for production outputs" + id: main-prod + run: | + cd packages/\@glimmer + dust --ignore_hidden \ + --reverse --apparent-size \ + --filter ".+\/dist\/prod\/index.js$" \ + --no-percent-bars --only-dir --depth 1 > out.txt + + echo 'sizes<> $GITHUB_OUTPUT + while IFS= read -r line; do + echo "$line" >> $GITHUB_OUTPUT + done <<< $(cat out.txt) + echo 'EOF' >> $GITHUB_OUTPUT + cat out.txt + + ######################### + # Intended Layout: + # + # | | This PR | Main | + # | Dev | x1 | y1 | + # | Prod | x2 | y2 | + # + ######################### + - uses: mshick/add-pr-comment@v2 + with: + message: | + + + + +
This PRmain
Dev + + ``` + ${{ steps.dev.outputs.sizes }} + ``` + + + + ``` + ${{ steps.main-dev.outputs.sizes }} + ``` + +
Prod + + ``` + ${{ steps.prod.outputs.sizes }} + ``` + + + + ``` + ${{ steps.main-prod.outputs.sizes }} + ``` + +
+ + + + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + diff --git a/glimmer-vm/.gitignore b/glimmer-vm/.gitignore new file mode 100644 index 00000000000..ec6222adef0 --- /dev/null +++ b/glimmer-vm/.gitignore @@ -0,0 +1,20 @@ +.DS_Store +/dist +**/dist +/control-dist/ +node_modules/ +**/node_modules/ +**/.turbo +**/*.tsbuildinfo +tmp/ +/ts-dist/ +**/ts-dist +.eslintcache +*.log +*.dot +*.pdf +instrumentation.*.json +.cache +**/*.tgz +tracerbench-results +.rollup.cache diff --git a/glimmer-vm/.npmignore b/glimmer-vm/.npmignore new file mode 100644 index 00000000000..3e9b4a1bc30 --- /dev/null +++ b/glimmer-vm/.npmignore @@ -0,0 +1,16 @@ +/bin +/build +/node_modules +/packages/@glimmer/integration-tests +tmp +.eslintcache +ember-cli-build.js + +npm-debug.log +sauce-example.log + +testem.js +testem-browserstack.js +testem.log + +.vscode diff --git a/glimmer-vm/.npmrc b/glimmer-vm/.npmrc new file mode 100644 index 00000000000..927d3e5241d --- /dev/null +++ b/glimmer-vm/.npmrc @@ -0,0 +1,4 @@ +ignore-workspace-root-check=true +auto-install-peers=true +strict-peer-dependencies=true +hoist-workspace-packages=false diff --git a/glimmer-vm/.prettierignore b/glimmer-vm/.prettierignore new file mode 100644 index 00000000000..be4d5bfe873 --- /dev/null +++ b/glimmer-vm/.prettierignore @@ -0,0 +1,14 @@ +node_modules/ +.reference/ + +# output directories +dist/ +ts-dist/ + +# We don't need prettier here +*.md +!packages/**/*.md +*.yaml +*.yml +guides/**/*.md +!guides/workspace/**/*.md diff --git a/glimmer-vm/.prettierrc.json b/glimmer-vm/.prettierrc.json new file mode 100644 index 00000000000..d6531530cdd --- /dev/null +++ b/glimmer-vm/.prettierrc.json @@ -0,0 +1,25 @@ +{ + "printWidth": 100, + "plugins": [], + "overrides": [ + { + "files": ["**/*.{js,ts,cjs,mjs,cts,mts,cts}"], + "options": { + "singleQuote": true, + "trailingComma": "es5" + } + }, + { + "files": ["*.json"], + "options": { + "singleQuote": false + } + }, + { + "files": ["*.hbs"], + "options": { + "singleQuote": false + } + } + ] +} diff --git a/glimmer-vm/.prototools b/glimmer-vm/.prototools new file mode 100644 index 00000000000..3d8d6e01e68 --- /dev/null +++ b/glimmer-vm/.prototools @@ -0,0 +1,2 @@ +node = "lts" +pnpm = "latest-10" diff --git a/glimmer-vm/.release-plan.json b/glimmer-vm/.release-plan.json new file mode 100644 index 00000000000..183c7868204 --- /dev/null +++ b/glimmer-vm/.release-plan.json @@ -0,0 +1,169 @@ +{ + "solution": { + "@glimmer/compiler": { + "impact": "patch", + "oldVersion": "0.94.10", + "newVersion": "0.94.11", + "constraints": [ + { + "impact": "patch", + "reason": "Has dependency `workspace:*` on @glimmer/syntax" + } + ], + "pkgJSONPath": "./packages/@glimmer/compiler/package.json" + }, + "@glimmer/destroyable": { + "oldVersion": "0.94.8" + }, + "@glimmer/encoder": { + "oldVersion": "0.93.8" + }, + "@glimmer/global-context": { + "oldVersion": "0.93.4" + }, + "@glimmer/interfaces": { + "oldVersion": "0.94.6" + }, + "@glimmer/manager": { + "impact": "patch", + "oldVersion": "0.94.9", + "newVersion": "0.94.10", + "constraints": [ + { + "impact": "patch", + "reason": "Has dependency `workspace:*` on @glimmer/validator" + }, + { + "impact": "patch", + "reason": "Has dependency `workspace:*` on @glimmer/reference" + } + ], + "pkgJSONPath": "./packages/@glimmer/manager/package.json" + }, + "@glimmer/node": { + "impact": "patch", + "oldVersion": "0.94.9", + "newVersion": "0.94.10", + "constraints": [ + { + "impact": "patch", + "reason": "Has dependency `workspace:*` on @glimmer/runtime" + } + ], + "pkgJSONPath": "./packages/@glimmer/node/package.json" + }, + "@glimmer/opcode-compiler": { + "impact": "patch", + "oldVersion": "0.94.9", + "newVersion": "0.94.10", + "constraints": [ + { + "impact": "patch", + "reason": "Has dependency `workspace:*` on @glimmer/manager" + } + ], + "pkgJSONPath": "./packages/@glimmer/opcode-compiler/package.json" + }, + "@glimmer/owner": { + "oldVersion": "0.93.4" + }, + "@glimmer/program": { + "impact": "patch", + "oldVersion": "0.94.9", + "newVersion": "0.94.10", + "constraints": [ + { + "impact": "patch", + "reason": "Has dependency `workspace:*` on @glimmer/opcode-compiler" + }, + { + "impact": "patch", + "reason": "Has dependency `workspace:*` on @glimmer/manager" + } + ], + "pkgJSONPath": "./packages/@glimmer/program/package.json" + }, + "@glimmer/reference": { + "impact": "patch", + "oldVersion": "0.94.8", + "newVersion": "0.94.9", + "constraints": [ + { + "impact": "patch", + "reason": "Has dependency `workspace:*` on @glimmer/validator" + } + ], + "pkgJSONPath": "./packages/@glimmer/reference/package.json" + }, + "@glimmer/runtime": { + "impact": "patch", + "oldVersion": "0.94.10", + "newVersion": "0.94.11", + "constraints": [ + { + "impact": "patch", + "reason": "Has dependency `workspace:*` on @glimmer/program" + }, + { + "impact": "patch", + "reason": "Has dependency `workspace:*` on @glimmer/manager" + }, + { + "impact": "patch", + "reason": "Has dependency `workspace:*` on @glimmer/reference" + }, + { + "impact": "patch", + "reason": "Has dependency `workspace:*` on @glimmer/validator" + } + ], + "pkgJSONPath": "./packages/@glimmer/runtime/package.json" + }, + "@glimmer/syntax": { + "impact": "minor", + "oldVersion": "0.94.9", + "newVersion": "0.95.0", + "constraints": [ + { + "impact": "minor", + "reason": "Appears in changelog section :rocket: Enhancement" + } + ], + "pkgJSONPath": "./packages/@glimmer/syntax/package.json" + }, + "@glimmer/util": { + "oldVersion": "0.94.8" + }, + "@glimmer/validator": { + "impact": "minor", + "oldVersion": "0.94.8", + "newVersion": "0.95.0", + "constraints": [ + { + "impact": "minor", + "reason": "Appears in changelog section :rocket: Enhancement" + } + ], + "pkgJSONPath": "./packages/@glimmer/validator/package.json" + }, + "@glimmer/vm": { + "oldVersion": "0.94.8" + }, + "@glimmer/vm-babel-plugins": { + "impact": "patch", + "oldVersion": "0.93.4", + "newVersion": "0.93.5", + "constraints": [ + { + "impact": "patch", + "reason": "Appears in changelog section :bug: Bug Fix" + } + ], + "pkgJSONPath": "./packages/@glimmer/vm-babel-plugins/package.json" + }, + "@glimmer/wire-format": { + "oldVersion": "0.94.8" + } + }, + "description": "## Release (2025-07-27)\n\n@glimmer/compiler 0.94.11 (patch)\n@glimmer/manager 0.94.10 (patch)\n@glimmer/node 0.94.10 (patch)\n@glimmer/opcode-compiler 0.94.10 (patch)\n@glimmer/program 0.94.10 (patch)\n@glimmer/reference 0.94.9 (patch)\n@glimmer/runtime 0.94.11 (patch)\n@glimmer/syntax 0.95.0 (minor)\n@glimmer/validator 0.95.0 (minor)\n@glimmer/vm-babel-plugins 0.93.5 (patch)\n\n#### :rocket: Enhancement\n* `@glimmer-workspace/integration-tests`, `@glimmer/validator`\n * [#1748](https://github.com/glimmerjs/glimmer-vm/pull/1748) Implement trackedObject, trackedSet, trackedWeakSet, trackedMap, and trackedWeakMap ([@NullVoxPopuli](https://github.com/NullVoxPopuli))\n * [#1713](https://github.com/glimmerjs/glimmer-vm/pull/1713) Implement trackedArray(data, { equals, description }) ([@NullVoxPopuli](https://github.com/NullVoxPopuli))\n* `@glimmer/syntax`\n * [#1743](https://github.com/glimmerjs/glimmer-vm/pull/1743) Upgrade handlebars parser ([@NullVoxPopuli](https://github.com/NullVoxPopuli))\n\n#### :bug: Bug Fix\n* `@glimmer-workspace/build-support`, `@glimmer/vm-babel-plugins`\n * [#1759](https://github.com/glimmerjs/glimmer-vm/pull/1759) Fix security vulnerabilities with targeted solutions ([@wycats](https://github.com/wycats))\n* `@glimmer-workspace/bin`, `@glimmer-workspace/build-support`, `@glimmer-workspace/repo-metadata`\n * [#1753](https://github.com/glimmerjs/glimmer-vm/pull/1753) Fix build verification by stripping debug calls from all builds ([@wycats](https://github.com/wycats))\n* Other\n * [#1744](https://github.com/glimmerjs/glimmer-vm/pull/1744) Upgrade to pnpm 10.6.5 ([@NullVoxPopuli](https://github.com/NullVoxPopuli))\n\n#### :memo: Documentation\n* [#1752](https://github.com/glimmerjs/glimmer-vm/pull/1752) Add reactivity docs from #1690 ([@NullVoxPopuli](https://github.com/NullVoxPopuli))\n\n#### :house: Internal\n* `@glimmer-workspace/bin`\n * [#1764](https://github.com/glimmerjs/glimmer-vm/pull/1764) fix link-all: Extensions must match path on disk. It was TS that created a problem, and node fixed it. ([@NullVoxPopuli](https://github.com/NullVoxPopuli))\n * [#1763](https://github.com/glimmerjs/glimmer-vm/pull/1763) Change link all, so that tarballs are left in the dist directory for easier testing with emberjs ([@NullVoxPopuli](https://github.com/NullVoxPopuli))\n * [#1757](https://github.com/glimmerjs/glimmer-vm/pull/1757) Improve and consolidate package.json scripts ([@wycats](https://github.com/wycats))\n* `@glimmer-workspace/bin`, `@glimmer-workspace/repo-metadata`\n * [#1760](https://github.com/glimmerjs/glimmer-vm/pull/1760) Remove unused dependencies ([@wycats](https://github.com/wycats))\n * [#1756](https://github.com/glimmerjs/glimmer-vm/pull/1756) Remove unused scripts and update documentation ([@wycats](https://github.com/wycats))\n* Other\n * [#1758](https://github.com/glimmerjs/glimmer-vm/pull/1758) Optimize Turbo configuration and clean up dependencies ([@wycats](https://github.com/wycats))\n* `@glimmer-workspace/repo-metadata`\n * [#1754](https://github.com/glimmerjs/glimmer-vm/pull/1754) Fix floating dependencies CI by replacing meta-updater ([@wycats](https://github.com/wycats))\n\n#### Committers: 2\n- Yehuda Katz ([@wycats](https://github.com/wycats))\n- [@NullVoxPopuli](https://github.com/NullVoxPopuli)\n" +} diff --git a/glimmer-vm/.vscode/extensions.json b/glimmer-vm/.vscode/extensions.json new file mode 100644 index 00000000000..4416b29e7ca --- /dev/null +++ b/glimmer-vm/.vscode/extensions.json @@ -0,0 +1,12 @@ +{ + "recommendations": [ + "foxundermoon.shell-format", + "dbaeumer.vscode-eslint", + "fill-labs.dependi", + "rohit-gohri.format-code-action", + "tintinweb.vscode-inline-bookmarks", + "herrmannplatz.npm-dependency-links", + "esbenp.prettier-vscode", + "dnut.rewrap-revived" + ] +} diff --git a/glimmer-vm/.vscode/launch.json b/glimmer-vm/.vscode/launch.json new file mode 100644 index 00000000000..8ae967037b4 --- /dev/null +++ b/glimmer-vm/.vscode/launch.json @@ -0,0 +1,32 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "All packages", + "type": "chrome", + "request": "launch", + "url": "http://localhost:7357/tests/index.html", + "sourceMaps": true, + "userDataDir": "${workspaceRoot}/tmp/chrome-user-data", + "webRoot": "${workspaceRoot}/packages/node_modules" + }, + { + "name": "glimmer-runtime", + "type": "chrome", + "request": "launch", + "url": "http://localhost:7357/tests/index.html?packages=glimmer-runtime", + "sourceMaps": true, + "userDataDir": "${workspaceRoot}/tmp/chrome-user-data", + "webRoot": "${workspaceRoot}/packages/node_modules" + }, + { + "name": "focused", + "type": "chrome", + "request": "launch", + "url": "http://localhost:7357/tests/index.html?packages=glimmer-runtime&testId=8b1252f6", + "sourceMaps": true, + "userDataDir": "${workspaceRoot}/tmp/chrome-user-data", + "webRoot": "${workspaceRoot}/packages/node_modules" + } + ] +} diff --git a/glimmer-vm/.vscode/settings.json b/glimmer-vm/.vscode/settings.json new file mode 100644 index 00000000000..e094615e277 --- /dev/null +++ b/glimmer-vm/.vscode/settings.json @@ -0,0 +1,141 @@ +// Place your settings in this file to overwrite default and user settings. +{ + "[ignore][properties][shellscript]": { + "editor.defaultFormatter": "foxundermoon.shell-format" + }, + "[javascript][typescript]": { + "editor.codeActionsOnSave": { + "source.fixAll": "always", + "source.formatDocument": "always" + }, + "editor.defaultFormatter": "esbenp.prettier-vscode", + "editor.formatOnSave": false, + "editor.rulers": [100] + }, + "[json][jsonc][markdown][yaml]": { + "editor.codeActionsOnSave": { + "source.fixAll": "always", + "source.formatDocument": "always" + }, + "editor.defaultFormatter": "esbenp.prettier-vscode", + "editor.formatOnSave": false + }, + "dependi.npm.informPatchUpdates": true, + "dependi.npm.lockFileEnabled": true, + "editor.formatOnSave": true, + "eslint.codeAction.showDocumentation": { + "enable": true + }, + "eslint.codeActionsOnSave.mode": "all", + "eslint.enable": true, + "eslint.lintTask.enable": true, + "eslint.onIgnoredFiles": "warn", + "eslint.options": { + "overrideConfigFile": "./eslint.config.js" + }, + "eslint.problems.shortenToSingleLine": true, + "eslint.runtime": "node", + "eslint.useFlatConfig": true, + "eslint.validate": ["javascript", "typescript", "json", "jsonc"], + "eslint.workingDirectories": [ + { + "pattern": "." + } + ], + "explorer.excludeGitIgnore": true, + "files.exclude": { + "**/.DS_Store": true, + "**/.git": true, + "**/dist": true, + "**/node_modules": true, + "tracerbench-results": true + }, + "files.watcherExclude": { + "**/.git/objects/**": true, + "**/.git/subtree-cache/**": true + }, + "inline-bookmarks.expert.custom.styles": { + "active": { + "dark": { + "color": "#00ffff", + "fontWeight": "bold" + }, + // teal + "gutterIconColor": "#009999", + "light": { + "color": "#009999", + "fontWeight": "bold" + }, + "overviewRulerColor": "rgba(0, 150, 150, 0.7)" + }, + "bandaid": { + "dark": { + "color": "#ffff00", + "fontWeight": "bold" + }, + // teal + "gutterIconColor": "#999900", + "light": { + "color": "#999900", + "fontWeight": "bold" + }, + "overviewRulerColor": "rgba(150, 150, 0, 0.7)" + }, + "fixme": { + "dark": { + "color": "#ff0000", + "fontWeight": "bold" + }, + // yellow + "gutterIconColor": "#990000", + "light": { + "color": "#990000", + "fontWeight": "bold" + }, + "overviewRulerColor": "rgba(150, 0, 0, 0.7)" + }, + "warn": { + "dark": { + "color": "#ffff00", + "fontWeight": "bold" + }, + // yellow + "gutterIconColor": "#999900", + "light": { + "color": "#999900", + "fontWeight": "bold" + }, + "overviewRulerColor": "rgba(150, 150, 0, 0.7)" + } + }, + "inline-bookmarks.expert.custom.words.mapping": { + "audit": ["@audit(\\s|$)"], + "fixme": ["@fixme(\\s|$)"], + "warn": ["@premerge(\\s|$)"], + "bandaid": [ + "@bandaid\\(until:[^)]+\\)(\\s|$)", + "@bandaid(?=\\{@link [^}]+\\}(\\s|$))", + "@bandaid(?!\\()" + ] + }, + "inline-bookmarks.view.showVisibleFilesOnly": true, + "javascript.preferences.importModuleSpecifier": "project-relative", + "javascript.updateImportsOnFileMove.enabled": "always", + "rewrap.autoWrap.enabled": true, + "rewrap.onSave": false, + "rewrap.reformat": true, + "rewrap.wholeComment": false, + "surround.custom": { + "register": { + "label": "register helper", + "snippet": "{ ${1:helper}: $TM_SELECTED_TEXT }" + } + }, + "typescript.experimental.updateImportsOnPaste": true, + "typescript.preferences.importModuleSpecifier": "project-relative", + "typescript.preferences.importModuleSpecifierEnding": "auto", + "typescript.preferences.useAliasesForRenames": false, + "typescript.tsdk": "node_modules/typescript/lib", + "typescript.updateImportsOnFileMove.enabled": "always", + "typescript.reportStyleChecksAsWarnings": false +} diff --git a/glimmer-vm/.vscode/tasks.json b/glimmer-vm/.vscode/tasks.json new file mode 100644 index 00000000000..c91b0449252 --- /dev/null +++ b/glimmer-vm/.vscode/tasks.json @@ -0,0 +1,22 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "type": "shell", + "command": "pnpm", + "args": ["dotenv", "--", "turbo", "lint"], + // "script": "lint:files", + "problemMatcher": ["$eslint-stylish"], + "presentation": { + "echo": true, + "reveal": "always", + "focus": false, + "panel": "shared", + "showReuseMessage": true, + "clear": false + }, + "label": "turbo: lint", + "detail": "dotenv -- turbo lint" + } + ] +} diff --git a/glimmer-vm/CHANGELOG.md b/glimmer-vm/CHANGELOG.md new file mode 100644 index 00000000000..525e2806091 --- /dev/null +++ b/glimmer-vm/CHANGELOG.md @@ -0,0 +1,3493 @@ +# Changelog + +## Release (2025-07-27) + +@glimmer/compiler 0.94.11 (patch) +@glimmer/manager 0.94.10 (patch) +@glimmer/node 0.94.10 (patch) +@glimmer/opcode-compiler 0.94.10 (patch) +@glimmer/program 0.94.10 (patch) +@glimmer/reference 0.94.9 (patch) +@glimmer/runtime 0.94.11 (patch) +@glimmer/syntax 0.95.0 (minor) +@glimmer/validator 0.95.0 (minor) +@glimmer/vm-babel-plugins 0.93.5 (patch) + +#### :rocket: Enhancement +* `@glimmer-workspace/integration-tests`, `@glimmer/validator` + * [#1748](https://github.com/glimmerjs/glimmer-vm/pull/1748) Implement trackedObject, trackedSet, trackedWeakSet, trackedMap, and trackedWeakMap ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) + * [#1713](https://github.com/glimmerjs/glimmer-vm/pull/1713) Implement trackedArray(data, { equals, description }) ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) +* `@glimmer/syntax` + * [#1743](https://github.com/glimmerjs/glimmer-vm/pull/1743) Upgrade handlebars parser ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) + +#### :bug: Bug Fix +* `@glimmer-workspace/build-support`, `@glimmer/vm-babel-plugins` + * [#1759](https://github.com/glimmerjs/glimmer-vm/pull/1759) Fix security vulnerabilities with targeted solutions ([@wycats](https://github.com/wycats)) +* `@glimmer-workspace/bin`, `@glimmer-workspace/build-support`, `@glimmer-workspace/repo-metadata` + * [#1753](https://github.com/glimmerjs/glimmer-vm/pull/1753) Fix build verification by stripping debug calls from all builds ([@wycats](https://github.com/wycats)) +* Other + * [#1744](https://github.com/glimmerjs/glimmer-vm/pull/1744) Upgrade to pnpm 10.6.5 ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) + +#### :memo: Documentation +* [#1752](https://github.com/glimmerjs/glimmer-vm/pull/1752) Add reactivity docs from #1690 ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) + +#### :house: Internal +* `@glimmer-workspace/bin` + * [#1764](https://github.com/glimmerjs/glimmer-vm/pull/1764) fix link-all: Extensions must match path on disk. It was TS that created a problem, and node fixed it. ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) + * [#1763](https://github.com/glimmerjs/glimmer-vm/pull/1763) Change link all, so that tarballs are left in the dist directory for easier testing with emberjs ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) + * [#1757](https://github.com/glimmerjs/glimmer-vm/pull/1757) Improve and consolidate package.json scripts ([@wycats](https://github.com/wycats)) +* `@glimmer-workspace/bin`, `@glimmer-workspace/repo-metadata` + * [#1760](https://github.com/glimmerjs/glimmer-vm/pull/1760) Remove unused dependencies ([@wycats](https://github.com/wycats)) + * [#1756](https://github.com/glimmerjs/glimmer-vm/pull/1756) Remove unused scripts and update documentation ([@wycats](https://github.com/wycats)) +* Other + * [#1758](https://github.com/glimmerjs/glimmer-vm/pull/1758) Optimize Turbo configuration and clean up dependencies ([@wycats](https://github.com/wycats)) +* `@glimmer-workspace/repo-metadata` + * [#1754](https://github.com/glimmerjs/glimmer-vm/pull/1754) Fix floating dependencies CI by replacing meta-updater ([@wycats](https://github.com/wycats)) + +#### Committers: 2 +- Yehuda Katz ([@wycats](https://github.com/wycats)) +- [@NullVoxPopuli](https://github.com/NullVoxPopuli) + +## Release (2025-03-18) + +@glimmer/compiler 0.94.10 (patch) +@glimmer/destroyable 0.94.8 (patch) +@glimmer/encoder 0.93.8 (patch) +@glimmer/global-context 0.93.4 (patch) +@glimmer/manager 0.94.9 (patch) +@glimmer/node 0.94.9 (patch) +@glimmer/opcode-compiler 0.94.9 (patch) +@glimmer/owner 0.93.4 (patch) +@glimmer/program 0.94.9 (patch) +@glimmer/reference 0.94.8 (patch) +@glimmer/runtime 0.94.10 (patch) +@glimmer/syntax 0.94.9 (patch) +@glimmer/util 0.94.8 (patch) +@glimmer/validator 0.94.8 (patch) +@glimmer/vm 0.94.8 (patch) +@glimmer/wire-format 0.94.8 (patch) + +#### :bug: Bug Fix +* `@glimmer-workspace/meta-updater`, `@glimmer-workspace/benchmark-env`, `@glimmer/compiler`, `@glimmer/destroyable`, `@glimmer/encoder`, `@glimmer/global-context`, `@glimmer/manager`, `@glimmer/node`, `@glimmer/opcode-compiler`, `@glimmer/owner`, `@glimmer/program`, `@glimmer/reference`, `@glimmer/runtime`, `@glimmer/syntax`, `@glimmer/util`, `@glimmer/validator`, `@glimmer/vm`, `@glimmer/wire-format` + * [#1741](https://github.com/glimmerjs/glimmer-vm/pull/1741) Re-add support for tsconfig's moduleResolution=node10 ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) + +#### :house: Internal +* Other + * [#1738](https://github.com/glimmerjs/glimmer-vm/pull/1738) Removing editor.rulers ([@ef4](https://github.com/ef4)) +* `@glimmer-workspace/repo-metadata` + * [#1736](https://github.com/glimmerjs/glimmer-vm/pull/1736) pnpm repo:update:metadata ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) +* `@glimmer/runtime` + * [#1735](https://github.com/glimmerjs/glimmer-vm/pull/1735) Force release ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) + +#### Committers: 2 +- Edward Faulkner ([@ef4](https://github.com/ef4)) +- [@NullVoxPopuli](https://github.com/NullVoxPopuli) + +## Release (2025-03-14) + +@glimmer/runtime 0.94.9 (patch) + +#### :bug: Bug Fix +* `@glimmer-workspace/build-support`, `@glimmer/runtime` + * [#1734](https://github.com/glimmerjs/glimmer-vm/pull/1734) Restore {{debugger}} behavior ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) + +#### :house: Internal +* `@glimmer-workspace/bin` + * [#1732](https://github.com/glimmerjs/glimmer-vm/pull/1732) Fix bench post-install ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) + +#### Committers: 1 +- [@NullVoxPopuli](https://github.com/NullVoxPopuli) + +## Release (2025-03-04) + +@glimmer/compiler 0.94.9 (patch) +@glimmer/destroyable 0.94.7 (patch) +@glimmer/encoder 0.93.7 (patch) +@glimmer/global-context 0.93.3 (patch) +@glimmer/interfaces 0.94.6 (patch) +@glimmer/manager 0.94.8 (patch) +@glimmer/node 0.94.8 (patch) +@glimmer/opcode-compiler 0.94.8 (patch) +@glimmer/owner 0.93.3 (patch) +@glimmer/program 0.94.8 (patch) +@glimmer/reference 0.94.7 (patch) +@glimmer/runtime 0.94.8 (patch) +@glimmer/syntax 0.94.8 (patch) +@glimmer/util 0.94.7 (patch) +@glimmer/validator 0.94.7 (patch) +@glimmer/vm 0.94.7 (patch) +@glimmer/vm-babel-plugins 0.93.4 (patch) +@glimmer/wire-format 0.94.7 (patch) + +#### :bug: Bug Fix +* `@glimmer/syntax` + * [#1722](https://github.com/glimmerjs/glimmer-vm/pull/1722) Printer bug: empty string literal args are dropped ([@ef4](https://github.com/ef4)) + * [#1720](https://github.com/glimmerjs/glimmer-vm/pull/1720) Printer quoting bug ([@ef4](https://github.com/ef4)) +* `@glimmer/compiler`, `@glimmer/syntax` + * [#1717](https://github.com/glimmerjs/glimmer-vm/pull/1717) Fix source slicing for whitespace-stripping comments ([@chancancode](https://github.com/chancancode)) + +#### :house: Internal +* Other + * [#1730](https://github.com/glimmerjs/glimmer-vm/pull/1730) fix release-plan ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) + * [#1728](https://github.com/glimmerjs/glimmer-vm/pull/1728) Set node-version to 22 in plan-release/publish ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) + * [#1727](https://github.com/glimmerjs/glimmer-vm/pull/1727) Update release-plan ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) + * [#1723](https://github.com/glimmerjs/glimmer-vm/pull/1723) Add .npmrc to turbo.json ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) + * [#1721](https://github.com/glimmerjs/glimmer-vm/pull/1721) set hoist-workspace-packages=false ([@ef4](https://github.com/ef4)) +* `@glimmer/compiler`, `@glimmer/destroyable`, `@glimmer/encoder`, `@glimmer/global-context`, `@glimmer/interfaces`, `@glimmer/manager`, `@glimmer/node`, `@glimmer/opcode-compiler`, `@glimmer/owner`, `@glimmer/program`, `@glimmer/reference`, `@glimmer/runtime`, `@glimmer/syntax`, `@glimmer/util`, `@glimmer/validator`, `@glimmer/vm-babel-plugins`, `@glimmer/vm`, `@glimmer/wire-format`, `@glimmer-workspace/repo-metadata` + * [#1729](https://github.com/glimmerjs/glimmer-vm/pull/1729) Revert "Prepare Release" ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) + * [#1715](https://github.com/glimmerjs/glimmer-vm/pull/1715) Prepare Release ([@github-actions[bot]](https://github.com/apps/github-actions)) +* `@glimmer-workspace/repo-metadata` + * [#1726](https://github.com/glimmerjs/glimmer-vm/pull/1726) Move prettier tests to the smoke-tests project ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) +* `@glimmer-workspace/bin` + * [#1718](https://github.com/glimmerjs/glimmer-vm/pull/1718) Fix accidental success in tests due to ansi-output not matching non-ansi string. ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) +* `@glimmer/syntax` + * [#1719](https://github.com/glimmerjs/glimmer-vm/pull/1719) @handlebars/parser 2.1.0 causes errors due to an unreleased fix -- downgrade for now ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) +* `@glimmer-workspace/meta-updater`, `@glimmer-workspace/bin`, `@glimmer-workspace/benchmark-env`, `@glimmer-workspace/build-support`, `@glimmer-workspace/eslint-plugin`, `@glimmer-workspace/integration-tests`, `@glimmer-workspace/test-utils`, `@glimmer/compiler`, `@glimmer/constants`, `@glimmer/debug-util`, `@glimmer/debug`, `@glimmer/destroyable`, `@glimmer/encoder`, `@glimmer/global-context`, `@glimmer/interfaces`, `@glimmer/local-debug-flags`, `@glimmer/manager`, `@glimmer/node`, `@glimmer/opcode-compiler`, `@glimmer/owner`, `@glimmer/program`, `@glimmer/reference`, `@glimmer/runtime`, `@glimmer/syntax`, `@glimmer/util`, `@glimmer/validator`, `@glimmer/vm-babel-plugins`, `@glimmer/vm`, `@glimmer/wire-format`, `@glimmer-workspace/repo-metadata` + * [#1714](https://github.com/glimmerjs/glimmer-vm/pull/1714) Dep upgrades from https://github.com/glimmerjs/glimmer-vm/pull/1690/ ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) + +#### Committers: 4 +- Edward Faulkner ([@ef4](https://github.com/ef4)) +- Godfrey Chan ([@chancancode](https://github.com/chancancode)) +- [@NullVoxPopuli](https://github.com/NullVoxPopuli) +- [@github-actions[bot]](https://github.com/apps/github-actions) + +## Release (2025-02-11) + +@glimmer/manager 0.94.7 (patch) +@glimmer/node 0.94.7 (patch) +@glimmer/opcode-compiler 0.94.7 (patch) +@glimmer/program 0.94.7 (patch) +@glimmer/runtime 0.94.7 (patch) + +#### :bug: Bug Fix +* `@glimmer-workspace/integration-tests`, `@glimmer/manager` + * [#1710](https://github.com/glimmerjs/glimmer-vm/pull/1710) Fix rendering non-object, yet stringable values (Symbol?), moves Reflect.getPrototypeOf to Object.getPrototypeOf ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) + +#### :house: Internal +* `@glimmer-workspace/bin` + * [#1711](https://github.com/glimmerjs/glimmer-vm/pull/1711) Pull benchmark changes from feature/emit-fn-calls ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) + +#### Committers: 1 +- [@NullVoxPopuli](https://github.com/NullVoxPopuli) + +## Release (2025-02-11) + +@glimmer/compiler 0.94.8 (patch) +@glimmer/syntax 0.94.7 (patch) + +#### :bug: Bug Fix +* `@glimmer/syntax`, `@glimmer-workspace/repo-metadata` + * [#1708](https://github.com/glimmerjs/glimmer-vm/pull/1708) Bring back cjs for glimmer syntax ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) + +#### Committers: 1 +- [@NullVoxPopuli](https://github.com/NullVoxPopuli) + +## Release (2025-02-10) + +@glimmer/compiler 0.94.7 (patch) +@glimmer/destroyable 0.94.6 (patch) +@glimmer/encoder 0.93.6 (patch) +@glimmer/interfaces 0.94.5 (patch) +@glimmer/manager 0.94.6 (patch) +@glimmer/node 0.94.6 (patch) +@glimmer/opcode-compiler 0.94.6 (patch) +@glimmer/program 0.94.6 (patch) +@glimmer/reference 0.94.6 (patch) +@glimmer/runtime 0.94.6 (patch) +@glimmer/syntax 0.94.6 (patch) +@glimmer/util 0.94.6 (patch) +@glimmer/validator 0.94.6 (patch) +@glimmer/vm 0.94.6 (patch) +@glimmer/wire-format 0.94.6 (patch) + +#### :bug: Bug Fix +* `@glimmer/interfaces` + * [#1706](https://github.com/glimmerjs/glimmer-vm/pull/1706) Fix @glimmer/interfaces exports ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) + +#### Committers: 1 +- [@NullVoxPopuli](https://github.com/NullVoxPopuli) + +## Release (2025-02-10) + +@glimmer/compiler 0.94.6 (patch) +@glimmer/destroyable 0.94.5 (patch) +@glimmer/encoder 0.93.5 (patch) +@glimmer/interfaces 0.94.4 (patch) +@glimmer/manager 0.94.5 (patch) +@glimmer/node 0.94.5 (patch) +@glimmer/opcode-compiler 0.94.5 (patch) +@glimmer/program 0.94.5 (patch) +@glimmer/reference 0.94.5 (patch) +@glimmer/runtime 0.94.5 (patch) +@glimmer/syntax 0.94.5 (patch) +@glimmer/util 0.94.5 (patch) +@glimmer/validator 0.94.5 (patch) +@glimmer/vm 0.94.5 (patch) +@glimmer/wire-format 0.94.5 (patch) + +#### :bug: Bug Fix +* `@glimmer-workspace/build-support`, `@glimmer/interfaces`, `@glimmer-workspace/repo-metadata` + * [#1704](https://github.com/glimmerjs/glimmer-vm/pull/1704) Fix types rollup ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) + +#### Committers: 1 +- [@NullVoxPopuli](https://github.com/NullVoxPopuli) + +## Release (2025-02-10) + +@glimmer/compiler 0.94.5 (patch) +@glimmer/destroyable 0.94.4 (patch) +@glimmer/encoder 0.93.4 (patch) +@glimmer/interfaces 0.94.3 (patch) +@glimmer/manager 0.94.4 (patch) +@glimmer/node 0.94.4 (patch) +@glimmer/opcode-compiler 0.94.4 (patch) +@glimmer/program 0.94.4 (patch) +@glimmer/reference 0.94.4 (patch) +@glimmer/runtime 0.94.4 (patch) +@glimmer/syntax 0.94.4 (patch) +@glimmer/util 0.94.4 (patch) +@glimmer/validator 0.94.4 (patch) +@glimmer/vm 0.94.4 (patch) +@glimmer/vm-babel-plugins 0.93.3 (patch) +@glimmer/wire-format 0.94.4 (patch) + +#### :bug: Bug Fix +* `@glimmer/interfaces` + * [#1703](https://github.com/glimmerjs/glimmer-vm/pull/1703) Add README to @glimmer/interfaces to try to force a release of dependent packages ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) +* `@glimmer-workspace/meta-updater`, `@glimmer-workspace/build-support`, `@glimmer/vm-babel-plugins`, `@glimmer-workspace/repo-metadata` + * [#1701](https://github.com/glimmerjs/glimmer-vm/pull/1701) Rollup the types (solves missing types from unpublished packages) ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) + +#### Committers: 1 +- [@NullVoxPopuli](https://github.com/NullVoxPopuli) + +## Release (2025-02-08) + +@glimmer/compiler 0.94.4 (patch) + +#### :bug: Bug Fix +* `@glimmer-workspace/meta-updater`, `@glimmer-workspace/build-support`, `@glimmer/compiler`, `@glimmer-workspace/repo-metadata` + * [#1699](https://github.com/glimmerjs/glimmer-vm/pull/1699) Re-enable CJS for @glimmer/compiler (used by babel plugin) ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) + +#### Committers: 1 +- [@NullVoxPopuli](https://github.com/NullVoxPopuli) + +## Release (2025-02-07) + +@glimmer/compiler 0.94.3 (patch) +@glimmer/destroyable 0.94.3 (patch) +@glimmer/encoder 0.93.3 (patch) +@glimmer/global-context 0.93.2 (patch) +@glimmer/manager 0.94.3 (patch) +@glimmer/node 0.94.3 (patch) +@glimmer/opcode-compiler 0.94.3 (patch) +@glimmer/owner 0.93.2 (patch) +@glimmer/program 0.94.3 (patch) +@glimmer/reference 0.94.3 (patch) +@glimmer/runtime 0.94.3 (patch) +@glimmer/syntax 0.94.3 (patch) +@glimmer/util 0.94.3 (patch) +@glimmer/validator 0.94.3 (patch) +@glimmer/vm 0.94.3 (patch) +@glimmer/vm-babel-plugins 0.93.2 (patch) +@glimmer/wire-format 0.94.3 (patch) + +#### :bug: Bug Fix +* `@glimmer-workspace/meta-updater`, `@glimmer-workspace/benchmark-env`, `@glimmer/compiler`, `@glimmer/destroyable`, `@glimmer/encoder`, `@glimmer/global-context`, `@glimmer/manager`, `@glimmer/node`, `@glimmer/opcode-compiler`, `@glimmer/owner`, `@glimmer/program`, `@glimmer/reference`, `@glimmer/runtime`, `@glimmer/syntax`, `@glimmer/util`, `@glimmer/validator`, `@glimmer/vm-babel-plugins`, `@glimmer/vm`, `@glimmer/wire-format` + * [#1698](https://github.com/glimmerjs/glimmer-vm/pull/1698) Fix exports ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) + +#### :house: Internal +* `@glimmer-workspace/repo-metadata` + * [#1696](https://github.com/glimmerjs/glimmer-vm/pull/1696) Update package meta post-publish and tell the auto-publish infra to do this for us ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) + +#### Committers: 1 +- [@NullVoxPopuli](https://github.com/NullVoxPopuli) + +## Release (2025-02-07) + +@glimmer/compiler 0.94.2 (patch) +@glimmer/destroyable 0.94.2 (patch) +@glimmer/encoder 0.93.2 (patch) +@glimmer/interfaces 0.94.2 (patch) +@glimmer/manager 0.94.2 (patch) +@glimmer/node 0.94.2 (patch) +@glimmer/opcode-compiler 0.94.2 (patch) +@glimmer/program 0.94.2 (patch) +@glimmer/reference 0.94.2 (patch) +@glimmer/runtime 0.94.2 (patch) +@glimmer/syntax 0.94.2 (patch) +@glimmer/util 0.94.2 (patch) +@glimmer/validator 0.94.2 (patch) +@glimmer/vm 0.94.2 (patch) +@glimmer/wire-format 0.94.2 (patch) + +#### :bug: Bug Fix +* `@glimmer/interfaces` + * [#1694](https://github.com/glimmerjs/glimmer-vm/pull/1694) Fix @glimmer/interfaces, we were not publishing anything ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) + +#### Committers: 1 +- [@NullVoxPopuli](https://github.com/NullVoxPopuli) + +## Release (2025-01-26) + +@glimmer/compiler 0.94.1 (patch) +@glimmer/destroyable 0.94.1 (patch) +@glimmer/encoder 0.93.1 (patch) +@glimmer/global-context 0.93.1 (patch) +@glimmer/interfaces 0.94.1 (patch) +@glimmer/manager 0.94.1 (patch) +@glimmer/node 0.94.1 (patch) +@glimmer/opcode-compiler 0.94.1 (patch) +@glimmer/owner 0.93.1 (patch) +@glimmer/program 0.94.1 (patch) +@glimmer/reference 0.94.1 (patch) +@glimmer/runtime 0.94.1 (patch) +@glimmer/syntax 0.94.1 (patch) +@glimmer/util 0.94.1 (patch) +@glimmer/validator 0.94.1 (patch) +@glimmer/vm 0.94.1 (patch) +@glimmer/vm-babel-plugins 0.93.1 (patch) +@glimmer/wire-format 0.94.1 (patch) + +#### :bug: Bug Fix +* `@glimmer-workspace/meta-updater`, `@glimmer-workspace/bin`, `@glimmer-workspace/benchmark-env`, `@glimmer-workspace/build-support`, `@glimmer-workspace/env`, `@glimmer-workspace/eslint-plugin`, `@glimmer-workspace/integration-node-tests`, `@glimmer-workspace/integration-tests`, `@glimmer-workspace/test-utils`, `@glimmer/compiler`, `@glimmer/constants`, `@glimmer/debug-util`, `@glimmer/debug`, `@glimmer/destroyable`, `@glimmer/encoder`, `@glimmer/global-context`, `@glimmer/interfaces`, `@glimmer/local-debug-babel-plugin`, `@glimmer/local-debug-flags`, `@glimmer/manager`, `@glimmer/node`, `@glimmer/opcode-compiler`, `@glimmer/owner`, `@glimmer/program`, `@glimmer/reference`, `@glimmer/runtime`, `@glimmer/syntax`, `@glimmer/util`, `@glimmer/validator`, `@glimmer/vm-babel-plugins`, `@glimmer/vm`, `@glimmer/wire-format`, `@types/eslint-community__eslint-plugin-eslint-comments`, `@types/eslint-plugin-import`, `@types/eslint-plugin-qunit`, `@types/js-reporters`, `@types/puppeteer-chromium-resolver`, `@glimmer-workspace/repo-metadata` + * [#1689](https://github.com/glimmerjs/glimmer-vm/pull/1689) Prevent #1688 (and other accidental prettier breakages) ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) + +#### :house: Internal +* `@glimmer-workspace/meta-updater`, `@glimmer-workspace/bin`, `@glimmer-workspace/integration-tests`, `@glimmer/compiler`, `@glimmer/constants`, `@glimmer/debug-util`, `@glimmer/debug`, `@glimmer/opcode-compiler`, `@glimmer/runtime`, `@glimmer/syntax`, `@glimmer/util`, `@glimmer-workspace/repo-metadata` + * [#1691](https://github.com/glimmerjs/glimmer-vm/pull/1691) Fix Formatting, add verify step to CI that prevents accidentally git diffs from happening later ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) +* Other + * [#1685](https://github.com/glimmerjs/glimmer-vm/pull/1685) Root package.json needs a repository field ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) + +#### Committers: 1 +- [@NullVoxPopuli](https://github.com/NullVoxPopuli) + +## Release (2025-01-21) + +@glimmer/compiler 0.94.0 (minor) +@glimmer/destroyable 0.94.0 (minor) +@glimmer/encoder 0.93.0 (minor) +@glimmer/global-context 0.93.0 (minor) +@glimmer/interfaces 0.94.0 (minor) +@glimmer/manager 0.94.0 (minor) +@glimmer/node 0.94.0 (minor) +@glimmer/opcode-compiler 0.94.0 (minor) +@glimmer/owner 0.93.0 (minor) +@glimmer/program 0.94.0 (minor) +@glimmer/reference 0.94.0 (minor) +@glimmer/runtime 0.94.0 (minor) +@glimmer/syntax 0.94.0 (minor) +@glimmer/util 0.94.0 (minor) +@glimmer/validator 0.94.0 (minor) +@glimmer/vm 0.94.0 (minor) +@glimmer/vm-babel-plugins 0.93.0 (minor) +@glimmer/wire-format 0.94.0 (minor) + +#### :rocket: Enhancement +* `@glimmer-workspace/meta-updater`, `@glimmer-workspace/bin`, `@glimmer-workspace/benchmark-env`, `@glimmer-workspace/build-support`, `@glimmer-workspace/env`, `@glimmer-workspace/eslint-plugin`, `@glimmer-workspace/integration-tests`, `@glimmer-workspace/test-utils`, `@glimmer/compiler`, `@glimmer/constants`, `@glimmer/debug-util`, `@glimmer/debug`, `@glimmer/destroyable`, `@glimmer/encoder`, `@glimmer/global-context`, `@glimmer/interfaces`, `@glimmer/local-debug-babel-plugin`, `@glimmer/local-debug-flags`, `@glimmer/manager`, `@glimmer/node`, `@glimmer/opcode-compiler`, `@glimmer/owner`, `@glimmer/program`, `@glimmer/reference`, `@glimmer/runtime`, `@glimmer/syntax`, `@glimmer/util`, `@glimmer/validator`, `@glimmer/vm-babel-plugins`, `@glimmer/vm`, `@glimmer/wire-format`, `@types/eslint-community__eslint-plugin-eslint-comments`, `@types/eslint-plugin-import`, `@types/eslint-plugin-qunit`, `@types/js-reporters`, `@types/puppeteer-chromium-resolver`, `@glimmer-workspace/repo-metadata` + * [#1677](https://github.com/glimmerjs/glimmer-vm/pull/1677) Refresh tsconfig and eslint setup ([@wycats](https://github.com/wycats)) +* `@glimmer-workspace/integration-tests`, `@glimmer/syntax` + * [#1673](https://github.com/glimmerjs/glimmer-vm/pull/1673) Lexical "this" capture ([@ef4](https://github.com/ef4)) + +#### :bug: Bug Fix +* `@glimmer-workspace/integration-tests`, `@glimmer/runtime` + * [#1672](https://github.com/glimmerjs/glimmer-vm/pull/1672) Feature: Basic mathml support ([@lifeart](https://github.com/lifeart)) + +#### :house: Internal +* Other + * [#1684](https://github.com/glimmerjs/glimmer-vm/pull/1684) Don't run the size check on main ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) + * [#1683](https://github.com/glimmerjs/glimmer-vm/pull/1683) Use our own local copy of @glimemr/syntax when we run prettier to make sure we didn't break prettier ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) + * [#1681](https://github.com/glimmerjs/glimmer-vm/pull/1681) Rotate the size chart ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) + * [#1679](https://github.com/glimmerjs/glimmer-vm/pull/1679) Compare sizes with main ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) + * [#1678](https://github.com/glimmerjs/glimmer-vm/pull/1678) Allow manual checkout for perf and size workflows ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) + * [#1641](https://github.com/glimmerjs/glimmer-vm/pull/1641) Measure sizes and post as a comment ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) +* `@types/puppeteer-chromium-resolver` + * [#1675](https://github.com/glimmerjs/glimmer-vm/pull/1675) Fix CI ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) + +#### Committers: 4 +- Alex Kanunnikov ([@lifeart](https://github.com/lifeart)) +- Edward Faulkner ([@ef4](https://github.com/ef4)) +- Yehuda Katz ([@wycats](https://github.com/wycats)) +- [@NullVoxPopuli](https://github.com/NullVoxPopuli) + +## Release (2024-11-27) + +@glimmer/compiler 0.93.1 (patch) +@glimmer/destroyable 0.93.1 (patch) +@glimmer/encoder 0.92.5 (patch) +@glimmer/manager 0.93.1 (patch) +@glimmer/node 0.93.1 (patch) +@glimmer/opcode-compiler 0.93.1 (patch) +@glimmer/owner 0.92.5 (patch) +@glimmer/program 0.93.1 (patch) +@glimmer/reference 0.93.1 (patch) +@glimmer/runtime 0.93.1 (patch) +@glimmer/syntax 0.93.1 (patch) +@glimmer/util 0.93.1 (patch) +@glimmer/validator 0.93.1 (patch) +@glimmer/vm 0.93.1 (patch) +@glimmer/wire-format 0.93.1 (patch) + +#### :bug: Bug Fix +* `@glimmer/syntax`, `@glimmer/util`, `@glimmer/wire-format` + * [#1669](https://github.com/glimmerjs/glimmer-vm/pull/1669) Closes [#1668](https://github.com/glimmerjs/glimmer-vm/issues/1668): Node does not use the 'development' condition with default require() - this PR removes the `development` condition under `require` for `@glimmer/syntax` and dependents. ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) + +#### Committers: 1 +- [@NullVoxPopuli](https://github.com/NullVoxPopuli) + +## Release (2024-11-22) + +@glimmer/compiler 0.93.0 (minor) +@glimmer/destroyable 0.93.0 (minor) +@glimmer/encoder 0.92.4 (patch) +@glimmer/global-context 0.92.4 (patch) +@glimmer/interfaces 0.93.0 (minor) +@glimmer/manager 0.93.0 (minor) +@glimmer/node 0.93.0 (minor) +@glimmer/opcode-compiler 0.93.0 (minor) +@glimmer/owner 0.92.4 (patch) +@glimmer/program 0.93.0 (minor) +@glimmer/reference 0.93.0 (minor) +@glimmer/runtime 0.93.0 (minor) +@glimmer/syntax 0.93.0 (minor) +@glimmer/util 0.93.0 (minor) +@glimmer/validator 0.93.0 (minor) +@glimmer/vm 0.93.0 (minor) +@glimmer/vm-babel-plugins 0.92.4 (patch) +@glimmer/wire-format 0.93.0 (minor) + +#### :rocket: Enhancement +* `@glimmer-workspace/integration-tests`, `@glimmer/compiler`, `@glimmer/constants`, `@glimmer/debug-util`, `@glimmer/debug`, `@glimmer/interfaces`, `@glimmer/opcode-compiler`, `@glimmer/program`, `@glimmer/runtime`, `@glimmer/syntax` + * [#1665](https://github.com/glimmerjs/glimmer-vm/pull/1665) Feature/pass args to debugger ([@wycats](https://github.com/wycats)) +* `@glimmer-workspace/benchmark-env`, `@glimmer-workspace/integration-tests`, `@glimmer/debug-util`, `@glimmer/debug`, `@glimmer/interfaces`, `@glimmer/node`, `@glimmer/opcode-compiler`, `@glimmer/program`, `@glimmer/runtime` + * [#1663](https://github.com/glimmerjs/glimmer-vm/pull/1663) Streamline and modernize naming ([@wycats](https://github.com/wycats)) +* `@glimmer-workspace/integration-tests`, `@glimmer/compiler`, `@glimmer/constants`, `@glimmer/runtime`, `@glimmer/vm` + * [#1664](https://github.com/glimmerjs/glimmer-vm/pull/1664) Move curried types to constants ([@wycats](https://github.com/wycats)) +* `@glimmer-workspace/bin`, `@glimmer/constants`, `@glimmer/debug`, `@glimmer/interfaces`, `@glimmer/opcode-compiler`, `@glimmer/runtime`, `@glimmer/vm` + * [#1662](https://github.com/glimmerjs/glimmer-vm/pull/1662) Remove Partial infra and rename eval -> debugger ([@wycats](https://github.com/wycats)) +* `@glimmer-workspace/krausest`, `@glimmer-workspace/bin`, `@glimmer-workspace/benchmark-env`, `@glimmer-workspace/build-support`, `@glimmer-workspace/integration-tests`, `@glimmer-workspace/test-utils`, `@glimmer/compiler`, `@glimmer/debug-util`, `@glimmer/debug`, `@glimmer/destroyable`, `@glimmer/interfaces`, `@glimmer/manager`, `@glimmer/node`, `@glimmer/opcode-compiler`, `@glimmer/program`, `@glimmer/reference`, `@glimmer/runtime`, `@glimmer/syntax`, `@glimmer/util`, `@glimmer/validator`, `@glimmer/vm`, `@glimmer/wire-format` + * [#1646](https://github.com/glimmerjs/glimmer-vm/pull/1646) Streamline append VM implementation ([@wycats](https://github.com/wycats)) +* `@glimmer-workspace/integration-tests`, `@glimmer/compiler`, `@glimmer/interfaces`, `@glimmer/opcode-compiler`, `@glimmer/program`, `@glimmer/runtime`, `@glimmer/syntax` + * [#1634](https://github.com/glimmerjs/glimmer-vm/pull/1634) Plumb debug symbols when using lexical scope ([@wycats](https://github.com/wycats)) + +#### :bug: Bug Fix +* `@glimmer/syntax` + * [#1651](https://github.com/glimmerjs/glimmer-vm/pull/1651) Revert "allow uppercase elements in strict mode" ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) + * [#1650](https://github.com/glimmerjs/glimmer-vm/pull/1650) allow uppercase elements in strict mode ([@patricklx](https://github.com/patricklx)) + +#### :house: Internal +* `@glimmer-workspace/krausest`, `@glimmer-workspace/bin`, `@glimmer-workspace/benchmark-env`, `@glimmer-workspace/integration-tests`, `@glimmer/compiler`, `@glimmer/constants`, `@glimmer/debug-util`, `@glimmer/debug`, `@glimmer/interfaces`, `@glimmer/local-debug-flags`, `@glimmer/node`, `@glimmer/opcode-compiler`, `@glimmer/program`, `@glimmer/reference`, `@glimmer/runtime`, `@glimmer/syntax`, `@glimmer/util`, `@glimmer/vm-babel-plugins`, `@glimmer/vm` + * [#1649](https://github.com/glimmerjs/glimmer-vm/pull/1649) Continue on with error-recovery infra refresh ([@wycats](https://github.com/wycats)) +* `@glimmer-workspace/benchmark-env`, `@glimmer-workspace/integration-tests`, `@glimmer/debug-util`, `@glimmer/debug`, `@glimmer/interfaces`, `@glimmer/node`, `@glimmer/opcode-compiler`, `@glimmer/program`, `@glimmer/runtime` + * [#1663](https://github.com/glimmerjs/glimmer-vm/pull/1663) Streamline and modernize naming ([@wycats](https://github.com/wycats)) +* `@glimmer-workspace/integration-tests` + * [#1658](https://github.com/glimmerjs/glimmer-vm/pull/1658) Additional coverage for each iteration with undefined item and specified key ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) +* `@glimmer-workspace/bin` + * [#1659](https://github.com/glimmerjs/glimmer-vm/pull/1659) Make tests fail when tests fail ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) + * [#1653](https://github.com/glimmerjs/glimmer-vm/pull/1653) Fix perf bench comment ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) +* `@glimmer-workspace/krausest`, `@glimmer-workspace/bin`, `@glimmer-workspace/build-support`, `@glimmer-workspace/integration-tests`, `@glimmer/compiler`, `@glimmer/constants`, `@glimmer/debug-util`, `@glimmer/debug`, `@glimmer/destroyable`, `@glimmer/interfaces`, `@glimmer/local-debug-flags`, `@glimmer/opcode-compiler`, `@glimmer/program`, `@glimmer/runtime`, `@glimmer/syntax`, `@glimmer/util`, `@glimmer/vm` + * [#1645](https://github.com/glimmerjs/glimmer-vm/pull/1645) Move from const enums to consts ([@wycats](https://github.com/wycats)) +* `@glimmer-workspace/bin`, `@glimmer-workspace/benchmark-env`, `@glimmer-workspace/integration-tests`, `@glimmer/compiler`, `@glimmer/debug-util`, `@glimmer/debug`, `@glimmer/destroyable`, `@glimmer/encoder`, `@glimmer/global-context`, `@glimmer/interfaces`, `@glimmer/local-debug-babel-plugin`, `@glimmer/local-debug-flags`, `@glimmer/manager`, `@glimmer/node`, `@glimmer/opcode-compiler`, `@glimmer/owner`, `@glimmer/program`, `@glimmer/reference`, `@glimmer/runtime`, `@glimmer/syntax`, `@glimmer/util`, `@glimmer/validator`, `@glimmer/vm-babel-plugins`, `@glimmer/vm`, `@glimmer/wire-format` + * [#1648](https://github.com/glimmerjs/glimmer-vm/pull/1648) Improve benchmark setup, consistently rely on publishConfig ([@wycats](https://github.com/wycats)) +* `@glimmer-workspace/krausest`, `@glimmer-workspace/bin`, `@glimmer-workspace/build-support`, `@glimmer-workspace/test-utils`, `@glimmer/debug`, `@glimmer/global-context`, `@glimmer/interfaces`, `@glimmer/manager`, `@glimmer/node`, `@glimmer/opcode-compiler`, `@glimmer/owner`, `@glimmer/syntax`, `@glimmer/util`, `@glimmer/validator` + * [#1647](https://github.com/glimmerjs/glimmer-vm/pull/1647) Improve benchmark setup ([@wycats](https://github.com/wycats)) +* Other + * [#1640](https://github.com/glimmerjs/glimmer-vm/pull/1640) Run perf tests if a PR has the 'perf' label ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) + * [#1638](https://github.com/glimmerjs/glimmer-vm/pull/1638) Allow perf to run on PRs from forkrs ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) + * [#1627](https://github.com/glimmerjs/glimmer-vm/pull/1627) Add `packageManager` to root package.json and `use-node-version` to the .npmrc ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) +* `@glimmer-workspace/bin`, `@glimmer/syntax`, `@types/puppeteer-chromium-resolver` + * [#1628](https://github.com/glimmerjs/glimmer-vm/pull/1628) Update puppeteer, node (for perf testing), and the setup script which launches tracerbench ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) +* `@glimmer-workspace/bin`, `@glimmer/debug`, `@glimmer/manager`, `@glimmer/opcode-compiler`, `@glimmer/syntax` + * [#1625](https://github.com/glimmerjs/glimmer-vm/pull/1625) Don't build @glimmer/debug, as no package should be using it during publish-time ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) +* `@glimmer-workspace/bin`, `@glimmer/compiler`, `@glimmer/debug`, `@glimmer/destroyable`, `@glimmer/encoder`, `@glimmer/global-context`, `@glimmer/interfaces`, `@glimmer/manager`, `@glimmer/node`, `@glimmer/opcode-compiler`, `@glimmer/owner`, `@glimmer/program`, `@glimmer/reference`, `@glimmer/runtime`, `@glimmer/syntax`, `@glimmer/util`, `@glimmer/validator`, `@glimmer/vm-babel-plugins`, `@glimmer/vm`, `@glimmer/wire-format` + * [#1624](https://github.com/glimmerjs/glimmer-vm/pull/1624) Force bump, plan fix for release-plan ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) + +#### Committers: 3 +- Patrick Pircher ([@patricklx](https://github.com/patricklx)) +- Yehuda Katz ([@wycats](https://github.com/wycats)) +- [@NullVoxPopuli](https://github.com/NullVoxPopuli) + +## Release (2024-09-13) + + + +#### :bug: Bug Fix +* `@glimmer-workspace/bin`, `@glimmer-workspace/build-support` + * [#1622](https://github.com/glimmerjs/glimmer-vm/pull/1622) Add CI step for verifying that unwanted code does not get published ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) + +#### Committers: 1 +- [@NullVoxPopuli](https://github.com/NullVoxPopuli) + +## Release (2024-09-12) + +@glimmer/compiler 0.92.2 (patch) +@glimmer/debug 0.92.3 (patch) +@glimmer/destroyable 0.92.2 (patch) +@glimmer/encoder 0.92.2 (patch) +@glimmer/global-context 0.92.2 (patch) +@glimmer/interfaces 0.92.2 (patch) +@glimmer/manager 0.92.3 (patch) +@glimmer/node 0.92.3 (patch) +@glimmer/opcode-compiler 0.92.3 (patch) +@glimmer/owner 0.92.2 (patch) +@glimmer/program 0.92.3 (patch) +@glimmer/reference 0.92.2 (patch) +@glimmer/runtime 0.92.3 (patch) +@glimmer/syntax 0.92.3 (patch) +@glimmer/util 0.92.2 (patch) +@glimmer/validator 0.92.2 (patch) +@glimmer/vm 0.92.2 (patch) +@glimmer/vm-babel-plugins 0.92.2 (patch) +@glimmer/wire-format 0.92.2 (patch) + +#### :bug: Bug Fix +* `@glimmer/debug`, `@glimmer/compiler`, `@glimmer/destroyable`, `@glimmer/encoder`, `@glimmer/global-context`, `@glimmer/interfaces`, `@glimmer/manager`, `@glimmer/node`, `@glimmer/opcode-compiler`, `@glimmer/owner`, `@glimmer/program`, `@glimmer/reference`, `@glimmer/runtime`, `@glimmer/syntax`, `@glimmer/util`, `@glimmer/validator`, `@glimmer/vm`, `@glimmer/vm-babel-plugins`, `@glimmer/wire-format` + * [#1620](https://github.com/glimmerjs/glimmer-vm/pull/1620) cause patch release of glimmer debug ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) + +#### :house: Internal +* [#1619](https://github.com/glimmerjs/glimmer-vm/pull/1619) Add turbo build before publish ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) +* [#1617](https://github.com/glimmerjs/glimmer-vm/pull/1617) Use ignore-scripts during publish, as we don't need to install browsers during publish ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) + +#### Committers: 1 +- [@NullVoxPopuli](https://github.com/NullVoxPopuli) + +## Release (2024-09-12) + +@glimmer/debug 0.92.3 (patch) +@glimmer/manager 0.92.3 (patch) +@glimmer/node 0.92.3 (patch) +@glimmer/opcode-compiler 0.92.3 (patch) +@glimmer/program 0.92.3 (patch) +@glimmer/runtime 0.92.3 (patch) + +#### :bug: Bug Fix +* `@glimmer/debug` + * [#1620](https://github.com/glimmerjs/glimmer-vm/pull/1620) cause patch release of glimmer debug ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) + +#### :house: Internal +* [#1619](https://github.com/glimmerjs/glimmer-vm/pull/1619) Add turbo build before publish ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) +* [#1617](https://github.com/glimmerjs/glimmer-vm/pull/1617) Use ignore-scripts during publish, as we don't need to install browsers during publish ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) + +#### Committers: 1 +- [@NullVoxPopuli](https://github.com/NullVoxPopuli) + +## Release (2024-09-11) + +@glimmer/compiler 0.92.1 (patch) +@glimmer/debug 0.92.2 (patch) +@glimmer/destroyable 0.92.1 (patch) +@glimmer/encoder 0.92.1 (patch) +@glimmer/global-context 0.92.1 (patch) +@glimmer/interfaces 0.92.1 (patch) +@glimmer/manager 0.92.2 (patch) +@glimmer/node 0.92.2 (patch) +@glimmer/opcode-compiler 0.92.2 (patch) +@glimmer/owner 0.92.1 (patch) +@glimmer/program 0.92.2 (patch) +@glimmer/reference 0.92.1 (patch) +@glimmer/runtime 0.92.2 (patch) +@glimmer/syntax 0.92.1 (patch) +@glimmer/util 0.92.1 (patch) +@glimmer/validator 0.92.1 (patch) +@glimmer/vm 0.92.1 (patch) +@glimmer/vm-babel-plugins 0.92.1 (patch) +@glimmer/wire-format 0.92.1 (patch) + +#### :bug: Bug Fix +* `@glimmer-workspace/build-support`, `@glimmer/debug`, `@glimmer/local-debug-babel-plugin` + * [#1606](https://github.com/glimmerjs/glimmer-vm/pull/1606) Fix stripping local debug code so can that dead-code-elimination produces smaller bundles with fewer function calls (part 1) ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) + +#### :house: Internal +* `@glimmer-workspace/krausest`, `@glimmer-workspace/bin`, `@glimmer-workspace/benchmark-env`, `@glimmer-workspace/integration-tests`, `@glimmer-workspace/test-utils`, `@glimmer/compiler`, `@glimmer/debug`, `@glimmer/destroyable`, `@glimmer/encoder`, `@glimmer/global-context`, `@glimmer/interfaces`, `@glimmer/manager`, `@glimmer/node`, `@glimmer/opcode-compiler`, `@glimmer/owner`, `@glimmer/program`, `@glimmer/reference`, `@glimmer/runtime`, `@glimmer/syntax`, `@glimmer/util`, `@glimmer/validator`, `@glimmer/vm-babel-plugins`, `@glimmer/vm`, `@glimmer/wire-format` + * [#1616](https://github.com/glimmerjs/glimmer-vm/pull/1616) Declare all workspace protocols workspace:* so that patch bumps bump all consumers as well ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) +* Other + * [#1615](https://github.com/glimmerjs/glimmer-vm/pull/1615) When generating the release plan, we don't need to run the puppeteer install -- so we can use --ignore-scripts ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) + * [#1614](https://github.com/glimmerjs/glimmer-vm/pull/1614) Do not have nested packages ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) + * [#1612](https://github.com/glimmerjs/glimmer-vm/pull/1612) Don't run the Krausest benchmark unless we have to ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) + * [#1613](https://github.com/glimmerjs/glimmer-vm/pull/1613) Add a name entry to a package.json that didn't have a name -- all package.jsons must have a name ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) + * [#1610](https://github.com/glimmerjs/glimmer-vm/pull/1610) Have the release-automation workflows use the same setup as CI ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) + * [#1609](https://github.com/glimmerjs/glimmer-vm/pull/1609) Sync pnpm versions in the new release-automation workflows ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) + * [#1607](https://github.com/glimmerjs/glimmer-vm/pull/1607) Setup Release plan, remove release-it ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) + +#### Committers: 1 +- [@NullVoxPopuli](https://github.com/NullVoxPopuli) + + + + + + + + + + + + + + + + + + + + + + + + + + + +## v0.92.0 (2024-04-08) + +#### :rocket: Enhancement +* `@glimmer-workspace/integration-tests`, `@glimmer/compiler`, `@glimmer/interfaces`, `@glimmer/syntax` + * [#1585](https://github.com/glimmerjs/glimmer-vm/pull/1585) Introduce `keywords` option for `precompile` ([@chancancode](https://github.com/chancancode)) + +#### Committers: 1 +- Godfrey Chan ([@chancancode](https://github.com/chancancode)) + +## v0.91.2 (2024-04-05) + +#### :bug: Bug Fix +* `@glimmer/syntax` + * [#1577](https://github.com/glimmerjs/glimmer-vm/pull/1577) fix extra spaces in block params ([@patricklx](https://github.com/patricklx)) + +#### Committers: 1 +- Patrick Pircher ([@patricklx](https://github.com/patricklx)) + +## v0.91.1 (2024-03-28) + +#### :bug: Bug Fix +* `@glimmer/syntax` + * [#1583](https://github.com/glimmerjs/glimmer-vm/pull/1583) [BUGFIX] Ensure legacy path.parts matches existing semantics ([@chancancode](https://github.com/chancancode)) + +#### Committers: 1 +- Godfrey Chan ([@chancancode](https://github.com/chancancode)) + +## v0.91.0 (2024-03-25) + +#### :rocket: Enhancement +* `@glimmer/syntax` + * [#1582](https://github.com/glimmerjs/glimmer-vm/pull/1582) Prevent use of ...attributes in invalid places ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) + +#### Committers: 1 +- [@NullVoxPopuli](https://github.com/NullVoxPopuli) + +## v0.90.1 (2024-03-22) + +#### :bug: Bug Fix +* `@glimmer/compiler`, `@glimmer/syntax` + * [#1581](https://github.com/glimmerjs/glimmer-vm/pull/1581) Remove index imports as they are not defined by package.json#exports ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) + +#### Committers: 1 +- [@NullVoxPopuli](https://github.com/NullVoxPopuli) + +## v0.90.0 (2024-03-22) + +#### :boom: Breaking Change +* `@glimmer-workspace/integration-tests`, `@glimmer/runtime` + * [#1580](https://github.com/glimmerjs/glimmer-vm/pull/1580) Remove deprecation for setting hash properties (from years ago) ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) + +#### :rocket: Enhancement +* `@glimmer-workspace/integration-tests`, `@glimmer/runtime` + * [#1580](https://github.com/glimmerjs/glimmer-vm/pull/1580) Remove deprecation for setting hash properties (from years ago) ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) + +#### :bug: Bug Fix +* `@glimmer/compiler`, `@glimmer/debug`, `@glimmer/encoder`, `@glimmer/global-context`, `@glimmer/interfaces`, `@glimmer/local-debug-flags`, `@glimmer/manager`, `@glimmer/node`, `@glimmer/opcode-compiler`, `@glimmer/program`, `@glimmer/syntax`, `@glimmer/vm` + * [#1579](https://github.com/glimmerjs/glimmer-vm/pull/1579) Add missing licenses ([@andreyfel](https://github.com/andreyfel)) + +#### Committers: 3 +- Andrey Fel ([@andreyfel](https://github.com/andreyfel)) +- Godfrey Chan ([@chancancode](https://github.com/chancancode)) +- [@NullVoxPopuli](https://github.com/NullVoxPopuli) + +## v0.89.0 (2024-03-09) + +#### :rocket: Enhancement +* `@glimmer-workspace/integration-tests`, `@glimmer/interfaces`, `@glimmer/node`, `@glimmer/runtime` + * [#1560](https://github.com/glimmerjs/glimmer-vm/pull/1560) add in element to debug render tree ([@patricklx](https://github.com/patricklx)) +* `@glimmer-workspace/integration-tests`, `@glimmer-workspace`, `@glimmer/syntax` + * [#1568](https://github.com/glimmerjs/glimmer-vm/pull/1568) Cleanup v1 AST ([@chancancode](https://github.com/chancancode)) +* `@glimmer/syntax` + * [#1561](https://github.com/glimmerjs/glimmer-vm/pull/1561) [CLEANUP] Remove unused ASTv1 nodes ([@chancancode](https://github.com/chancancode)) + +#### :bug: Bug Fix +* `@glimmer-workspace/integration-tests`, `@glimmer/runtime` + * [#1565](https://github.com/glimmerjs/glimmer-vm/pull/1565) Don't infinitely duplicate positional arguments when modifiers update ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) +* `@glimmer/syntax` + * [#1562](https://github.com/glimmerjs/glimmer-vm/pull/1562) [BUGFIX] properly surface deprecation message ([@chancancode](https://github.com/chancancode)) + +#### :house: Internal +* `@glimmer/debug`, `@glimmer/runtime` + * [#1573](https://github.com/glimmerjs/glimmer-vm/pull/1573) Refactor on modifier implementation ([@chancancode](https://github.com/chancancode)) +* `@glimmer-workspace/integration-tests`, `@glimmer/validator` + * [#1556](https://github.com/glimmerjs/glimmer-vm/pull/1556) Restore test harness on CI ([@chancancode](https://github.com/chancancode)) + +#### Committers: 3 +- Godfrey Chan ([@chancancode](https://github.com/chancancode)) +- Patrick Pircher ([@patricklx](https://github.com/patricklx)) +- [@NullVoxPopuli](https://github.com/NullVoxPopuli) + +## v0.88.1 (2024-01-31) + +#### :bug: Bug Fix +* `@glimmer/interfaces` + * [#1555](https://github.com/glimmerjs/glimmer-vm/pull/1555) @glimmer/interfaces now uses extensions in its imports. ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) + +#### Committers: 1 +- [@NullVoxPopuli](https://github.com/NullVoxPopuli) + +## v0.88.0 (2024-01-26) + +#### :rocket: Enhancement +* `@glimmer/syntax` + * [#1552](https://github.com/glimmerjs/glimmer-vm/pull/1552) add block param nodes ([@patricklx](https://github.com/patricklx)) + * [#1553](https://github.com/glimmerjs/glimmer-vm/pull/1553) add element parts, startTag & endTag ([@patricklx](https://github.com/patricklx)) + +#### :bug: Bug Fix +* `@glimmer/destroyable` + * [#1543](https://github.com/glimmerjs/glimmer-vm/pull/1543) Fix @glimmer/destroyable dev exports ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) + +#### :house: Internal +* [#1554](https://github.com/glimmerjs/glimmer-vm/pull/1554) support run tests on windows ([@patricklx](https://github.com/patricklx)) +* [#1544](https://github.com/glimmerjs/glimmer-vm/pull/1544) Upgrade esyes ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) + +#### Committers: 2 +- Patrick Pircher ([@patricklx](https://github.com/patricklx)) +- [@NullVoxPopuli](https://github.com/NullVoxPopuli) + +## v0.87.1 (2023-12-24) + +#### :rocket: Enhancement +* `@glimmer-workspace/integration-tests`, `@glimmer/runtime` + * [#1535](https://github.com/glimmerjs/glimmer-vm/pull/1535) [chore] remove ie11 `on` fallback ([@lifeart](https://github.com/lifeart)) + +#### Committers: 1 +- Alex Kanunnikov ([@lifeart](https://github.com/lifeart)) + +## v0.87.0 (2023-12-24) + +#### :rocket: Enhancement +* `@glimmer-workspace/integration-tests`, `@glimmer/debug`, `@glimmer/runtime`, `@glimmer/util`, `@glimmer/validator` + * [#1539](https://github.com/glimmerjs/glimmer-vm/pull/1539) Drop ie11 code ([@ef4](https://github.com/ef4)) + +#### :bug: Bug Fix +* `@glimmer/runtime` + * [#1538](https://github.com/glimmerjs/glimmer-vm/pull/1538) Make feature discovery lazy ([@ef4](https://github.com/ef4)) + +#### :house: Internal +* [#1537](https://github.com/glimmerjs/glimmer-vm/pull/1537) adjust benchmark close to real-life usage ([@lifeart](https://github.com/lifeart)) + +#### Committers: 2 +- Alex Kanunnikov ([@lifeart](https://github.com/lifeart)) +- Edward Faulkner ([@ef4](https://github.com/ef4)) + +## v0.86.0 (2023-12-20) + +#### :rocket: Enhancement +* `@glimmer/debug`, `@glimmer/runtime`, `@glimmer/util` + * [#1518](https://github.com/glimmerjs/glimmer-vm/pull/1518) [perf] avoid double memory usage in append opcodes ([@lifeart](https://github.com/lifeart)) +* `@glimmer/validator` + * [#1520](https://github.com/glimmerjs/glimmer-vm/pull/1520) [perf] replace Math.max usage with reduce and pure compare ([@lifeart](https://github.com/lifeart)) + * [#1522](https://github.com/glimmerjs/glimmer-vm/pull/1522) [memory] replace forEach with arrayFrom ([@lifeart](https://github.com/lifeart)) +* `@glimmer/runtime` + * [#1510](https://github.com/glimmerjs/glimmer-vm/pull/1510) [perf | trim] Remove extra class ([@lifeart](https://github.com/lifeart)) + +#### :bug: Bug Fix +* `@glimmer/runtime` + * [#1440](https://github.com/glimmerjs/glimmer-vm/pull/1440) Fix helper/modifier memory leak ([@bendemboski](https://github.com/bendemboski)) +* `@glimmer/debug`, `@glimmer/destroyable` + * [#1516](https://github.com/glimmerjs/glimmer-vm/pull/1516) fix `exports` config for @glimmer/destroyable and @glimmer/debug ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) + +#### :house: Internal +* `@glimmer-workspace/build` + * [#1530](https://github.com/glimmerjs/glimmer-vm/pull/1530) Upgrade to vite 5 ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) + * [#1495](https://github.com/glimmerjs/glimmer-vm/pull/1495) make it run on windows ([@patricklx](https://github.com/patricklx)) +* Other + * [#1523](https://github.com/glimmerjs/glimmer-vm/pull/1523) Restore a working linking setup ([@chancancode](https://github.com/chancancode)) + * [#1497](https://github.com/glimmerjs/glimmer-vm/pull/1497) Create codemods and opcode generator ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) +* `@glimmer-workspace/benchmark-env`, `@glimmer-workspace/build`, `@glimmer-workspace/integration-tests`, `@glimmer-workspace/test-utils`, `@glimmer/compiler`, `@glimmer/debug`, `@glimmer/destroyable`, `@glimmer/encoder`, `@glimmer/global-context`, `@glimmer/interfaces`, `@glimmer/local-debug-flags`, `@glimmer/manager`, `@glimmer/node`, `@glimmer/opcode-compiler`, `@glimmer/owner`, `@glimmer/program`, `@glimmer/reference`, `@glimmer/runtime`, `@glimmer/syntax`, `@glimmer/util`, `@glimmer/validator`, `@glimmer/vm-babel-plugins`, `@glimmer/vm`, `@glimmer/wire-format` + * [#1506](https://github.com/glimmerjs/glimmer-vm/pull/1506) Sort package.json files to reduce diff from the Error Recovery PR ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) +* `@glimmer/reference` + * [#1483](https://github.com/glimmerjs/glimmer-vm/pull/1483) Use stricter type for createPrimitiveRef ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) + +#### Committers: 5 +- Alex Kanunnikov ([@lifeart](https://github.com/lifeart)) +- Ben Demboski ([@bendemboski](https://github.com/bendemboski)) +- Godfrey Chan ([@chancancode](https://github.com/chancancode)) +- Patrick Pircher ([@patricklx](https://github.com/patricklx)) +- [@NullVoxPopuli](https://github.com/NullVoxPopuli) + +## v0.85.13 (2023-11-14) + +#### :house: Internal +* `@glimmer-workspace/build`, `@glimmer/local-debug-flags` + * [#1494](https://github.com/glimmerjs/glimmer-vm/pull/1494) Compile away local debug for publish ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) +* `@glimmer-workspace/integration-tests`, `@glimmer/interfaces`, `@glimmer/runtime`, `@glimmer/vm-babel-plugins` + * [#1493](https://github.com/glimmerjs/glimmer-vm/pull/1493) Revert "fix capture render tree fails when errors in args" ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) + +#### Committers: 1 +- [@NullVoxPopuli](https://github.com/NullVoxPopuli) + +## v0.85.12 (2023-11-02) + +#### :bug: Bug Fix +* `@glimmer/compiler`, `@glimmer/debug`, `@glimmer/destroyable`, `@glimmer/encoder`, `@glimmer/global-context`, `@glimmer/interfaces`, `@glimmer/manager`, `@glimmer/node`, `@glimmer/opcode-compiler`, `@glimmer/owner`, `@glimmer/program`, `@glimmer/reference`, `@glimmer/runtime`, `@glimmer/syntax`, `@glimmer/util`, `@glimmer/validator`, `@glimmer/vm-babel-plugins`, `@glimmer/vm`, `@glimmer/wire-format` + * [#1488](https://github.com/glimmerjs/glimmer-vm/pull/1488) Add back package.json#module so the ember build can have fewer changes ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) +* `@glimmer-workspace/integration-tests`, `@glimmer/interfaces`, `@glimmer/runtime`, `@glimmer/vm-babel-plugins` + * [#1460](https://github.com/glimmerjs/glimmer-vm/pull/1460) fix capture render tree fails when errors in args ([@patricklx](https://github.com/patricklx)) + +#### :house: Internal +* `@glimmer`, `@glimmer/dom-change-list` + * [#1486](https://github.com/glimmerjs/glimmer-vm/pull/1486) Remove @glimmer/dom-change-list as nothing depends on it ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) +* `@glimmer/compiler`, `@glimmer/debug`, `@glimmer/destroyable`, `@glimmer/dom-change-list`, `@glimmer/encoder`, `@glimmer/global-context`, `@glimmer/interfaces`, `@glimmer/manager`, `@glimmer/node`, `@glimmer/opcode-compiler`, `@glimmer/owner`, `@glimmer/program`, `@glimmer/reference`, `@glimmer/runtime`, `@glimmer/syntax`, `@glimmer/util`, `@glimmer/validator`, `@glimmer/vm-babel-plugins`, `@glimmer/vm`, `@glimmer/wire-format` + * [#1482](https://github.com/glimmerjs/glimmer-vm/pull/1482) Setup the cache server ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) + +#### Committers: 2 +- Patrick Pircher ([@patricklx](https://github.com/patricklx)) +- [@NullVoxPopuli](https://github.com/NullVoxPopuli) + +## v0.85.11 (2023-11-01) + +#### :bug: Bug Fix +* `@glimmer/runtime` + * [#1485](https://github.com/glimmerjs/glimmer-vm/pull/1485) Remove dependency on @glimmer/low-level because it doesn't exist anymore (and is unused) ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) + +#### Committers: 1 +- [@NullVoxPopuli](https://github.com/NullVoxPopuli) + +## v0.85.10 (2023-11-01) + +#### :bug: Bug Fix +* `@glimmer/reference` + * [#1484](https://github.com/glimmerjs/glimmer-vm/pull/1484) Unify reference factory function signatures ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) + +#### Committers: 1 +- [@NullVoxPopuli](https://github.com/NullVoxPopuli) + +## v0.85.9 (2023-11-01) + +#### :bug: Bug Fix +* `@glimmer/reference` + * [#1481](https://github.com/glimmerjs/glimmer-vm/pull/1481) MakePrimitiveRef generic so that UNDEFINED_REFERENCE can be Reference rather than Reference ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) + +#### Committers: 1 +- [@NullVoxPopuli](https://github.com/NullVoxPopuli) + +## v0.85.8 (2023-10-31) + +#### :house: Internal +* `@glimmer/vm` + * [#1480](https://github.com/glimmerjs/glimmer-vm/pull/1480) Re-add CJS exports to the VM package ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) + +#### Committers: 1 +- [@NullVoxPopuli](https://github.com/NullVoxPopuli) + +## v0.85.7 (2023-10-31) + +#### :house: Internal +* `@glimmer-workspace/build`, `@glimmer/compiler`, `@glimmer/debug`, `@glimmer/destroyable`, `@glimmer/dom-change-list`, `@glimmer/encoder`, `@glimmer/global-context`, `@glimmer/interfaces`, `@glimmer/manager`, `@glimmer/node`, `@glimmer/opcode-compiler`, `@glimmer/owner`, `@glimmer/program`, `@glimmer/reference`, `@glimmer/runtime`, `@glimmer/syntax`, `@glimmer/util`, `@glimmer/validator`, `@glimmer/vm-babel-plugins`, `@glimmer/vm`, `@glimmer/wire-format` + * [#1479](https://github.com/glimmerjs/glimmer-vm/pull/1479) CJS needs to be enabled entirely, because ember-source requires it for now ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) + +#### Committers: 1 +- [@NullVoxPopuli](https://github.com/NullVoxPopuli) + +## v0.85.6 (2023-10-31) + +#### :bug: Bug Fix +* `@glimmer-workspace/build`, `@glimmer/compiler`, `@glimmer/syntax` + * [#1478](https://github.com/glimmerjs/glimmer-vm/pull/1478) Add CJS back to glimmer/syntax,compiler ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) + +#### Committers: 1 +- [@NullVoxPopuli](https://github.com/NullVoxPopuli) + +## v0.85.5 (2023-10-30) + +#### :bug: Bug Fix +* `@glimmer/global-context` + * [#1476](https://github.com/glimmerjs/glimmer-vm/pull/1476) @glimmer/global-context forgot to override main/types during publish ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) + +#### Committers: 1 +- [@NullVoxPopuli](https://github.com/NullVoxPopuli) + +## v0.85.4 (2023-10-30) + +#### :bug: Bug Fix +* `@glimmer-workspace/eslint-plugin`, `@glimmer`, `@glimmer/compiler`, `@glimmer/debug`, `@glimmer/destroyable`, `@glimmer/dom-change-list`, `@glimmer/encoder`, `@glimmer/global-context`, `@glimmer/interfaces`, `@glimmer/manager`, `@glimmer/node`, `@glimmer/opcode-compiler`, `@glimmer/owner`, `@glimmer/program`, `@glimmer/reference`, `@glimmer/runtime`, `@glimmer/syntax`, `@glimmer/util`, `@glimmer/validator`, `@glimmer/vm-babel-plugins`, `@glimmer/vm`, `@glimmer/wire-format` + * [#1470](https://github.com/glimmerjs/glimmer-vm/pull/1470) Fix the package contents of each package, only publishing dist ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) +* `@glimmer/syntax` + * [#1467](https://github.com/glimmerjs/glimmer-vm/pull/1467) visitorKeys is needed for prettier ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) + * [#1468](https://github.com/glimmerjs/glimmer-vm/pull/1468) Use a Set for checking if an element is a void element, which is faster than object access ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) +* `@glimmer/compiler`, `@glimmer/debug`, `@glimmer/destroyable`, `@glimmer/dom-change-list`, `@glimmer/encoder`, `@glimmer/global-context`, `@glimmer/interfaces`, `@glimmer/local-debug-flags`, `@glimmer/manager`, `@glimmer/node`, `@glimmer/opcode-compiler`, `@glimmer/owner`, `@glimmer/program`, `@glimmer/reference`, `@glimmer/runtime`, `@glimmer/syntax`, `@glimmer/util`, `@glimmer/validator`, `@glimmer/vm-babel-plugins`, `@glimmer/vm`, `@glimmer/wire-format` + * [#1466](https://github.com/glimmerjs/glimmer-vm/pull/1466) declare type=module ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) + +#### :house: Internal +* `@glimmer-workspace/build`, `@glimmer/compiler`, `@glimmer/debug`, `@glimmer/destroyable`, `@glimmer/dom-change-list`, `@glimmer/encoder`, `@glimmer/global-context`, `@glimmer/interfaces`, `@glimmer/manager`, `@glimmer/node`, `@glimmer/opcode-compiler`, `@glimmer/owner`, `@glimmer/program`, `@glimmer/reference`, `@glimmer/runtime`, `@glimmer/syntax`, `@glimmer/util`, `@glimmer/validator`, `@glimmer/vm-babel-plugins`, `@glimmer/vm`, `@glimmer/wire-format` + * [#1472](https://github.com/glimmerjs/glimmer-vm/pull/1472) Fix the build. Split dev from prod. In dev, convert import.meta.env.DEV to DEBUG from `@glimmer/env` ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) +* Other + * [#1475](https://github.com/glimmerjs/glimmer-vm/pull/1475) dedupe lockfile ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) + * [#1471](https://github.com/glimmerjs/glimmer-vm/pull/1471) Set default git config, add github config, per the rest of ember-family-of-projects-automation ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) +* `@glimmer-workspace`, `@glimmer-workspace/benchmark-env`, `@glimmer-workspace/build`, `@glimmer-workspace/eslint-plugin`, `@glimmer-workspace/integration-tests`, `@glimmer-workspace/test-utils`, `@glimmer`, `@glimmer/compiler`, `@glimmer/debug`, `@glimmer/destroyable`, `@glimmer/dom-change-list`, `@glimmer/encoder`, `@glimmer/global-context`, `@glimmer/interfaces`, `@glimmer/local-debug-flags`, `@glimmer/manager`, `@glimmer/node`, `@glimmer/opcode-compiler`, `@glimmer/owner`, `@glimmer/program`, `@glimmer/reference`, `@glimmer/runtime`, `@glimmer/syntax`, `@glimmer/util`, `@glimmer/validator`, `@glimmer/vm-babel-plugins`, `@glimmer/vm`, `@glimmer/wire-format` + * [#1474](https://github.com/glimmerjs/glimmer-vm/pull/1474) Update lints ahead of #1462, so that #1462's diff is smaller ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) +* `@glimmer/compiler`, `@glimmer/debug`, `@glimmer/destroyable`, `@glimmer/dom-change-list`, `@glimmer/encoder`, `@glimmer/global-context`, `@glimmer/interfaces`, `@glimmer/manager`, `@glimmer/node`, `@glimmer/opcode-compiler`, `@glimmer/owner`, `@glimmer/program`, `@glimmer/reference`, `@glimmer/runtime`, `@glimmer/syntax`, `@glimmer/util`, `@glimmer/validator`, `@glimmer/vm-babel-plugins`, `@glimmer/vm`, `@glimmer/wire-format` + * [#1473](https://github.com/glimmerjs/glimmer-vm/pull/1473) Add rollup to every package with a rollup config ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) + +#### Committers: 1 +- [@NullVoxPopuli](https://github.com/NullVoxPopuli) + +## 0.85.3 (2023-10-24) + +#### :bug: Bug Fix +* `@glimmer-workspace/integration-tests`, `@glimmer/runtime` + * [#1459](https://github.com/glimmerjs/glimmer-vm/pull/1459) Revert "fix: capture render tree can fail if args cannot be obtained" ([@patricklx](https://github.com/patricklx)) + +#### :house: Internal +* [#1452](https://github.com/glimmerjs/glimmer-vm/pull/1452) rename local token in release workflow ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) + +#### Committers: 2 +- Patrick Pircher ([@patricklx](https://github.com/patricklx)) +- [@NullVoxPopuli](https://github.com/NullVoxPopuli) + +## 0.85.2 (2023-10-23) + +#### :house: Internal +* [#1451](https://github.com/glimmerjs/glimmer-vm/pull/1451) Allow publishing from tags / non-branches ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) + +#### Committers: 1 +- [@NullVoxPopuli](https://github.com/NullVoxPopuli) + +## 0.85.1 (2023-10-23) + +#### :house: Internal +* `@glimmer/wire-format` + * [#1450](https://github.com/glimmerjs/glimmer-vm/pull/1450) Use workspace protocol everywhere so release-it doesn't cause a diff,… ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) + +#### Committers: 1 +- [@NullVoxPopuli](https://github.com/NullVoxPopuli) + +## 0.85.0 (2023-10-23) + +#### :rocket: Enhancement +* `@glimmer/compiler`, `@glimmer/debug`, `@glimmer/dom-change-list`, `@glimmer/integration-tests`, `@glimmer/interfaces`, `@glimmer/opcode-compiler`, `@glimmer/runtime`, `@glimmer/syntax`, `@glimmer/validator`, `@glimmer/vm` + * [#1421](https://github.com/glimmerjs/glimmer-vm/pull/1421) Improve lexical scope ([@wycats](https://github.com/wycats)) +* `@glimmer/syntax` + * [#1420](https://github.com/glimmerjs/glimmer-vm/pull/1420) [syntax] Remove v2-b and rename v2-a to v2 ([@wycats](https://github.com/wycats)) + +#### :bug: Bug Fix +* `@glimmer/syntax` + * [#1412](https://github.com/glimmerjs/glimmer-vm/pull/1412) Fix another issue with getTemplateLocals and block params ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) + +#### :house: Internal +* Other + * [#1444](https://github.com/glimmerjs/glimmer-vm/pull/1444) Add release workflow ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) + * [#1437](https://github.com/glimmerjs/glimmer-vm/pull/1437) GH Actions: Move to wyvox and off branch ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) + * [#1415](https://github.com/glimmerjs/glimmer-vm/pull/1415) Try upgrading ember-cli-browserstack ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) +* `@glimmer-workspace`, `@glimmer-workspace/benchmark-env`, `@glimmer-workspace/build`, `@glimmer-workspace/eslint-plugin`, `@glimmer-workspace/integration-tests`, `@glimmer-workspace/test-utils`, `@glimmer`, `@glimmer/compiler`, `@glimmer/debug`, `@glimmer/destroyable`, `@glimmer/dom-change-list`, `@glimmer/encoder`, `@glimmer/global-context`, `@glimmer/integration-tests`, `@glimmer/interfaces`, `@glimmer/local-debug-flags`, `@glimmer/manager`, `@glimmer/node`, `@glimmer/opcode-compiler`, `@glimmer/owner`, `@glimmer/program`, `@glimmer/reference`, `@glimmer/runtime`, `@glimmer/syntax`, `@glimmer/test-utils`, `@glimmer/util`, `@glimmer/validator`, `@glimmer/vm-babel-plugins`, `@glimmer/vm`, `@glimmer/wire-format`, `@types`, `@types/qunit`, `build-utils` + * [#1427](https://github.com/glimmerjs/glimmer-vm/pull/1427) Restore performance tests ([@wycats](https://github.com/wycats)) +* `@glimmer`, `@glimmer/benchmark-env`, `@glimmer/compiler`, `@glimmer/destroyable`, `@glimmer/dom-change-list`, `@glimmer/integration-tests`, `@glimmer/interfaces`, `@glimmer/manager`, `@glimmer/opcode-compiler`, `@glimmer/owner`, `@glimmer/program`, `@glimmer/reference`, `@glimmer/runtime`, `@glimmer/syntax`, `@glimmer/util`, `@glimmer/validator`, `@glimmer/vm`, `@types`, `@types/puppeteer-chromium-resolver`, `@types/qunit`, `build-utils` + * [#1426](https://github.com/glimmerjs/glimmer-vm/pull/1426) Follow-up migrate to vite (restore type tests) ([@wycats](https://github.com/wycats)) +* `@glimmer/benchmark-env`, `@glimmer/compiler`, `@glimmer/debug`, `@glimmer/destroyable`, `@glimmer/dom-change-list`, `@glimmer/encoder`, `@glimmer/global-context`, `@glimmer/integration-tests`, `@glimmer/interfaces`, `@glimmer/local-debug-flags`, `@glimmer/manager`, `@glimmer/node`, `@glimmer/opcode-compiler`, `@glimmer/owner`, `@glimmer/program`, `@glimmer/reference`, `@glimmer/runtime`, `@glimmer/syntax`, `@glimmer/test-utils`, `@glimmer/util`, `@glimmer/validator`, `@glimmer/vm`, `@glimmer/wire-format`, `@types/js-reporters`, `@types/qunit` + * [#1423](https://github.com/glimmerjs/glimmer-vm/pull/1423) Migrate to Vite ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) +* `@glimmer/debug`, `@glimmer/dom-change-list`, `@glimmer/integration-tests`, `@glimmer/interfaces`, `@glimmer/node`, `@glimmer/runtime`, `@glimmer/syntax`, `@glimmer/validator` + * [#1419](https://github.com/glimmerjs/glimmer-vm/pull/1419) Continue updating infrastructure ([@wycats](https://github.com/wycats)) +* `@glimmer/benchmark-env`, `@glimmer/compiler`, `@glimmer/debug`, `@glimmer/destroyable`, `@glimmer/dom-change-list`, `@glimmer/encoder`, `@glimmer/integration-tests`, `@glimmer/interfaces`, `@glimmer/manager`, `@glimmer/node`, `@glimmer/opcode-compiler`, `@glimmer/owner`, `@glimmer/program`, `@glimmer/reference`, `@glimmer/runtime`, `@glimmer/syntax`, `@glimmer/util`, `@glimmer/validator`, `@glimmer/vm`, `@glimmer/wire-format` + * [#1418](https://github.com/glimmerjs/glimmer-vm/pull/1418) Modernize Infrastructure ([@wycats](https://github.com/wycats)) + +#### Committers: 3 +- Patrick Pircher ([@patricklx](https://github.com/patricklx)) +- Yehuda Katz ([@wycats](https://github.com/wycats)) +- [@NullVoxPopuli](https://github.com/NullVoxPopuli) + +## v0.84.3 (2023-03-23) + +#### :bug: Bug Fix +* `@glimmer/runtime` + * [#1402](https://github.com/glimmerjs/glimmer-vm/pull/1402) Allow passing `false` to the `on` modifier's options ([@boris-petrov](https://github.com/boris-petrov)) +* `@glimmer/integration-tests` + * [#1391](https://github.com/glimmerjs/glimmer-vm/pull/1391) Update Firefox detection in `on` modifier test (remove use of `InstallTrigger`) ([@bertdeblock](https://github.com/bertdeblock)) +* `@glimmer/syntax` + * [#1390](https://github.com/glimmerjs/glimmer-vm/pull/1390) Allow components to be named the same as void tags ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) + +#### :house: Internal +* `@glimmer/integration-tests` + * [#1394](https://github.com/glimmerjs/glimmer-vm/pull/1394) Fix typo ([@2hu12](https://github.com/2hu12)) + +#### Committers: 5 +- 2hu ([@2hu12](https://github.com/2hu12)) +- Bert De Block ([@bertdeblock](https://github.com/bertdeblock)) +- Boris Petrov ([@boris-petrov](https://github.com/boris-petrov)) +- Simon Ihmig ([@simonihmig](https://github.com/simonihmig)) +- [@NullVoxPopuli](https://github.com/NullVoxPopuli) + +## v0.84.2 (2022-04-13) + +#### :bug: Bug Fix +* `@glimmer/syntax` + * [#1380](https://github.com/glimmerjs/glimmer-vm/pull/1380) fix: #1379 - Unclear compiler error if literal used as a path ([@lifeart](https://github.com/lifeart)) +* `@glimmer/integration-tests`, `@glimmer/manager` + * [#1389](https://github.com/glimmerjs/glimmer-vm/pull/1389) Fix a problem where plain functions can't be used as helper if they are not passed through the strict mode context object ([@Windvis](https://github.com/Windvis)) +* `@glimmer/integration-tests`, `@glimmer/runtime` + * [#1387](https://github.com/glimmerjs/glimmer-vm/pull/1387) Fix typo in `fn` helper error message ([@bertdeblock](https://github.com/bertdeblock)) + +#### Committers: 3 +- Alex Kanunnikov ([@lifeart](https://github.com/lifeart)) +- Bert De Block ([@bertdeblock](https://github.com/bertdeblock)) +- Sam Van Campenhout ([@Windvis](https://github.com/Windvis)) + + +## v0.84.1 (2022-03-15) + +#### :rocket: Enhancement +* `@glimmer/global-context`, `@glimmer/integration-tests`, `@glimmer/manager` + * [#1384](https://github.com/glimmerjs/glimmer-vm/pull/1384) Add a `DEFAULT_HELPER_MANAGER` feature flag ([@Windvis](https://github.com/Windvis)) + +#### Committers: 1 +- Sam Van Campenhout ([@Windvis](https://github.com/Windvis)) + + +## v0.84.0 (2022-02-15) + +#### :rocket: Enhancement +* `@glimmer/integration-tests`, `@glimmer/manager` + * [#1348](https://github.com/glimmerjs/glimmer-vm/pull/1348) Implement Default Helper Manager (RFC #756) ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) + +#### :bug: Bug Fix +* `@glimmer/syntax` + * [#1375](https://github.com/glimmerjs/glimmer-vm/pull/1375) fix: buildElement options should be optional ([@runspired](https://github.com/runspired)) + +#### :memo: Documentation +* `@glimmer/integration-tests`, `@glimmer/runtime` + * [#1346](https://github.com/glimmerjs/glimmer-vm/pull/1346) Fix comma splice in `on` modifier error message. ([@muziejus](https://github.com/muziejus)) + +#### Committers: 5 +- Aaron Sikes ([@courajs](https://github.com/courajs)) +- Chris Thoburn ([@runspired](https://github.com/runspired)) +- James C. Davis ([@jamescdavis](https://github.com/jamescdavis)) +- Moacir P. de Sá Pereira ([@muziejus](https://github.com/muziejus)) +- [@NullVoxPopuli](https://github.com/NullVoxPopuli) + +## v0.83.1 (2021-11-08) + +#### :bug: Bug Fix +* `@glimmer/compiler`, `@glimmer/interfaces`, `@glimmer/opcode-compiler`, `@glimmer/syntax` + * [#1362](https://github.com/glimmerjs/glimmer-vm/pull/1362) Fix issues with "loose free variable" lookup by dropping unneeded `GetFreeAsFallback` op code ([@ef4](https://github.com/ef4)) + +#### Committers: 1 +- Edward Faulkner ([@ef4](https://github.com/ef4)) + + +## v0.83.0 (2021-11-05) + +#### :boom: Breaking Change +* `@glimmer/interfaces`, `@glimmer/opcode-compiler` + * [#1349](https://github.com/glimmerjs/glimmer-vm/pull/1349) Follow up: more {{partial}} cleanup after removal ([@snewcomer](https://github.com/snewcomer)) + +#### :rocket: Enhancement +* `@glimmer/integration-tests`, `@glimmer/syntax` + * [#1351](https://github.com/glimmerjs/glimmer-vm/pull/1351) Support lexical scope in loose mode ([@ef4](https://github.com/ef4)) + +#### Committers: 3 +- Edward Faulkner ([@ef4](https://github.com/ef4)) +- Jaydon Peng ([@v-jiepeng](https://github.com/v-jiepeng)) +- Scott Newcomer ([@snewcomer](https://github.com/snewcomer)) + + +## v0.82.0 (2021-10-06) + +#### :boom: Breaking Change +* `@glimmer/integration-tests`, `@glimmer/interfaces`, `@glimmer/opcode-compiler` + * [#1331](https://github.com/glimmerjs/glimmer-vm/pull/1331) [cleanup]: Remove `this.` property fallback (e.g. the `this-property-fallback` deprecation) ([@snewcomer](https://github.com/snewcomer)) +* `@glimmer/benchmark-env`, `@glimmer/compiler`, `@glimmer/debug`, `@glimmer/integration-tests`, `@glimmer/interfaces`, `@glimmer/opcode-compiler`, `@glimmer/runtime`, `@glimmer/vm` + * [#1332](https://github.com/glimmerjs/glimmer-vm/pull/1332) Remove support for `{{partial}}` ([@snewcomer](https://github.com/snewcomer)) + +#### :rocket: Enhancement +* `@glimmer/syntax` + * [#1344](https://github.com/glimmerjs/glimmer-vm/pull/1344) Cache `head` getter in `PathExpressionImplV1` ([@chriskrycho](https://github.com/chriskrycho)) + +#### :bug: Bug Fix +* `@glimmer/manager` + * [#1343](https://github.com/glimmerjs/glimmer-vm/pull/1343) Remove deprecated versions of modifier/component manager capabilities from error messages ([@nlfurniss](https://github.com/nlfurniss)) + +#### Committers: 3 +- Chris Krycho ([@chriskrycho](https://github.com/chriskrycho)) +- Nathaniel Furniss ([@nlfurniss](https://github.com/nlfurniss)) +- Scott Newcomer ([@snewcomer](https://github.com/snewcomer)) + + +## v0.81.0 (2021-09-27) + +#### :boom: Breaking Change +* `@glimmer/integration-tests`, `@glimmer/manager`, `@glimmer/validator` + * [#1330](https://github.com/glimmerjs/glimmer-vm/pull/1330) Remove deprecated support for mutation after consumption during certain manager hooks ([@snewcomer](https://github.com/snewcomer)) +* `@glimmer/manager` + * [#1328](https://github.com/glimmerjs/glimmer-vm/pull/1328) Remove deprecated Component Manager version 3.4 ([@nlfurniss](https://github.com/nlfurniss)) +* `@glimmer/integration-tests`, `@glimmer/manager` + * [#1329](https://github.com/glimmerjs/glimmer-vm/pull/1329) Remove deprecated Modifier Manager version 3.13 ([@nlfurniss](https://github.com/nlfurniss)) + +#### :rocket: Enhancement +* `@glimmer/syntax` + * [#1341](https://github.com/glimmerjs/glimmer-vm/pull/1341) Remove unused `scope` from Walker ([@chriskrycho](https://github.com/chriskrycho)) +* `@glimmer/integration-tests`, `@glimmer/syntax` + * [#1305](https://github.com/glimmerjs/glimmer-vm/pull/1305) Update simple-html-tokenizer to v0.5.11 and support doctype ([@laurensclaessen](https://github.com/laurensclaessen)) +* `@glimmer/compiler`, `@glimmer/syntax` + * [#1335](https://github.com/glimmerjs/glimmer-vm/pull/1335) Use `_private` instead of `#private` properties ([@chriskrycho](https://github.com/chriskrycho)) + +#### :bug: Bug Fix +* `@glimmer/syntax` + * [#1338](https://github.com/glimmerjs/glimmer-vm/pull/1338) Use `Object.assign` instead of custom `copy` function ([@chriskrycho](https://github.com/chriskrycho)) + +#### Committers: 4 +- Chris Krycho ([@chriskrycho](https://github.com/chriskrycho)) +- Laurens Claessen ([@laurensclaessen](https://github.com/laurensclaessen)) +- Nathaniel Furniss ([@nlfurniss](https://github.com/nlfurniss)) +- Scott Newcomer ([@snewcomer](https://github.com/snewcomer)) + + +## v0.80.0 (2021-06-29) + +#### :boom: Breaking Change +* `@glimmer/integration-tests`, `@glimmer/reference`, `@glimmer/runtime` + * [#1323](https://github.com/glimmerjs/glimmer-vm/pull/1323) Revert hash to bi-modal behavior ([@pzuraq](https://github.com/pzuraq)) + +#### Committers: 1 +- Chris Garrett ([@pzuraq](https://github.com/pzuraq)) + +## v0.79.4 (2021-06-21) + +#### :rocket: Enhancement +* `@glimmer/runtime` + * [#1319](https://github.com/glimmerjs/glimmer-vm/pull/1319) Adds isHashProxy ([@pzuraq](https://github.com/pzuraq)) + +#### Committers: 1 +- Chris Garrett ([@pzuraq](https://github.com/pzuraq)) + +## v0.79.3 (2021-05-27) + +#### :bug: Bug Fix +* `@glimmer/runtime` + * [#1318](https://github.com/glimmerjs/glimmer-vm/pull/1318) Ensure hash works with custom tags ([@pzuraq](https://github.com/pzuraq)) + +#### :house: Internal +* `@glimmer/destroyable`, `@glimmer/global-context`, `@glimmer/integration-tests`, `@glimmer/reference` + * [#1317](https://github.com/glimmerjs/glimmer-vm/pull/1317) Fix global-context test leakage ([@pzuraq](https://github.com/pzuraq)) +* `@glimmer/interfaces`, `@glimmer/runtime`, `@glimmer/util` + * [#1316](https://github.com/glimmerjs/glimmer-vm/pull/1316) Remove UpdatingOpcode base classes ([@pzuraq](https://github.com/pzuraq)) +* Other + * [#1315](https://github.com/glimmerjs/glimmer-vm/pull/1315) Strip assert and deprecate from the benchmark ([@pzuraq](https://github.com/pzuraq)) + +#### Committers: 2 +- Chris Garrett ([@pzuraq](https://github.com/pzuraq)) +- [@NullVoxPopuli](https://github.com/NullVoxPopuli) + +## v0.79.2 (2021-05-20) + +#### :bug: Bug Fix +* `@glimmer/integration-tests`, `@glimmer/runtime` + * [#1308](https://github.com/glimmerjs/glimmer-vm/pull/1308) Allow all (hash) keys to be set ([@pzuraq](https://github.com/pzuraq)) + +#### Committers: 1 +- Chris Garrett ([@pzuraq](https://github.com/pzuraq)) + +## v0.79.1 (2021-05-11) + +#### :bug: Bug Fix +* `@glimmer/runtime` + * [#1304](https://github.com/glimmerjs/glimmer-vm/pull/1304) Remove unnecessary property descriptor assertion from hash ([@pzuraq](https://github.com/pzuraq)) + +#### Committers: 1 +- Chris Garrett ([@pzuraq](https://github.com/pzuraq)) + +## v0.79.0 (2021-04-27) + +#### :boom: Breaking Change +* `@glimmer/low-level`, `@glimmer/runtime` + * [#1299](https://github.com/glimmerjs/glimmer-vm/pull/1299) Simplify Stack (remove `@glimmer/low-level` package) ([@pzuraq](https://github.com/pzuraq)) + +#### :bug: Bug Fix +* `@glimmer/integration-tests`, `@glimmer/runtime` + * [#1298](https://github.com/glimmerjs/glimmer-vm/pull/1298) [BUGFIX] Ensure `hash` properties are reified lazily ([@pzuraq](https://github.com/pzuraq)) + +#### Committers: 1 +- Chris Garrett ([@pzuraq](https://github.com/pzuraq)) + +## v0.78.2 (2021-04-22) + +#### :bug: Bug Fix +* `@glimmer/opcode-compiler` + * [#1297](https://github.com/glimmerjs/glimmer-vm/pull/1297) Fix evaluation stack off-by-one error introduced in #1293 ([@chancancode](https://github.com/chancancode)) + +#### Committers: 1 +- Godfrey Chan ([@chancancode](https://github.com/chancancode)) + + +## v0.78.1 (2021-04-21) + +#### :bug: Bug Fix +* `@glimmer/compiler`, `@glimmer/integration-tests`, `@glimmer/syntax` + * [#1296](https://github.com/glimmerjs/glimmer-vm/pull/1296) Correctly handle <:inverse> named block ([@wagenet](https://github.com/wagenet)) + +#### Committers: 1 +- Peter Wagenet ([@wagenet](https://github.com/wagenet)) + + +## v0.78.0 (2021-04-15) + +#### :rocket: Enhancement +* `@glimmer/compiler`, `@glimmer/integration-tests`, `@glimmer/interfaces`, `@glimmer/opcode-compiler`, `@glimmer/syntax` + * [#1295](https://github.com/glimmerjs/glimmer-vm/pull/1295) Deprecate `@foo={{helper}}` ([@chancancode](https://github.com/chancancode)) + +#### :bug: Bug Fix +* `@glimmer/integration-tests`, `@glimmer/opcode-compiler`, `@glimmer/runtime` + * [#1293](https://github.com/glimmerjs/glimmer-vm/pull/1293) Fix nested calls to helpers in dynamic helpers ([@pzuraq](https://github.com/pzuraq)) + +#### Committers: 3 +- Chris Garrett ([@pzuraq](https://github.com/pzuraq)) +- Godfrey Chan ([@chancancode](https://github.com/chancancode)) +- Milind Alvares ([@milindalvares](https://github.com/milindalvares)) + + +## v0.77.6 (2021-03-25) + +#### :rocket: Enhancement +* `build-utils` + * [#1290](https://github.com/glimmerjs/glimmer-vm/pull/1290) Fixes VM Babel plugin generation in browsers ([@pzuraq](https://github.com/pzuraq)) + +#### Committers: 1 +- Chris Garrett ([@pzuraq](https://github.com/pzuraq)) + +## v0.77.5 (2021-03-23) + +#### :bug: Bug Fix +* `@glimmer/syntax` + * [#1289](https://github.com/glimmerjs/glimmer-vm/pull/1289) Exclude HTML elements from template locals by default ([@pzuraq](https://github.com/pzuraq)) + +#### Committers: 1 +- Chris Garrett ([@pzuraq](https://github.com/pzuraq)) + +## v0.77.4 (2021-03-22) + +#### :rocket: Enhancement +* `@glimmer/syntax` + * [#1287](https://github.com/glimmerjs/glimmer-vm/pull/1287) Adds a utility for parsing template locals ([@pzuraq](https://github.com/pzuraq)) + +#### Committers: 1 +- Chris Garrett ([@pzuraq](https://github.com/pzuraq)) + +## v0.77.3 (2021-03-16) + +#### :bug: Bug Fix +* `@glimmer/integration-tests`, `@glimmer/manager` + * [#1276](https://github.com/glimmerjs/glimmer-vm/pull/1276) [BUGFIX] Do not eagerly consume modifier args during destruction ([@pzuraq](https://github.com/pzuraq)) + +#### Committers: 1 +- Chris Garrett ([@pzuraq](https://github.com/pzuraq)) + + +## v0.77.2 (2021-03-16) + +#### :bug: Bug Fix +* `@glimmer/syntax` + * [#1284](https://github.com/glimmerjs/glimmer-vm/pull/1284) Ensure Entities are never transformed in codemod mode. ([@rwjblue](https://github.com/rwjblue)) + +#### :house: Internal +* `@glimmer/syntax` + * [#1285](https://github.com/glimmerjs/glimmer-vm/pull/1285) Pin @handlebars/parser to 2.0.x. ([@rwjblue](https://github.com/rwjblue)) + +#### Committers: 1 +- Robert Jackson ([@rwjblue](https://github.com/rwjblue)) + + +## v0.77.1 (2021-02-17) + +#### :bug: Bug Fix +* `@glimmer/manager` + * [#1275](https://github.com/glimmerjs/glimmer-vm/pull/1275) Fix generics on setInternalHelperManager ([@pzuraq](https://github.com/pzuraq)) + +#### Committers: 1 +- Chris Garrett ([@pzuraq](https://github.com/pzuraq)) + +## v0.77.0 (2021-02-17) + +#### :boom: Breaking Change +* `@glimmer/benchmark-env`, `@glimmer/compiler`, `@glimmer/destroyable`, `@glimmer/integration-tests`, `@glimmer/interfaces`, `@glimmer/manager`, `@glimmer/reference`, `@glimmer/runtime`, `@glimmer/util` + * [#1267](https://github.com/glimmerjs/glimmer-vm/pull/1267) [BUGFIX] Fixes dynamic helpers and modifiers with updating definitions ([@pzuraq](https://github.com/pzuraq)) + +#### :rocket: Enhancement +* `@glimmer/compiler`, `@glimmer/integration-tests`, `@glimmer/interfaces`, `@glimmer/opcode-compiler`, `@glimmer/program`, `@glimmer/syntax` + * [#1274](https://github.com/glimmerjs/glimmer-vm/pull/1274) Revert "Removes id from templates" ([@pzuraq](https://github.com/pzuraq)) + +#### :bug: Bug Fix +* `@glimmer/compiler` + * [#1261](https://github.com/glimmerjs/glimmer-vm/pull/1261) Make defaultId function more robust ([@pzuraq](https://github.com/pzuraq)) +* `@glimmer/util` + * [#1273](https://github.com/glimmerjs/glimmer-vm/pull/1273) [BUGFIX] Use built-in Object.assign if possible ([@pzuraq](https://github.com/pzuraq)) + +#### :house: Internal +* `@glimmer/integration-tests`, `@glimmer/interfaces`, `@glimmer/manager` + * [#1271](https://github.com/glimmerjs/glimmer-vm/pull/1271) Upstream modifier tests ([@pzuraq](https://github.com/pzuraq)) + +#### Committers: 1 +- Chris Garrett ([@pzuraq](https://github.com/pzuraq)) + +## v0.76.0 (2021-02-16) + +#### :boom: Breaking Change +* `@glimmer/integration-tests`, `@glimmer/interfaces`, `@glimmer/opcode-compiler`, `@glimmer/program`, `@glimmer/runtime` + * [#1263](https://github.com/glimmerjs/glimmer-vm/pull/1263) [BUGFIX] Ensure owner is available during resolution for all components ([@pzuraq](https://github.com/pzuraq)) + +#### :bug: Bug Fix +* `@glimmer/compiler`, `@glimmer/integration-tests`, `@glimmer/interfaces` + * [#1270](https://github.com/glimmerjs/glimmer-vm/pull/1270) Ensure inline `if` returns `undefined` when no falsey value is provided ([@rwjblue](https://github.com/rwjblue)) +* `@glimmer/integration-tests`, `@glimmer/runtime` + * [#1268](https://github.com/glimmerjs/glimmer-vm/pull/1268) [BUGFIX] Fix reactivity of dynamic attributes ([@pzuraq](https://github.com/pzuraq)) + * [#1269](https://github.com/glimmerjs/glimmer-vm/pull/1269) [BUGFIX] Fix {{get}} when used on non-objects ([@pzuraq](https://github.com/pzuraq)) +* `@glimmer/syntax` + * [#1266](https://github.com/glimmerjs/glimmer-vm/pull/1266) Maintain relative order of attributes and comments within an `ElementNode` ([@charlespierce](https://github.com/charlespierce)) + +#### :house: Internal +* `@glimmer/integration-tests` + * [#1265](https://github.com/glimmerjs/glimmer-vm/pull/1265) Add tests for helper managers ([@pzuraq](https://github.com/pzuraq)) + +#### Committers: 3 +- Charles Pierce ([@charlespierce](https://github.com/charlespierce)) +- Chris Garrett ([@pzuraq](https://github.com/pzuraq)) +- Robert Jackson ([@rwjblue](https://github.com/rwjblue)) + + +## v0.75.0 (2021-02-09) + +#### :boom: Breaking Change +* `@glimmer/compiler`, `@glimmer/integration-tests`, `@glimmer/interfaces`, `@glimmer/opcode-compiler`, `@glimmer/program`, `@glimmer/syntax` + * [#1262](https://github.com/glimmerjs/glimmer-vm/pull/1262) Removes id from templates ([@pzuraq](https://github.com/pzuraq)) + +#### Committers: 1 +- Chris Garrett ([@pzuraq](https://github.com/pzuraq)) + +## v0.74.2 (2021-02-01) + +#### :bug: Bug Fix +* `@glimmer/compiler`, `@glimmer/interfaces` + * [#1260](https://github.com/glimmerjs/glimmer-vm/pull/1260) Omit scope property from precompiled templates in loose mode ([@rwjblue](https://github.com/rwjblue)) + +#### Committers: 1 +- Robert Jackson ([@rwjblue](https://github.com/rwjblue)) + + +## v0.74.1 (2021-02-01) + +#### :rocket: Enhancement +* `@glimmer/integration-tests`, `@glimmer/interfaces`, `@glimmer/opcode-compiler`, `@glimmer/validator` + * [#1259](https://github.com/glimmerjs/glimmer-vm/pull/1259) Adds deprecation for property fallback lookup ([@pzuraq](https://github.com/pzuraq)) + +#### Committers: 1 +- Chris Garrett ([@pzuraq](https://github.com/pzuraq)) + + +## v0.74.0 (2021-01-30) + +#### :boom: Breaking Change +* `@glimmer/benchmark-env`, `@glimmer/global-context`, `@glimmer/integration-tests`, `@glimmer/validator`, `build-utils` + * [#1257](https://github.com/glimmerjs/glimmer-vm/pull/1257) Add `assert` and `deprecate` to global context API ([@pzuraq](https://github.com/pzuraq)) + +#### :bug: Bug Fix +* `@glimmer/integration-tests`, `@glimmer/syntax` + * [#1255](https://github.com/glimmerjs/glimmer-vm/pull/1255) Don't call `customizeComponentName` on curly components ([@dfreeman](https://github.com/dfreeman)) + +#### :house: Internal +* `@glimmer/integration-tests`, `@glimmer/syntax` + * [#1258](https://github.com/glimmerjs/glimmer-vm/pull/1258) Remove usages of `this.property` fallback from tests ([@pzuraq](https://github.com/pzuraq)) + +#### Committers: 2 +- Chris Garrett ([@pzuraq](https://github.com/pzuraq)) +- Dan Freeman ([@dfreeman](https://github.com/dfreeman)) + +## v0.73.2 (2021-01-21) + +#### :bug: Bug Fix +* `@glimmer/integration-tests`, `@glimmer/syntax` + * [#1253](https://github.com/glimmerjs/glimmer-vm/pull/1253) [BUGFIX] Convert component names after symbol allocation ([@pzuraq](https://github.com/pzuraq)) + +#### Committers: 1 +- Chris Garrett ([@pzuraq](https://github.com/pzuraq)) + + +## v0.73.1 (2020-12-21) + +#### :bug: Bug Fix +* `@glimmer/compiler`, `@glimmer/integration-tests` + * [#1249](https://github.com/glimmerjs/glimmer-vm/pull/1249) Ensure `{{component.name}}` works with implicit this fallback in loose mode. ([@rwjblue](https://github.com/rwjblue)) + +#### :house: Internal +* [#1248](https://github.com/glimmerjs/glimmer-vm/pull/1248) Update automated release tooling ([@rwjblue](https://github.com/rwjblue)) + +#### Committers: 1 +- Robert Jackson ([@rwjblue](https://github.com/rwjblue)) + + +## v0.73.0 (2020-12-18) + +#### :boom: Breaking Change +* `@glimmer/benchmark-env`, `@glimmer/global-context`, `@glimmer/integration-tests`, `@glimmer/runtime`, `@glimmer/util` + * [#1245](https://github.com/glimmerjs/glimmer-vm/pull/1245) [FEATURE] Upstream built-in helpers and modifiers from Ember ([@pzuraq](https://github.com/pzuraq)) +* `@glimmer/compiler`, `@glimmer/integration-tests`, `@glimmer/interfaces`, `@glimmer/opcode-compiler`, `@glimmer/runtime` + * [#1243](https://github.com/glimmerjs/glimmer-vm/pull/1243) [FEATURE] Upstreams {{log}} keyword ([@pzuraq](https://github.com/pzuraq)) + * [#1242](https://github.com/glimmerjs/glimmer-vm/pull/1242) [REFACTOR] Make `-get-dynamic-var` a keyword ([@pzuraq](https://github.com/pzuraq)) + +#### :rocket: Enhancement +* `@glimmer/compiler`, `@glimmer/debug`, `@glimmer/integration-tests`, `@glimmer/interfaces`, `@glimmer/opcode-compiler`, `@glimmer/runtime`, `@glimmer/vm` + * [#1240](https://github.com/glimmerjs/glimmer-vm/pull/1240) [FEATURE] Adds inline if and unless keywords ([@pzuraq](https://github.com/pzuraq)) + +#### :bug: Bug Fix +* `@glimmer/runtime` + * [#1241](https://github.com/glimmerjs/glimmer-vm/pull/1241) Fix missing component error message ([@ef4](https://github.com/ef4)) + +#### :house: Internal +* `@glimmer/compiler`, `@glimmer/integration-tests` + * [#1244](https://github.com/glimmerjs/glimmer-vm/pull/1244) [REFACTOR] Deduplicate keyword logic ([@pzuraq](https://github.com/pzuraq)) + +#### Committers: 2 +- Chris Garrett ([@pzuraq](https://github.com/pzuraq)) +- Edward Faulkner ([@ef4](https://github.com/ef4)) + + +## v0.72.0 (2020-12-17) + +#### :boom: Breaking Change +* `@glimmer/compiler`, `@glimmer/debug`, `@glimmer/integration-tests`, `@glimmer/interfaces`, `@glimmer/opcode-compiler`, `@glimmer/runtime`, `@glimmer/vm` + * [#1237](https://github.com/glimmerjs/glimmer-vm/pull/1237) [REFACTOR] Unifies currying for all values ([@pzuraq](https://github.com/pzuraq)) + +#### :rocket: Enhancement +* `@glimmer/compiler`, `@glimmer/debug`, `@glimmer/integration-tests`, `@glimmer/interfaces`, `@glimmer/manager`, `@glimmer/opcode-compiler`, `@glimmer/program`, `@glimmer/runtime`, `@glimmer/syntax` + * [#1238](https://github.com/glimmerjs/glimmer-vm/pull/1238) [FEATURE] Adds dynamic modifiers ([@pzuraq](https://github.com/pzuraq)) + +#### Committers: 1 +- Chris Garrett ([@pzuraq](https://github.com/pzuraq)) + + +## v0.71.2 (2020-12-17) + +Version unpublished due to incorrect semver (breaking change occured) + +## v0.71.1 (2020-12-16) + +Republish with correct prod build + + +## v0.71.0 (2020-12-15) + +#### :boom: Breaking Change +* `@glimmer/compiler`, `@glimmer/debug`, `@glimmer/integration-tests`, `@glimmer/interfaces`, `@glimmer/manager`, `@glimmer/opcode-compiler`, `@glimmer/program`, `@glimmer/runtime`, `@glimmer/syntax`, `@glimmer/vm` + * [#1235](https://github.com/glimmerjs/glimmer-vm/pull/1235) [FEATURE] Adds dynamic curly components and helpers ([@pzuraq](https://github.com/pzuraq)) +* `@glimmer/benchmark-env`, `@glimmer/integration-tests`, `@glimmer/interfaces`, `@glimmer/manager`, `@glimmer/opcode-compiler`, `@glimmer/program`, `@glimmer/runtime` + * [#1234](https://github.com/glimmerjs/glimmer-vm/pull/1234) [REFACTOR] Removes owner from managers ([@pzuraq](https://github.com/pzuraq)) + +#### :bug: Bug Fix +* `@glimmer/util` + * [#1212](https://github.com/glimmerjs/glimmer-vm/pull/1212) [Bugfix] debug-to-string-tests ([@lifeart](https://github.com/lifeart)) + +#### Committers: 2 +- Alex Kanunnikov ([@lifeart](https://github.com/lifeart)) +- Chris Garrett ([@pzuraq](https://github.com/pzuraq)) + +## v0.70.0 (2020-12-14) + +#### :boom: Breaking Change +* `@glimmer/benchmark-env`, `@glimmer/integration-tests`, `@glimmer/interfaces`, `@glimmer/manager`, `@glimmer/opcode-compiler`, `@glimmer/runtime` + * [#1232](https://github.com/glimmerjs/glimmer-vm/pull/1232) [REFACTOR] Make Owner VM state ([@pzuraq](https://github.com/pzuraq)) + +#### Committers: 1 +- Chris Garrett ([@pzuraq](https://github.com/pzuraq)) + +## v0.69.3 (2020-12-10) + +#### :bug: Bug Fix +* `@glimmer/integration-tests`, `@glimmer/syntax` + * [#1231](https://github.com/glimmerjs/glimmer-vm/pull/1231) [BUGFIX] Ensure template locals work in nested blocks ([@pzuraq](https://github.com/pzuraq)) + +#### Committers: 1 +- Chris Garrett ([@pzuraq](https://github.com/pzuraq)) + +## v0.69.2 (2020-12-10) + +#### :bug: Bug Fix +* `@glimmer/runtime` + * [#1230](https://github.com/glimmerjs/glimmer-vm/pull/1230) [BUGFIX] Re-export isDestroying/ed ([@pzuraq](https://github.com/pzuraq)) + +#### Committers: 1 +- Chris Garrett ([@pzuraq](https://github.com/pzuraq)) + + +## v0.69.1 (2020-12-10) + +#### :bug: Bug Fix +* `@glimmer/syntax` + * [#1229](https://github.com/glimmerjs/glimmer-vm/pull/1229) [BUGFIX] Makes ASTPluginEnvironment generic ([@pzuraq](https://github.com/pzuraq)) + +#### Committers: 1 +- Chris Garrett ([@pzuraq](https://github.com/pzuraq)) + +## v0.69.0 (2020-12-10) + +#### :boom: Breaking Change +* `@glimmer/benchmark-env`, `@glimmer/compiler`, `@glimmer/debug`, `@glimmer/integration-tests`, `@glimmer/interfaces`, `@glimmer/manager`, `@glimmer/opcode-compiler`, `@glimmer/program`, `@glimmer/runtime`, `@glimmer/syntax`, `@glimmer/vm` + * [#1225](https://github.com/glimmerjs/glimmer-vm/pull/1225) [FEAT] Implements Strict Mode ([@pzuraq](https://github.com/pzuraq)) + +#### :rocket: Enhancement +* `@glimmer/compiler`, `@glimmer/integration-tests`, `@glimmer/syntax` + * [#1227](https://github.com/glimmerjs/glimmer-vm/pull/1227) [FEAT] Finishes up named blocks ([@pzuraq](https://github.com/pzuraq)) + * [#1226](https://github.com/glimmerjs/glimmer-vm/pull/1226) [FEAT] Enable sub-expressions in mustache position ([@pzuraq](https://github.com/pzuraq)) + +#### :bug: Bug Fix +* `@glimmer/integration-tests`, `@glimmer/syntax` + * [#1228](https://github.com/glimmerjs/glimmer-vm/pull/1228) [BUGFIX] Fix tag classification in strict ([@pzuraq](https://github.com/pzuraq)) + +#### Committers: 1 +- Chris Garrett ([@pzuraq](https://github.com/pzuraq)) + +## v0.68.1 (2020-12-06) + +#### :bug: Bug Fix +* `@glimmer/manager`, `@glimmer/util` + * [#1224](https://github.com/glimmerjs/glimmer-vm/pull/1224) [BUGFIX] Make the custom tag system non-enumerable ([@pzuraq](https://github.com/pzuraq)) +* `@glimmer/runtime` + * [#1223](https://github.com/glimmerjs/glimmer-vm/pull/1223) [BUGFIX] Fix @glimmer/component ([@pzuraq](https://github.com/pzuraq)) + +#### Committers: 1 +- Chris Garrett ([@pzuraq](https://github.com/pzuraq)) + +## v0.68.0 (2020-12-04) + +#### :boom: Breaking Change +* `@glimmer/benchmark-env`, `@glimmer/debug`, `@glimmer/integration-tests`, `@glimmer/interfaces`, `@glimmer/manager`, `@glimmer/node`, `@glimmer/opcode-compiler`, `@glimmer/program`, `@glimmer/runtime`, `@glimmer/util` + * [#1222](https://github.com/glimmerjs/glimmer-vm/pull/1222) [REFACTOR] Align resolver and internals with strict mode ([@pzuraq](https://github.com/pzuraq)) +* `@glimmer/destroyable`, `@glimmer/integration-tests`, `@glimmer/manager`, `@glimmer/owner`, `@glimmer/runtime` + * [#1221](https://github.com/glimmerjs/glimmer-vm/pull/1221) [REFACTOR] Extract Owner and Destroyables into their own packages ([@pzuraq](https://github.com/pzuraq)) +* `@glimmer/benchmark-env`, `@glimmer/debug`, `@glimmer/integration-tests`, `@glimmer/interfaces`, `@glimmer/opcode-compiler`, `@glimmer/runtime` + * [#1215](https://github.com/glimmerjs/glimmer-vm/pull/1215) [REFACTOR] Use constants pool for definitions ([@pzuraq](https://github.com/pzuraq)) +* `@glimmer/benchmark-env`, `@glimmer/integration-tests`, `@glimmer/interfaces`, `@glimmer/manager`, `@glimmer/program`, `@glimmer/runtime`, `@glimmer/util` + * [#1213](https://github.com/glimmerjs/glimmer-vm/pull/1213) [REFACTOR] Upstream custom managers, TO managers ([@pzuraq](https://github.com/pzuraq)) + +#### :bug: Bug Fix +* `@glimmer/compiler`, `@glimmer/integration-tests` + * [#1218](https://github.com/glimmerjs/glimmer-vm/pull/1218) Fix splattributes handling of type attribute. [rebased] ([@locks](https://github.com/locks)) + +#### :house: Internal +* `@glimmer/benchmark-env` + * [#1220](https://github.com/glimmerjs/glimmer-vm/pull/1220) [BUGFIX] Absorb breakage in benchmark-env instead of benchmark ([@pzuraq](https://github.com/pzuraq)) + * [#1217](https://github.com/glimmerjs/glimmer-vm/pull/1217) Revert "[BREAKING] Update benchmark-env API" ([@pzuraq](https://github.com/pzuraq)) + * [#1216](https://github.com/glimmerjs/glimmer-vm/pull/1216) [BREAKING] Update benchmark-env API ([@pzuraq](https://github.com/pzuraq)) +* `@glimmer/integration-tests` + * [#1214](https://github.com/glimmerjs/glimmer-vm/pull/1214) [REFACTOR] Update tests to match actual Glimmer component API ([@pzuraq](https://github.com/pzuraq)) + +#### Committers: 2 +- Chris Garrett ([@pzuraq](https://github.com/pzuraq)) +- Ricardo Mendes ([@locks](https://github.com/locks)) + +## v0.67.0 (2020-11-24) + +#### :boom: Breaking Change +* `@glimmer/compiler`, `@glimmer/integration-tests`, `@glimmer/interfaces`, `@glimmer/syntax` + * [#1206](https://github.com/glimmerjs/glimmer-vm/pull/1206) [BUGFIX] Ensures keywords and elements can always be shadowed ([@pzuraq](https://github.com/pzuraq)) +* `@glimmer/benchmark-env`, `@glimmer/compiler`, `@glimmer/debug`, `@glimmer/encoder`, `@glimmer/integration-tests`, `@glimmer/interfaces`, `@glimmer/opcode-compiler`, `@glimmer/program`, `@glimmer/runtime`, `@glimmer/syntax`, `@glimmer/util` + * [#1171](https://github.com/glimmerjs/glimmer-vm/pull/1171) Refactor resolver for strict ([@pzuraq](https://github.com/pzuraq)) + +#### :bug: Bug Fix +* `@glimmer/integration-tests`, `@glimmer/runtime` + * [#1209](https://github.com/glimmerjs/glimmer-vm/pull/1209) Ensure `` works properly ([@KrishnaRPatel](https://github.com/KrishnaRPatel)) +* `@glimmer/validator` + * [#1205](https://github.com/glimmerjs/glimmer-vm/pull/1205) Ensure `@tracked` assertion can be made a deprecation. ([@rwjblue](https://github.com/rwjblue)) +* `@glimmer/syntax` + * [#1204](https://github.com/glimmerjs/glimmer-vm/pull/1204) Ensure `loc` is populated by `builders.element(...)` ([@rwjblue](https://github.com/rwjblue)) + +#### Committers: 3 +- Chris Garrett ([@pzuraq](https://github.com/pzuraq)) +- Krishna Patel ([@KrishnaRPatel](https://github.com/KrishnaRPatel)) +- Robert Jackson ([@rwjblue](https://github.com/rwjblue)) + +## v0.66.1 (2020-11-20) + +#### :bug: Bug Fix +* `@glimmer/integration-tests`, `@glimmer/runtime` + * [#1209](https://github.com/glimmerjs/glimmer-vm/pull/1209) Ensure `` + works properly ([@KrishnaRPatel](https://github.com/KrishnaRPatel)) + +* `@glimmer/validator` + * [#1205](https://github.com/glimmerjs/glimmer-vm/pull/1205) Ensure `@tracked` assertion can be +made a deprecation. ([@rwjblue](https://github.com/rwjblue)) + +* `@glimmer/syntax` + * [#1204](https://github.com/glimmerjs/glimmer-vm/pull/1204) Ensure `loc` is populated by `build +ers.element(...)` ([@rwjblue](https://github.com/rwjblue)) + +#### Committers: 3 +- Chris Garrett ([@pzuraq](https://github.com/pzuraq)) +- Krishna Patel ([@KrishnaRPatel](https://github.com/KrishnaRPatel)) +- Robert Jackson ([@rwjblue](https://github.com/rwjblue)) + + + +## v0.66.0 (2020-11-17) + +#### :boom: Breaking Change +* `@glimmer/compiler`, `@glimmer/debug`, `@glimmer/integration-tests`, `@glimmer/interfaces`, `@glimmer/local-debug-flags`, `@glimmer/node`, `@glimmer/opcode-compiler`, `@glimmer/program`, `@glimmer/reference`, `@glimmer/runtime`, `@glimmer/syntax`, `@glimmer/util`, `@glimmer/validator`, `@glimmer/wire-format` + * [#1170](https://github.com/glimmerjs/glimmer-vm/pull/1170) Refactor `@glimmer/syntax` and `@glimmer/compiler` to enable future strict mode functionality. ([@pzuraq](https://github.com/pzuraq)) + +#### Committers: 1 +- Chris Garrett ([@pzuraq](https://github.com/pzuraq)) + + +## v0.65.0 (2020-11-13) + +#### :boom: Breaking Change +* `@glimmer/benchmark-env`, `@glimmer/integration-tests`, `@glimmer/interfaces`, `@glimmer/node`, `@glimmer/opcode-compiler`, `@glimmer/runtime` + * [#1197](https://github.com/glimmerjs/glimmer-vm/pull/1197) [REFACTOR] Upstreams basic manager infrastructure and types ([@pzuraq](https://github.com/pzuraq)) + +#### Committers: 1 +- Chris Garrett ([@pzuraq](https://github.com/pzuraq)) + +## v0.64.0 (2020-11-12) + +#### :boom: Breaking Change +* `@glimmer/integration-tests`, `@glimmer/interfaces`, `@glimmer/opcode-compiler`, `@glimmer/runtime`, `@glimmer/validator` + * [#1192](https://github.com/glimmerjs/glimmer-vm/pull/1192) [REFACTOR] Integrate DebugRenderTree ([@pzuraq](https://github.com/pzuraq)) + +#### :bug: Bug Fix +* `@glimmer/benchmark-env`, `@glimmer/integration-tests`, `@glimmer/interfaces`, `@glimmer/runtime` + * [#1189](https://github.com/glimmerjs/glimmer-vm/pull/1189) [UPSTREAM] DebugRenderTree ([@pzuraq](https://github.com/pzuraq)) + +#### Committers: 1 +- Chris Garrett ([@pzuraq](https://github.com/pzuraq)) + +## v0.63.5 (2020-11-10) + +#### :bug: Bug Fix +* `@glimmer/util` + * [#1193](https://github.com/glimmerjs/glimmer-vm/pull/1193) [BUGFIX] Use custom symbol whenever native is not present ([@pzuraq](https://github.com/pzuraq)) + +#### Committers: 1 +- Chris Garrett ([@pzuraq](https://github.com/pzuraq)) + + +## v0.63.4 (2020-11-10) + +#### :bug: Bug Fix +* `@glimmer/runtime` + * [#1191](https://github.com/glimmerjs/glimmer-vm/pull/1191) [BUGFIX] Exports Owner for IE11 ([@pzuraq](https://github.com/pzuraq)) + +#### Committers: 1 +- Chris Garrett ([@pzuraq](https://github.com/pzuraq)) + +## v0.63.3 (2020-11-10) + +#### :bug: Bug Fix +* `@glimmer/runtime` + * [#1190](https://github.com/glimmerjs/glimmer-vm/pull/1190) [BUGFIX] Exports Owner for IE11 ([@pzuraq](https://github.com/pzuraq)) + +#### Committers: 1 +- Chris Garrett ([@pzuraq](https://github.com/pzuraq)) + +## v0.63.2 (2020-11-10) + +#### :bug: Bug Fix +* `@glimmer/runtime` + * [#1188](https://github.com/glimmerjs/glimmer-vm/pull/1188) [BUGFIX] Upstream ember.js#19253 ([@pzuraq](https://github.com/pzuraq)) + +#### Committers: 1 +- Chris Garrett ([@pzuraq](https://github.com/pzuraq)) + +## v0.63.1 (2020-11-10) + +#### :bug: Bug Fix +* `@glimmer/runtime` + * [#1187](https://github.com/glimmerjs/glimmer-vm/pull/1187) [BUGFIX] Don't strip out setComponentTemplate assertions ([@pzuraq](https://github.com/pzuraq)) + +#### Committers: 1 +- Chris Garrett ([@pzuraq](https://github.com/pzuraq)) + +## v0.63.0 (2020-11-09) + +#### :boom: Breaking Change +* `@glimmer/benchmark-env`, `@glimmer/compiler`, `@glimmer/debug`, `@glimmer/integration-tests`, `@glimmer/interfaces`, `@glimmer/opcode-compiler`, `@glimmer/program`, `@glimmer/runtime`, `@glimmer/syntax`, `@glimmer/util`, `@glimmer/vm` + * [#1185](https://github.com/glimmerjs/glimmer-vm/pull/1185) [REFACTOR] Upstreams Owner, simplifies template meta/ownership ([@pzuraq](https://github.com/pzuraq)) +* `@glimmer/benchmark-env`, `@glimmer/integration-tests`, `@glimmer/interfaces`, `@glimmer/runtime` + * [#1184](https://github.com/glimmerjs/glimmer-vm/pull/1184) [REFACTOR] Upstream `setComponentTemplate` ([@pzuraq](https://github.com/pzuraq)) + +#### :bug: Bug Fix +* `@glimmer/integration-tests`, `@glimmer/opcode-compiler`, `@glimmer/runtime` + * [#1186](https://github.com/glimmerjs/glimmer-vm/pull/1186) [BUGFIX] Prevent args from being created/evaluated twice ([@pzuraq](https://github.com/pzuraq)) + +#### Committers: 1 +- Chris Garrett ([@pzuraq](https://github.com/pzuraq)) + +## v0.62.4 (2020-10-26) + +#### :rocket: Enhancement +* `@glimmer/integration-tests`, `@glimmer/runtime` + * [#1179](https://github.com/glimmerjs/glimmer-vm/pull/1179) Adding support for partial rehydration ([@chiragpat](https://github.com/chiragpat)) + +#### :bug: Bug Fix +* `@glimmer/integration-tests`, `@glimmer/opcode-compiler`, `@glimmer/runtime` + * [#1181](https://github.com/glimmerjs/glimmer-vm/pull/1181) [REFACTOR] Combines/refactors Basic and Fragment components ([@pzuraq](https://github.com/pzuraq)) + +#### :house: Internal +* [#1175](https://github.com/glimmerjs/glimmer-vm/pull/1175) Add `yarn lint` script and stop aliasing `yarn eslint`. ([@rwjblue](https://github.com/rwjblue)) + +#### Committers: 3 +- Chirag Patel ([@chiragpat](https://github.com/chiragpat)) +- Chris Garrett ([@pzuraq](https://github.com/pzuraq)) +- Robert Jackson ([@rwjblue](https://github.com/rwjblue)) + + +## v0.62.3 (2020-10-14) + +#### :bug: Bug Fix +* `@glimmer/integration-tests`, `@glimmer/syntax` + * [#1174](https://github.com/glimmerjs/glimmer-vm/pull/1174) Update simple-html-tokenizer and use its codemod mode. ([@rwjblue](https://github.com/rwjblue)) + +#### Committers: 1 +- Robert Jackson ([@rwjblue](https://github.com/rwjblue)) + + +## v0.62.2 (2020-10-14) + +#### :rocket: Enhancement +* `@glimmer/integration-tests`, `@glimmer/runtime`, `@glimmer/validator` + * [#1169](https://github.com/glimmerjs/glimmer-vm/pull/1169) [FEAT] Adds better logging for render errors ([@pzuraq](https://github.com/pzuraq)) + +#### :bug: Bug Fix +* `@glimmer/runtime` + * [#1172](https://github.com/glimmerjs/glimmer-vm/pull/1172) Ensure "pause on uncaught" exceptions pauses in correct location. ([@rwjblue](https://github.com/rwjblue)) + +#### Committers: 2 +- Chris Garrett ([@pzuraq](https://github.com/pzuraq)) +- Robert Jackson ([@rwjblue](https://github.com/rwjblue)) + + +## v0.62.1 (2020-09-24) + +#### :bug: Bug Fix +* `@glimmer/benchmark-env`, `@glimmer/integration-tests`, `@glimmer/runtime`, `@glimmer/util` + * [#1162](https://github.com/glimmerjs/glimmer-vm/pull/1162) Simplify `SimpleDOM` casting (allow for proper production mode stripping) ([@pzuraq](https://github.com/pzuraq)) +* `@glimmer/benchmark-env`, `@glimmer/compiler`, `@glimmer/debug`, `@glimmer/dom-change-list`, `@glimmer/encoder`, `@glimmer/integration-tests`, `@glimmer/node`, `@glimmer/opcode-compiler`, `@glimmer/program`, `@glimmer/reference`, `@glimmer/runtime`, `@glimmer/syntax`, `@glimmer/util`, `@glimmer/vm`, `@glimmer/wire-format` + * [#1161](https://github.com/glimmerjs/glimmer-vm/pull/1161) [BUGFIX] Pin all package versions ([@pzuraq](https://github.com/pzuraq)) + +#### :house: Internal +* `@glimmer/syntax` + * [#1164](https://github.com/glimmerjs/glimmer-vm/pull/1164) Add test confirming parsing + printing `{{#in-element` is safe. ([@rwjblue](https://github.com/rwjblue)) + +#### Committers: 3 +- Chris Garrett ([@pzuraq](https://github.com/pzuraq)) +- Robert Jackson ([@rwjblue](https://github.com/rwjblue)) +- Volodymyr Radchenko ([@rreckonerr](https://github.com/rreckonerr)) + +## v0.62.0 (2020-09-18) + +#### :boom: Breaking Change +* `@glimmer/syntax` + * [#1160](https://github.com/glimmerjs/glimmer-vm/pull/1160) [REFACTOR] Converts to using @handlebars/parser ([@pzuraq](https://github.com/pzuraq)) +* `@glimmer/benchmark-env`, `@glimmer/compiler`, `@glimmer/integration-tests`, `@glimmer/interfaces`, `@glimmer/low-level`, `@glimmer/node`, `@glimmer/runtime`, `@glimmer/syntax`, `@glimmer/util`, `@glimmer/validator` + * [#1154](https://github.com/glimmerjs/glimmer-vm/pull/1154) Upgrade to TypeScript 4.0 ([@wycats](https://github.com/wycats)) + +#### :bug: Bug Fix +* `@glimmer/runtime` + * [#1155](https://github.com/glimmerjs/glimmer-vm/pull/1155) Ensure `protocolForUrl` works in `fastboot@3.1.0` environment ([@rwjblue](https://github.com/rwjblue)) + +#### :house: Internal +* [#1156](https://github.com/glimmerjs/glimmer-vm/pull/1156) Update PerformanceCheck CI run to fetch full git history. ([@rwjblue](https://github.com/rwjblue)) + +#### Committers: 3 +- Chris Garrett ([@pzuraq](https://github.com/pzuraq)) +- Robert Jackson ([@rwjblue](https://github.com/rwjblue)) +- Yehuda Katz ([@wycats](https://github.com/wycats)) + + +## v0.61.2 (2020-09-02) + +#### :bug: Bug Fix +* `@glimmer/runtime` + * [#1155](https://github.com/glimmerjs/glimmer-vm/pull/1155) Ensure `protocolForUrl` works in `fastboot@3.1.0` environment ([@rwjblue](https://github.com/rwjblue)) + +#### Committers: 1 +- Robert Jackson ([@rwjblue](https://github.com/rwjblue)) + + +## v0.61.1 (2020-09-02) + +#### :bug: Bug Fix +* `@glimmer/integration-tests`, `@glimmer/interfaces`, `@glimmer/opcode-compiler`, `@glimmer/runtime` + * [#1152](https://github.com/glimmerjs/glimmer-vm/pull/1152) [BUGFIX] Prevent accidental dynamic component lookup ([@pzuraq](https://github.com/pzuraq)) + +#### Committers: 1 +- Chris Garrett ([@pzuraq](https://github.com/pzuraq)) + + +## v0.61.0 (2020-09-02) + +#### :boom: Breaking Change +* `@glimmer/benchmark-env`, `@glimmer/bundle-compiler`, `@glimmer/debug`, `@glimmer/integration-tests`, `@glimmer/interfaces`, `@glimmer/opcode-compiler`, `@glimmer/program`, `@glimmer/runtime`, `@glimmer/vm` + * [#1148](https://github.com/glimmerjs/glimmer-vm/pull/1148) [REFACTOR] Removes AoT mode ([@pzuraq](https://github.com/pzuraq)) + +#### :house: Internal +* Other + * [#1151](https://github.com/glimmerjs/glimmer-vm/pull/1151) Ensure version numbers are bumped for benchmark and local-linker. ([@rwjblue](https://github.com/rwjblue)) + * [#1147](https://github.com/glimmerjs/glimmer-vm/pull/1147) GH Actions Workflow cleanup ([@krisselden](https://github.com/krisselden)) +* `@glimmer/benchmark-env`, `@glimmer/bundle-compiler`, `@glimmer/compiler`, `@glimmer/debug`, `@glimmer/dom-change-list`, `@glimmer/integration-tests`, `@glimmer/low-level`, `@glimmer/opcode-compiler`, `@glimmer/program`, `@glimmer/reference`, `@glimmer/runtime`, `@glimmer/syntax`, `@glimmer/util`, `@glimmer/validator`, `@glimmer/wire-format` + * [#1146](https://github.com/glimmerjs/glimmer-vm/pull/1146) Update Prettier to 2.1 ([@rwjblue](https://github.com/rwjblue)) + +#### Committers: 3 +- Chris Garrett ([@pzuraq](https://github.com/pzuraq)) +- Kris Selden ([@krisselden](https://github.com/krisselden)) +- Robert Jackson ([@rwjblue](https://github.com/rwjblue)) + + +## v0.60.0 (2020-08-27) + +#### :boom: Breaking Change +* `@glimmer/benchmark-env`, `@glimmer/debug`, `@glimmer/integration-tests`, `@glimmer/interfaces`, `@glimmer/opcode-compiler`, `@glimmer/reference`, `@glimmer/runtime`, `@glimmer/util`, `@glimmer/validator`, `@glimmer/vm` + * [#1142](https://github.com/glimmerjs/glimmer-vm/pull/1142) [REFACTOR] Monomorphic Reference ([@pzuraq](https://github.com/pzuraq)) + +#### Committers: 2 +- Chris Garrett ([@pzuraq](https://github.com/pzuraq)) +- Kris Selden ([@krisselden](https://github.com/krisselden)) + +## v0.59.0 (2020-08-22) + +#### :boom: Breaking Change +* `@glimmer/benchmark-env`, `@glimmer/global-context`, `@glimmer/integration-tests`, `@glimmer/interfaces`, `@glimmer/reference`, `@glimmer/runtime`, `@glimmer/validator` + * [#1138](https://github.com/glimmerjs/glimmer-vm/pull/1138) [REFACTOR] Extract environment variables into global context ([@pzuraq](https://github.com/pzuraq)) +* `@glimmer/benchmark-env`, `@glimmer/interfaces`, `@glimmer/opcode-compiler`, `@glimmer/reference`, `@glimmer/runtime`, `@glimmer/validator` + * [#1139](https://github.com/glimmerjs/glimmer-vm/pull/1139) Add Benchmark Interface ([@krisselden](https://github.com/krisselden)) + +#### Committers: 2 +- Chris Garrett ([@pzuraq](https://github.com/pzuraq)) +- Kris Selden ([@krisselden](https://github.com/krisselden)) + + +## v0.58.0 (2020-08-19) + +#### :boom: Breaking Change +* `@glimmer/debug`, `@glimmer/integration-tests`, `@glimmer/interfaces`, `@glimmer/reference`, `@glimmer/runtime` + * [#1135](https://github.com/glimmerjs/glimmer-vm/pull/1135) [REFACTOR] Simplify CapturedArguments ([@pzuraq](https://github.com/pzuraq)) +* `@glimmer/integration-tests`, `@glimmer/interfaces`, `@glimmer/runtime` + * [#1136](https://github.com/glimmerjs/glimmer-vm/pull/1136) [CLEANUP] Consolidate Scope classes ([@pzuraq](https://github.com/pzuraq)) + +#### Committers: 1 +- Chris Garrett ([@pzuraq](https://github.com/pzuraq)) + + +## v0.57.2 (2020-08-19) + +#### :bug: Bug Fix +* `@glimmer/validator` + * [#1134](https://github.com/glimmerjs/glimmer-vm/pull/1134) [BUGFIX] Fix string repeat ([@pzuraq](https://github.com/pzuraq)) + +#### Committers: 1 +- Chris Garrett ([@pzuraq](https://github.com/pzuraq)) + + +## v0.57.1 (2020-08-19) + +#### :bug: Bug Fix +* `@glimmer/validator` + * [#1133](https://github.com/glimmerjs/glimmer-vm/pull/1133) [BUGFIX] Avoid String.prototype.repeat ([@pzuraq](https://github.com/pzuraq)) + +#### Committers: 1 +- Chris Garrett ([@pzuraq](https://github.com/pzuraq)) + + +## v0.57.0 (2020-08-18) + +#### :boom: Breaking Change +* `@glimmer/integration-tests`, `@glimmer/interfaces`, `@glimmer/opcode-compiler`, `@glimmer/reference`, `@glimmer/runtime`, `@glimmer/validator`, `@glimmer/vm` + * [#1115](https://github.com/glimmerjs/glimmer-vm/pull/1115) [REFACTOR] Converts VM to use tracking internally ([@pzuraq](https://github.com/pzuraq)) + +#### Committers: 1 +- Chris Garrett ([@pzuraq](https://github.com/pzuraq)) + + +## v0.56.1 (2020-08-11) + +#### :house: Internal +* `@glimmer/bundle-compiler`, `@glimmer/debug`, `@glimmer/integration-tests`, `@glimmer/interfaces`, `@glimmer/opcode-compiler`, `@glimmer/program`, `@glimmer/runtime`, `@glimmer/util` + * [#1131](https://github.com/glimmerjs/glimmer-vm/pull/1131) [REFACTOR] Simplifies immediate and handle encoding ([@pzuraq](https://github.com/pzuraq)) + +#### Committers: 1 +- Chris Garrett ([@pzuraq](https://github.com/pzuraq)) + +## v0.56.0 (2020-08-05) + +#### :boom: Breaking Change +* `@glimmer/integration-tests`, `@glimmer/interfaces`, `@glimmer/reference`, `@glimmer/runtime`, `@glimmer/validator` + * [#1126](https://github.com/glimmerjs/glimmer-vm/pull/1126) [REFACTOR] Expose tagMeta and simplify property lookups ([@pzuraq](https://github.com/pzuraq)) + +#### :house: Internal +* Other + * [#1129](https://github.com/glimmerjs/glimmer-vm/pull/1129) set more timeouts for browserstack ([@krisselden](https://github.com/krisselden)) +* `@glimmer/integration-tests` + * [#1130](https://github.com/glimmerjs/glimmer-vm/pull/1130) [BUGFIX] Reduce test iteration count to prevent timeouts ([@pzuraq](https://github.com/pzuraq)) + * [#1127](https://github.com/glimmerjs/glimmer-vm/pull/1127) fix test memory leaks ([@krisselden](https://github.com/krisselden)) + +#### Committers: 2 +- Chris Garrett ([@pzuraq](https://github.com/pzuraq)) +- Kris Selden ([@krisselden](https://github.com/krisselden)) + + +## v0.55.3 (2020-08-02) + +#### :house: Internal +* `@glimmer/validator` + * [#1124](https://github.com/glimmerjs/glimmer-vm/pull/1124) [REFACTOR] Simplify and warm tag computation ([@pzuraq](https://github.com/pzuraq)) + * [#1108](https://github.com/glimmerjs/glimmer-vm/pull/1108) Remove $REVISION optimization ([@pzuraq](https://github.com/pzuraq)) + +#### Committers: 1 +- Chris Garrett ([@pzuraq](https://github.com/pzuraq)) + + +## v0.55.2 (2020-07-30) + +#### :rocket: Enhancement +* `@glimmer/bundle-compiler`, `@glimmer/integration-tests`, `@glimmer/interfaces`, `@glimmer/program`, `@glimmer/runtime` + * [#1122](https://github.com/glimmerjs/glimmer-vm/pull/1122) [Refactor] Use a map to dedupe constants instead of indexOf ([@pzuraq](https://github.com/pzuraq)) +* `@glimmer/runtime` + * [#1121](https://github.com/glimmerjs/glimmer-vm/pull/1121) Expose the destroyables on the error thrown by `assertDestroyablesDestroyed` ([@rwjblue](https://github.com/rwjblue)) + +#### :house: Internal +* `@glimmer/validator` + * [#1120](https://github.com/glimmerjs/glimmer-vm/pull/1120) Fix `MonomorphicTag` type error for downstream consumers ([@dfreeman](https://github.com/dfreeman)) + +#### Committers: 3 +- Chris Garrett ([@pzuraq](https://github.com/pzuraq)) +- Dan Freeman ([@dfreeman](https://github.com/dfreeman)) +- Robert Jackson ([@rwjblue](https://github.com/rwjblue)) + + +## v0.55.1 (2020-07-26) + +#### :bug: Bug Fix +* `@glimmer/runtime` + * [#1119](https://github.com/glimmerjs/glimmer-vm/pull/1119) Ensure `isDestroying`/`isDestroyed` without children or destructors does not fail `assertDestroyablesDestroyed` ([@rwjblue](https://github.com/rwjblue)) + +#### Committers: 1 +- Robert Jackson ([@rwjblue](https://github.com/rwjblue)) + + +## v0.55.0 (2020-07-17) + +#### :boom: Breaking Change +* `@glimmer/integration-tests`, `@glimmer/interfaces`, `@glimmer/reference`, `@glimmer/runtime`, `@glimmer/util` + * [#1114](https://github.com/glimmerjs/glimmer-vm/pull/1114) [REFACTOR] Remove LinkedList and simplify iteration ([@pzuraq](https://github.com/pzuraq)) + +#### Committers: 1 +- Chris Garrett ([@pzuraq](https://github.com/pzuraq)) + + +## v0.54.1 (2020-07-02) + +#### :bug: Bug Fix +* `@glimmer/runtime` + * [#1113](https://github.com/glimmerjs/glimmer-vm/pull/1113) Fix a memory leak with `{{each}}` ([@pzuraq](https://github.com/pzuraq)) + +#### Committers: 1 +- Chris Garrett ([@pzuraq](https://github.com/pzuraq)) + + +## v0.54.0 (2020-06-17) + +#### :boom: Breaking Change / :rocket: Enhancement +* `@glimmer/integration-tests`, `@glimmer/interfaces`, `@glimmer/runtime`, `@glimmer/util` + * [#1110](https://github.com/glimmerjs/glimmer-vm/pull/1110) Implement Destroyables RFC ([@pzuraq](https://github.com/pzuraq)) + +#### :bug: Bug Fix +* `@glimmer/validator` + * [#1103](https://github.com/glimmerjs/glimmer-vm/pull/1103) [BUGFIX] Adds an assertion to prevent duplicate validator packages ([@pzuraq](https://github.com/pzuraq)) + +#### Committers: 1 +- Chris Garrett ([@pzuraq](https://github.com/pzuraq)) + + +## v0.53.0 (2020-05-18) + +#### :boom: Breaking Change +* `@glimmer/integration-tests`, `@glimmer/reference`, `@glimmer/runtime`, `@glimmer/validator` + * [#1090](https://github.com/glimmerjs/glimmer-vm/pull/1090) Implement `@glimmer/tracking/primatives/cache` (see [emberjs/rfcs#615](https://github.com/emberjs/rfcs/blob/master/text/0615-autotracking-memoization.md) for details) ([@pzuraq](https://github.com/pzuraq)) +* `@glimmer/validator` + * [#1088](https://github.com/glimmerjs/glimmer-vm/pull/1088) Rename `memoizeTracked` to `memo` ([@pzuraq](https://github.com/pzuraq)) + * [#1089](https://github.com/glimmerjs/glimmer-vm/pull/1089) Remove unused EPOCH tag ([@pzuraq](https://github.com/pzuraq)) + +#### :rocket: Enhancement +* `@glimmer/integration-tests`, `@glimmer/reference`, `@glimmer/runtime`, `@glimmer/validator` + * [#1090](https://github.com/glimmerjs/glimmer-vm/pull/1090) Implement `@glimmer/tracking/primatives/cache` (see [emberjs/rfcs#615](https://github.com/emberjs/rfcs/blob/master/text/0615-autotracking-memoization.md) for details) ([@pzuraq](https://github.com/pzuraq)) + +#### :bug: Bug Fix +* `@glimmer/compiler` + * [#1102](https://github.com/glimmerjs/glimmer-vm/pull/1102) Add a compile time error when passing arguments to regular HTML elements (e.g. ` `EnvironmentDelegate` + * `iterable` -> `toIterator`, now returns an `IteratorDelegate` + * Changed `JitRuntime` creation methods to receive EnvironmentOptions instead + a `document` object + * Added `willDestroy` component capability. Should generally be avoided, it's + just for classic interop. + * `@glimmer/reference` + * Removed `MapReference` + * Removed `UpdatableReference`, replaced it with `UpdatableRootReference` and + `IterationItemReference` + * Most references now require the `env` + * Refactor property and root references generally, not a complete rewrite, but + large enough that embedders should really pay attention to that code and + will have to rewrite some things. + * Major changes + * `@glimmer/validator` + * Simplified `meta` implementation in general. `tagFor` and `dirtyTagFor` have + changed decently. + * Added assertions to tags to prevent incorrect usage + +#### Committers: 2 +- Chris Garrett ([@pzuraq](https://github.com/pzuraq)) +- Robert Jackson ([@rwjblue](https://github.com/rwjblue)) + + +## v0.44.0 (2019-11-08) + +#### :boom: Breaking Change +* `@glimmer/integration-tests`, `@glimmer/interfaces`, `@glimmer/object-reference`, `@glimmer/object`, `@glimmer/reference`, `@glimmer/runtime`, `@glimmer/validator` + * [#987](https://github.com/glimmerjs/glimmer-vm/pull/987) Extract validation system and tags into `@glimmer/validator` package ([@pzuraq](https://github.com/pzuraq)) + +#### :house: Internal +* Other + * [#989](https://github.com/glimmerjs/glimmer-vm/pull/989) Allow test runner to rerender between modules. ([@rwjblue](https://github.com/rwjblue)) +* `@glimmer/syntax` + * [#986](https://github.com/glimmerjs/glimmer-vm/pull/986) Update to handlebars@4.5.1. ([@rwjblue](https://github.com/rwjblue)) + +#### Committers: 2 +- Chris Garrett ([@pzuraq](https://github.com/pzuraq)) +- Robert Jackson ([@rwjblue](https://github.com/rwjblue)) + +## v0.43.0 (2019-10-27) + +#### :boom: Breaking Change +* `@glimmer/syntax` + * [#983](https://github.com/glimmerjs/glimmer-vm/pull/983) Ensure codemod mode ignores whitespace control. ([@rwjblue](https://github.com/rwjblue)) + +#### :rocket: Enhancement +* [#972](https://github.com/glimmerjs/glimmer-vm/pull/972) Lay groundwork for lexical scope & improve errors ([@wycats](https://github.com/wycats) / [@tomdale](https://github.com/tomdale)) + +#### :house: Internal +* Other + * [#981](https://github.com/glimmerjs/glimmer-vm/pull/981) Update ember-cli-browserstack so that BrowserStack tests will continue to work ([@kategengler](https://github.com/kategengler)) +* `@glimmer/runtime` + * [#980](https://github.com/glimmerjs/glimmer-vm/pull/980) Avoid duplicate `indexOf` in `BlockArguments` ([@bekzod](https://github.com/bekzod)) + +#### Committers: 3 +- Katie Gengler ([@kategengler](https://github.com/kategengler)) +- Robert Jackson ([@rwjblue](https://github.com/rwjblue)) +- bek ([@bekzod](https://github.com/bekzod)) + + +## v0.42.2 (2019-10-11) + +#### :bug: Bug Fix +* `@glimmer/syntax` + * [#979](https://github.com/glimmerjs/glimmer-vm/pull/979) Fix AST loc info for `ConcatStatement`s containing `TextNode`s ([@rwjblue](https://github.com/rwjblue)) + +#### :house: Internal +* `@glimmer/compiler`, `@glimmer/integration-tests`, `@glimmer/opcode-compiler`, `@glimmer/runtime`, `@glimmer/syntax` + * [#976](https://github.com/glimmerjs/glimmer-vm/pull/976) Replace TSLint with ESLint ([@Turbo87](https://github.com/Turbo87)) +* `@glimmer/bundle-compiler`, `@glimmer/compiler`, `@glimmer/dom-change-list`, `@glimmer/integration-tests`, `@glimmer/interfaces`, `@glimmer/opcode-compiler`, `@glimmer/runtime`, `@glimmer/syntax` + * [#975](https://github.com/glimmerjs/glimmer-vm/pull/975) Update `prettier` to v1.18.2 ([@Turbo87](https://github.com/Turbo87)) +* Other + * [#977](https://github.com/glimmerjs/glimmer-vm/pull/977) CI: Use Node 8 ([@Turbo87](https://github.com/Turbo87)) + +#### Committers: 2 +- Robert Jackson ([@rwjblue](https://github.com/rwjblue)) +- Tobias Bieniek ([@Turbo87](https://github.com/Turbo87)) + +## v0.42.1 (2019-09-26) + +#### :bug: Bug Fix +* `@glimmer/util` + * [#969](https://github.com/glimmerjs/glimmer-vm/pull/969) util/string: Fix broken array length conditions ([@Turbo87](https://github.com/Turbo87)) +* `@glimmer/runtime` + * [#971](https://github.com/glimmerjs/glimmer-vm/pull/971) Handle missing remote element marker gracefully. ([@melmerp](https://github.com/melmerp)) + +#### :house: Internal +* [#968](https://github.com/glimmerjs/glimmer-vm/pull/968) Run ESLint on *all* JS files in the project ([@Turbo87](https://github.com/Turbo87)) +* [#973](https://github.com/glimmerjs/glimmer-vm/pull/973) Upgrade amd-name-resolver dependency to 1.3.1 ([@tomdale](https://github.com/tomdale)) +* [#970](https://github.com/glimmerjs/glimmer-vm/pull/970) build/debug: Use `prettier` API directly instead of going through TSLint ([@Turbo87](https://github.com/Turbo87)) +* [#967](https://github.com/glimmerjs/glimmer-vm/pull/967) Cleanup Node.js files ([@Turbo87](https://github.com/Turbo87)) + +#### Committers: 2 +- Tobias Bieniek ([@Turbo87](https://github.com/Turbo87)) +- Tom Dale ([@tomdale](https://github.com/tomdale)) + +## v0.42.0 (2019-08-13) + +#### :boom: Breaking Change +* `@glimmer/integration-tests`, `@glimmer/reference`, `@glimmer/runtime` + * [#964](https://github.com/glimmerjs/glimmer-vm/pull/964) [FEAT] Perf Tuning + Functional API ([@pzuraq](https://github.com/pzuraq)) + +#### :bug: Bug Fix +* `@glimmer/integration-tests`, `@glimmer/node`, `@glimmer/runtime` + * [#961](https://github.com/glimmerjs/glimmer-vm/pull/961) Fix ``, `<script>`, and `<style>` rehydration ([@CvX](https://github.com/CvX)) +* `@glimmer/integration-tests`, `@glimmer/syntax` + * [#960](https://github.com/glimmerjs/glimmer-vm/pull/960) Update simple-html-tokenizer to v0.5.8 ([@josemarluedke](https://github.com/josemarluedke)) + +#### Committers: 4 +- Chris Garrett ([@pzuraq](https://github.com/pzuraq)) +- Jarek Radosz ([@CvX](https://github.com/CvX)) +- Josemar Luedke ([@josemarluedke](https://github.com/josemarluedke)) +- bek ([@bekzod](https://github.com/bekzod)) + +## v0.41.4 (2019-07-11) + +#### :rocket: Enhancement +* `@glimmer/syntax` + * [#957](https://github.com/glimmerjs/glimmer-vm/pull/957) Add ability to override printing of specific AST nodes. ([@rwjblue](https://github.com/rwjblue)) + +#### :bug: Bug Fix +* `@glimmer/integration-tests`, `@glimmer/node` + * [#956](https://github.com/glimmerjs/glimmer-vm/pull/956) Fix table thead and tfoot rehydration ([@josemarluedke](https://github.com/josemarluedke)) + +#### Committers: 2 +- Josemar Luedke ([@josemarluedke](https://github.com/josemarluedke)) +- Robert Jackson ([@rwjblue](https://github.com/rwjblue)) + + +## v0.41.2 (2019-07-04) + +#### :rocket: Enhancement +* `@glimmer/syntax` + * [#951](https://github.com/glimmerjs/glimmer-vm/pull/951) Preserve mustache whitespace stripping information in AST and printer ([@CvX](https://github.com/CvX)) + +#### Committers: 1 +- Jarek Radosz ([@CvX](https://github.com/CvX)) + + +## v0.41.1 (2019-06-25) + +#### :rocket: Enhancement +* `@glimmer/reference` + * [#945](https://github.com/glimmerjs/glimmer-vm/pull/945) Performance improvements for keyed lists changes ([@lifeart](https://github.com/lifeart)) + +#### :bug: Bug Fix +* `@glimmer/syntax` + * [#949](https://github.com/glimmerjs/glimmer-vm/pull/949) Print unescaped statements correctly ([@paddyobrien](https://github.com/paddyobrien)) + +#### Committers: 2 +- Alex Kanunnikov ([@lifeart](https://github.com/lifeart)) +- Paddy O'Brien ([@paddyobrien](https://github.com/paddyobrien)) + + +## v0.41.0 (2019-05-13) + +#### :boom: Breaking Change +* `@glimmer/syntax` + * [#942](https://github.com/glimmerjs/glimmer-vm/pull/942) Add support for `chained` inverse blocks ([@Turbo87](https://github.com/Turbo87)) + +#### :house: Internal +* [#927](https://github.com/glimmerjs/glimmer-vm/pull/927) Update yarn-link-all script to print out commands to run in project ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) + +#### Committers: 2 +- L. Preston Sego III ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) +- Tobias Bieniek ([@Turbo87](https://github.com/Turbo87)) + + +## v0.40.2 (2019-05-13) + +#### :bug: Bug Fix +* `@glimmer/syntax` + * [#941](https://github.com/glimmerjs/glimmer-vm/pull/941) Fix printer support for self-closing angle bracket component invocations ([@Turbo87](https://github.com/Turbo87)) + * [#932](https://github.com/glimmerjs/glimmer-vm/pull/932) Fix printing of MustacheStatement with literal path ([@ef4](https://github.com/ef4)) + +#### :house: Internal +* `@glimmer/runtime` + * [#943](https://github.com/glimmerjs/glimmer-vm/pull/943) Remove redundant "this" ([@2hu12](https://github.com/2hu12)) + +#### Committers: 4 +- 2hu ([@2hu12](https://github.com/2hu12)) +- Edward Faulkner ([@ef4](https://github.com/ef4)) +- Robert Jackson ([@rwjblue](https://github.com/rwjblue)) +- Tobias Bieniek ([@Turbo87](https://github.com/Turbo87)) + + +## v0.40.1 (2019-04-16) + +#### :rocket: Enhancement +* `@glimmer/integration-tests`, `@glimmer/interfaces`, `@glimmer/node`, `@glimmer/runtime`, `@glimmer/syntax` + * [#931](https://github.com/glimmerjs/glimmer-vm/pull/931) Modifying in-element semantics to support non-null insertBefore elements ([@chiragpat](https://github.com/chiragpat)) + +#### Committers: 1 +- Chirag Patel ([@chiragpat](https://github.com/chiragpat)) + + +## v0.40.0 (2019-04-08) + +#### :boom: Breaking Change +* `@glimmer/integration-tests`, `@glimmer/interfaces`, `@glimmer/node`, `@glimmer/opcode-compiler`, `@glimmer/runtime`, `@glimmer/syntax` + * [#918](https://github.com/glimmerjs/glimmer-vm/pull/918) [FEATURE | BREAKING] Change semantics of in-element to match emberjs/rfcs#287 ([@chadhietala](https://github.com/chadhietala)) + +#### :rocket: Enhancement +* `@glimmer/compiler`, `@glimmer/integration-tests`, `@glimmer/interfaces`, `@glimmer/runtime`, `@glimmer/wire-format` + * [#923](https://github.com/glimmerjs/glimmer-vm/pull/923) Allow forward element modifiers into component invocations via ...attributes ([@cibernox](https://github.com/cibernox)) +* `@glimmer/integration-tests`, `@glimmer/runtime` + * [#924](https://github.com/glimmerjs/glimmer-vm/pull/924) Add ability to pass in dynamic scope to render component apis ([@chiragpat](https://github.com/chiragpat)) +* `@glimmer/integration-tests`, `@glimmer/interfaces`, `@glimmer/node`, `@glimmer/opcode-compiler`, `@glimmer/runtime`, `@glimmer/syntax` + * [#918](https://github.com/glimmerjs/glimmer-vm/pull/918) [FEATURE | BREAKING] Change semantics of in-element to match emberjs/rfcs#287 ([@chadhietala](https://github.com/chadhietala)) + +#### :bug: Bug Fix +* `@glimmer/compiler`, `@glimmer/integration-tests`, `@glimmer/interfaces`, `@glimmer/node`, `@glimmer/opcode-compiler`, `@glimmer/runtime`, `@glimmer/wire-format` + * [#928](https://github.com/glimmerjs/glimmer-vm/pull/928) Fix modifiers order ([@chancancode](https://github.com/chancancode)) +* `@glimmer/compiler`, `@glimmer/integration-tests` + * [#869](https://github.com/glimmerjs/glimmer-vm/pull/869) Ensure passing attribute as mustache properly forwards the current namespace (e.g. svg) ([@mhankus](https://github.com/mhankus)) + +#### Committers: 6 +- Chad Hietala ([@chadhietala](https://github.com/chadhietala)) +- Chirag Patel ([@chiragpat](https://github.com/chiragpat)) +- Edward Faulkner ([@ef4](https://github.com/ef4)) +- Godfrey Chan ([@chancancode](https://github.com/chancancode)) +- Miguel Camba ([@cibernox](https://github.com/cibernox)) +- Mirek Hankus ([@mhankus](https://github.com/mhankus)) + +## v0.39.3 (2019-03-15) + +#### :bug: Bug Fix +* `@glimmer/runtime` + * [#922](https://github.com/glimmerjs/glimmer-vm/pull/922) Use type generic for `scope()` function ([@pzuraq](https://github.com/pzuraq)) +* `@glimmer/interfaces` + * [#921](https://github.com/glimmerjs/glimmer-vm/pull/921) ComponentManager types - fix typeParam shadowing ([@mike-north](https://github.com/mike-north)) +* `@glimmer/syntax` + * [#919](https://github.com/glimmerjs/glimmer-vm/pull/919) fix: security audit handlebars update ([@knownasilya](https://github.com/knownasilya)) + +#### :house: Internal +* `@glimmer/bundle-compiler` + * [#917](https://github.com/glimmerjs/glimmer-vm/pull/917) Fixed typo on method name; compilerModuleLocatorResolver ([@wondersloth](https://github.com/wondersloth)) + +#### Committers: 4 +- Chris Garrett ([@pzuraq](https://github.com/pzuraq)) +- Ilya Radchenko ([@knownasilya](https://github.com/knownasilya)) +- Matthew Edwards ([@wondersloth](https://github.com/wondersloth)) +- Mike North ([@mike-north](https://github.com/mike-north)) + +## 0.37.0 (2018-11-29) + +#### :bug: Bug Fix +* Other + * [#863](https://github.com/glimmerjs/glimmer-vm/pull/863) Fixed Windows Build Error. ([@mattselden12](https://github.com/mattselden12)) +* `@glimmer/interfaces`, `@glimmer/node`, `@glimmer/runtime` + * [#856](https://github.com/glimmerjs/glimmer-vm/pull/856) `Bounds` must be non-empty. ([@chancancode](https://github.com/chancancode)) + +#### :memo: Documentation +* [#862](https://github.com/glimmerjs/glimmer-vm/pull/862) [DOCS] Adds runtime documentation. ([@pzuraq](https://github.com/pzuraq)) + +#### Committers: 5 +- Chris Garrett ([pzuraq](https://github.com/pzuraq)) +- Godfrey Chan ([chancancode](https://github.com/chancancode)) +- Robert Jackson ([rwjblue](https://github.com/rwjblue)) +- Tom Dale ([tomdale](https://github.com/tomdale)) +- [mattselden12](https://github.com/mattselden12) + +## v0.36.5 (2018-10-16) + +#### :rocket: Enhancement +* `@glimmer/runtime` + * [#858](https://github.com/glimmerjs/glimmer-vm/pull/858) Export RenderComponentArgs. ([@chiragpat](https://github.com/chiragpat)) +* `@glimmer/bundle-compiler`, `@glimmer/runtime`, `@glimmer/test-helpers` + * [#850](https://github.com/glimmerjs/glimmer-vm/pull/850) Exposing a primitive renderComponent API. ([@chiragpat](https://github.com/chiragpat)) + +#### :bug: Bug Fix +* `@glimmer/bundle-compiler`, `@glimmer/opcode-compiler`, `@glimmer/vm` + * [#857](https://github.com/glimmerjs/glimmer-vm/pull/857) Fix debug issues reported in glimmerjs/glimmer-vm#846. ([@chiragpat](https://github.com/chiragpat)) + +#### Committers: 1 +- Chirag Patel ([chiragpat](https://github.com/chiragpat)) + +## v031.0 (2018-02-08) + +#### :boom: Breaking Change +* `@glimmer/bundle-compiler`, `@glimmer/interfaces`, `@glimmer/test-helpers` + * [#778](https://github.com/glimmerjs/glimmer-vm/pull/778) Move ModuleLocator and related interfaces to @glimmer/interfaces. ([@tomdale](https://github.com/tomdale)) + +#### :rocket: Enhancement +* `@glimmer/node`, `@glimmer/runtime`, `@glimmer/test-helpers` + * [#775](https://github.com/glimmerjs/glimmer-vm/pull/775) Serialized format renaming. ([@chadhietala](https://github.com/chadhietala)) +* `@glimmer/encoder`, `@glimmer/opcode-compiler`, `@glimmer/program` + * [#774](https://github.com/glimmerjs/glimmer-vm/pull/774) Fix args alloc. ([@krisselden](https://github.com/krisselden)) +* `@glimmer/runtime` + * [#771](https://github.com/glimmerjs/glimmer-vm/pull/771) improve nested transaction error message. ([@GavinJoyce](https://github.com/GavinJoyce)) + +#### :memo: Documentation +* [#768](https://github.com/glimmerjs/glimmer-vm/pull/768) Start fleshing out the precompiler docs. ([@smfoote](https://github.com/smfoote)) + +#### :house: Internal +* `@glimmer/runtime`, `@glimmer/vm` + * [#773](https://github.com/glimmerjs/glimmer-vm/pull/773) Encode component capabilities using bitmasks. ([@tomdale](https://github.com/tomdale)) + +#### Committers: 5 +- Chad Hietala ([chadhietala](https://github.com/chadhietala)) +- Gavin Joyce ([GavinJoyce](https://github.com/GavinJoyce)) +- Kris Selden ([krisselden](https://github.com/krisselden)) +- Steven ([smfoote](https://github.com/smfoote)) +- Tom Dale ([tomdale](https://github.com/tomdale)) + + +## v0.30.4 (2018-01-12) + +#### :bug: Bug Fix +* `@glimmer/opcode-compiler`, `@glimmer/runtime`, `@glimmer/vm` + * [#767](https://github.com/glimmerjs/glimmer-vm/pull/767) Fix nested currying.. ([@rwjblue](https://github.com/rwjblue)) +* `@glimmer/runtime` + * [#762](https://github.com/glimmerjs/glimmer-vm/pull/762) Allow null for iterable keys. ([@smfoote](https://github.com/smfoote)) + * [#761](https://github.com/glimmerjs/glimmer-vm/pull/761) Fix has-block-params in prod mode. ([@wycats](https://github.com/wycats)) + +#### Committers: 5 +- Chad Hietala ([chadhietala](https://github.com/chadhietala)) +- Kris Selden ([krisselden](https://github.com/krisselden)) +- Robert Jackson ([rwjblue](https://github.com/rwjblue)) +- Steven ([smfoote](https://github.com/smfoote)) +- Yehuda Katz ([wycats](https://github.com/wycats)) + + +## v0.30.3 (2017-11-27) + +#### :house: Internal +* [#742](https://github.com/glimmerjs/glimmer-vm/pull/742) Upgrade broccoli-rollup. ([@t-sauer](https://github.com/t-sauer)) + +#### Committers: 2 +- Chad Hietala ([chadhietala](https://github.com/chadhietala)) +- Thomas Sauer ([t-sauer](https://github.com/t-sauer)) + + +## v0.30.2 (2017-11-14) + +#### :bug: Bug Fix +* `@glimmer/encoder`, `@glimmer/interfaces`, `@glimmer/opcode-compiler`, `@glimmer/program`, `@glimmer/test-helpers` + * [#741](https://github.com/glimmerjs/glimmer-vm/pull/741) Fix bytecode recursive component invocation. ([@tomdale](https://github.com/tomdale)) + +#### :house: Internal +* `@glimmer/test-helpers` + * [#740](https://github.com/glimmerjs/glimmer-vm/pull/740) Mark @glimmer/test-helpers as private. ([@chadhietala](https://github.com/chadhietala)) + +#### Committers: 2 +- Chad Hietala ([chadhietala](https://github.com/chadhietala)) +- Tom Dale ([tomdale](https://github.com/tomdale)) + + +## v0.30.0 (2017-11-08) + +#### :rocket: Enhancement +* `@glimmer/bundle-compiler`, `@glimmer/interfaces`, `@glimmer/opcode-compiler`, `@glimmer/runtime`, `@glimmer/test-helpers` + * [#735](https://github.com/glimmerjs/glimmer-vm/pull/735) Allow passing additional template metadata to BundleCompiler. ([@tomdale](https://github.com/tomdale)) +* `@glimmer/bundle-compiler`, `@glimmer/opcode-compiler`, `@glimmer/program`, `@glimmer/runtime`, `@glimmer/test-helpers`, `@glimmer/vm` + * [#701](https://github.com/glimmerjs/glimmer-vm/pull/701) Initial work towards the renderComponent API. ([@chadhietala](https://github.com/chadhietala)) + +#### :bug: Bug Fix +* `@glimmer/runtime` + * [#727](https://github.com/glimmerjs/glimmer-vm/pull/727) [CLEANUP] Use correct environment. ([@Serabe](https://github.com/Serabe)) + * [#730](https://github.com/glimmerjs/glimmer-vm/pull/730) Fix nested partials within a `{{#with}}` block (#728). ([@GavinJoyce](https://github.com/GavinJoyce)) +* `@glimmer/interfaces`, `@glimmer/runtime` + * [#733](https://github.com/glimmerjs/glimmer-vm/pull/733) Fix Bounds and ElementBuilder interfaces.. ([@krisselden](https://github.com/krisselden)) + +#### :memo: Documentation +* [#724](https://github.com/glimmerjs/glimmer-vm/pull/724) guides: Fix several issues in TS codeblocks. ([@Turbo87](https://github.com/Turbo87)) + +#### :house: Internal +* `@glimmer/bundle-compiler`, `@glimmer/opcode-compiler`, `@glimmer/program`, `@glimmer/runtime`, `@glimmer/test-helpers`, `@glimmer/wire-format` + * [#738](https://github.com/glimmerjs/glimmer-vm/pull/738) Unify eager and lazy compilation metadata semantics. ([@tomdale](https://github.com/tomdale)) +* `@glimmer/bundle-compiler`, `@glimmer/runtime`, `@glimmer/test-helpers` + * [#737](https://github.com/glimmerjs/glimmer-vm/pull/737) Add tests for basic #each use cases. ([@chadhietala](https://github.com/chadhietala)) +* Other + * [#725](https://github.com/glimmerjs/glimmer-vm/pull/725) Remove obsolete "lerna.json" file. ([@Turbo87](https://github.com/Turbo87)) + +#### Committers: 6 +- Chad Hietala ([chadhietala](https://github.com/chadhietala)) +- Gavin Joyce ([GavinJoyce](https://github.com/GavinJoyce)) +- Kris Selden ([krisselden](https://github.com/krisselden)) +- Sergio Arbeo ([Serabe](https://github.com/Serabe)) +- Tobias Bieniek ([Turbo87](https://github.com/Turbo87)) +- Tom Dale ([tomdale](https://github.com/tomdale)) + + +## v0.29.1 (2017-10-27) + +#### :rocket: Enhancement +* `@glimmer/program` + * [#721](https://github.com/glimmerjs/glimmer-vm/pull/721) Compact Heap Table. ([@chadhietala](https://github.com/chadhietala)) + +#### :memo: Documentation +* [#717](https://github.com/glimmerjs/glimmer-vm/pull/717) Add Changelog file. ([@Turbo87](https://github.com/Turbo87)) + +#### :house: Internal +* `@glimmer/node`, `@glimmer/runtime` + * [#723](https://github.com/glimmerjs/glimmer-vm/pull/723) Don't infer the return type of the builder factories. ([@chadhietala](https://github.com/chadhietala)) + +#### Committers: 2 +- Chad Hietala ([chadhietala](https://github.com/chadhietala)) +- Tobias Bieniek ([Turbo87](https://github.com/Turbo87)) + + +## v0.29.10 (2017-10-27) + +#### :rocket: Enhancement +* `@glimmer/program` + * [#721](https://github.com/glimmerjs/glimmer-vm/pull/721) Compact Heap Table. ([@chadhietala](https://github.com/chadhietala)) + +#### :memo: Documentation +* [#717](https://github.com/glimmerjs/glimmer-vm/pull/717) Add Changelog file. ([@Turbo87](https://github.com/Turbo87)) + +#### :house: Internal +* `@glimmer/node`, `@glimmer/runtime` + * [#723](https://github.com/glimmerjs/glimmer-vm/pull/723) Don't infer the return type of the builder factories. ([@chadhietala](https://github.com/chadhietala)) + +#### Committers: 2 +- Chad Hietala ([chadhietala](https://github.com/chadhietala)) +- Tobias Bieniek ([Turbo87](https://github.com/Turbo87)) + + +## v0.29.9 (2017-10-25) + +#### :rocket: Enhancement +* `@glimmer/compiler`, `@glimmer/opcode-compiler`, `@glimmer/wire-format` + * [#720](https://github.com/glimmerjs/glimmer-vm/pull/720) [Cleanup] Remove top-level invocations. ([@chadhietala](https://github.com/chadhietala)) +* `@glimmer/bundle-compiler`, `@glimmer/program` + * [#712](https://github.com/glimmerjs/glimmer-vm/pull/712) Special case an empty array constant. ([@chadhietala](https://github.com/chadhietala)) + +#### :bug: Bug Fix +* `@glimmer/runtime`, `@glimmer/test-helpers` + * [#718](https://github.com/glimmerjs/glimmer-vm/pull/718) [BUGFIX] Fix Frozen Args When Currying. ([@chadhietala](https://github.com/chadhietala)) +* `@glimmer/bundle-compiler` + * [#714](https://github.com/glimmerjs/glimmer-vm/pull/714) Don't continuously recompile the layout. ([@chadhietala](https://github.com/chadhietala)) + +#### :house: Internal +* `@glimmer/object-reference`, `@glimmer/object`, `@glimmer/runtime`, `@glimmer/test-helpers`, `@glimmer/util` + * [#585](https://github.com/glimmerjs/glimmer-vm/pull/585) Remove the use of angle type assertion. ([@Serabe](https://github.com/Serabe)) + +#### Committers: 2 +- Chad Hietala ([chadhietala](https://github.com/chadhietala)) +- Sergio Arbeo ([Serabe](https://github.com/Serabe)) + + +## v0.29.8 (2017-10-16) + +#### :bug: Bug Fix +* `@glimmer/bundle-compiler` + * [#711](https://github.com/glimmerjs/glimmer-vm/pull/711) fix(bundle-compiler): Properly cache compileOptions. ([@tomdale](https://github.com/tomdale)) +* `@glimmer/runtime` + * [#710](https://github.com/glimmerjs/glimmer-vm/pull/710) Cache value instead of reading from the element. ([@chadhietala](https://github.com/chadhietala)) + * [#708](https://github.com/glimmerjs/glimmer-vm/pull/708) Check if attribute value actually changed before setting it. ([@t-sauer](https://github.com/t-sauer)) +* `@glimmer/compiler`, `@glimmer/runtime` + * [#707](https://github.com/glimmerjs/glimmer-vm/pull/707) Fix path lookup inside helpers. ([@tomdale](https://github.com/tomdale)) + +#### :memo: Documentation +* `@glimmer/interfaces`, `@glimmer/runtime`, `@glimmer/test-helpers` + * [#709](https://github.com/glimmerjs/glimmer-vm/pull/709) Document capabilities. ([@tomdale](https://github.com/tomdale)) + +#### :house: Internal +* `@glimmer/runtime` + * [#575](https://github.com/glimmerjs/glimmer-vm/pull/575) Custom element modifiers. ([@robbiepitts](https://github.com/robbiepitts)) +* `@glimmer/object-reference` + * [#568](https://github.com/glimmerjs/glimmer-vm/pull/568) reuse `referenceFromParts`. ([@bekzod](https://github.com/bekzod)) + +#### Committers: 5 +- Chad Hietala ([chadhietala](https://github.com/chadhietala)) +- Robbie Pitts ([robbiepitts](https://github.com/robbiepitts)) +- Thomas Sauer ([t-sauer](https://github.com/t-sauer)) +- Tom Dale ([tomdale](https://github.com/tomdale)) +- bek ([bekzod](https://github.com/bekzod)) + + +## v0.29.7 (2017-10-12) + +#### :bug: Bug Fix +* `@glimmer/runtime` + * [#703](https://github.com/glimmerjs/glimmer-vm/pull/703) Initialize v0 register. ([@tomdale](https://github.com/tomdale)) +* Other + * [#704](https://github.com/glimmerjs/glimmer-vm/pull/704) Fix stripped return statements in production builds. ([@tomdale](https://github.com/tomdale)) + +#### Committers: 1 +- Tom Dale ([tomdale](https://github.com/tomdale)) + + +## v0.29.5 (2017-10-11) + +#### :bug: Bug Fix +* `@glimmer/wire-format` + * [#700](https://github.com/glimmerjs/glimmer-vm/pull/700) Remove temporary enum value. ([@chadhietala](https://github.com/chadhietala)) + +#### :house: Internal +* `@glimmer/bundle-compiler`, `@glimmer/runtime`, `@glimmer/syntax`, `@glimmer/test-helpers` + * [#702](https://github.com/glimmerjs/glimmer-vm/pull/702) Move In-Element Specific Transform Into Visitor. ([@chadhietala](https://github.com/chadhietala)) + +#### Committers: 1 +- Chad Hietala ([chadhietala](https://github.com/chadhietala)) + + +## v0.29.4 (2017-10-10) + +#### :rocket: Enhancement +* `@glimmer/runtime` + * [#693](https://github.com/glimmerjs/glimmer-vm/pull/693) Guard for idempotent sets. ([@chadhietala](https://github.com/chadhietala)) + +#### :bug: Bug Fix +* `@glimmer/program`, `@glimmer/test-helpers` + * [#699](https://github.com/glimmerjs/glimmer-vm/pull/699) Fix floats and negative numbers. ([@chadhietala](https://github.com/chadhietala)) +* `@glimmer/runtime`, `@glimmer/test-helpers` + * [#697](https://github.com/glimmerjs/glimmer-vm/pull/697) Fix Memory Leaks. ([@chadhietala](https://github.com/chadhietala)) +* `@glimmer/runtime` + * [#694](https://github.com/glimmerjs/glimmer-vm/pull/694) Skip setting attributes if backing reference is not dirty. ([@tomdale](https://github.com/tomdale)) + +#### :memo: Documentation +* [#696](https://github.com/glimmerjs/glimmer-vm/pull/696) Correct typos for clarity. ([@smfoote](https://github.com/smfoote)) + +#### :house: Internal +* `@glimmer/runtime`, `@glimmer/test-helpers` + * [#698](https://github.com/glimmerjs/glimmer-vm/pull/698) Migrate Attribute Tests. ([@chadhietala](https://github.com/chadhietala)) +* `@glimmer/bundle-compiler`, `@glimmer/test-helpers` + * [#676](https://github.com/glimmerjs/glimmer-vm/pull/676) Eager Mode testing needs to delegate to the correct method. ([@chadhietala](https://github.com/chadhietala)) + * [#695](https://github.com/glimmerjs/glimmer-vm/pull/695) Cleanup bundle compiler. ([@chadhietala](https://github.com/chadhietala)) + +#### Committers: 3 +- Chad Hietala ([chadhietala](https://github.com/chadhietala)) +- Steven ([smfoote](https://github.com/smfoote)) +- Tom Dale ([tomdale](https://github.com/tomdale)) + + +## v0.29.3 (2017-10-05) + +#### :boom: Breaking Change +* `@glimmer/opcode-compiler`, `@glimmer/program`, `@glimmer/runtime`, `@glimmer/test-helpers`, `@glimmer/util` + * [#680](https://github.com/glimmerjs/glimmer-vm/pull/680) Remove support for IE9/IE10/Phantom. ([@chadhietala](https://github.com/chadhietala)) + +#### :rocket: Enhancement +* `@glimmer/opcode-compiler`, `@glimmer/program`, `@glimmer/runtime`, `@glimmer/test-helpers`, `@glimmer/util` + * [#680](https://github.com/glimmerjs/glimmer-vm/pull/680) Remove support for IE9/IE10/Phantom. ([@chadhietala](https://github.com/chadhietala)) + +#### :bug: Bug Fix +* `@glimmer/dom-change-list`, `@glimmer/node`, `@glimmer/runtime`, `@glimmer/test-helpers`, `@glimmer/util` + * [#690](https://github.com/glimmerjs/glimmer-vm/pull/690) Fix Rehydration. ([@chadhietala](https://github.com/chadhietala)) +* `@glimmer/runtime` + * [#686](https://github.com/glimmerjs/glimmer-vm/pull/686) Targeted fix for SVG rehydration. ([@chadhietala](https://github.com/chadhietala)) + +#### :house: Internal +* `@glimmer/node`, `@glimmer/runtime`, `@glimmer/test-helpers` + * [#691](https://github.com/glimmerjs/glimmer-vm/pull/691) Cleanup some of the rehydration code. ([@chadhietala](https://github.com/chadhietala)) +* `benchmark`, `glimmer-benchmarks`, `glimmer-demos` + * [#688](https://github.com/glimmerjs/glimmer-vm/pull/688) Remove Demos And Benches From Repo. ([@chadhietala](https://github.com/chadhietala)) +* `@glimmer/runtime` + * [#684](https://github.com/glimmerjs/glimmer-vm/pull/684) Return early for common text appending cases. ([@chadhietala](https://github.com/chadhietala)) + +#### Committers: 1 +- Chad Hietala ([chadhietala](https://github.com/chadhietala)) + + +## v0.29.2 (2017-09-29) + +#### :rocket: Enhancement +* `@glimmer/node`, `@glimmer/opcode-compiler`, `@glimmer/runtime`, `@glimmer/syntax`, `@glimmer/test-helpers`, `@glimmer/vm` + * [#678](https://github.com/glimmerjs/glimmer-vm/pull/678) Rehydrate in-element. ([@chadhietala](https://github.com/chadhietala)) + +#### :bug: Bug Fix +* `@glimmer/runtime`, `@glimmer/test-helpers` + * [#681](https://github.com/glimmerjs/glimmer-vm/pull/681) Fix metamorphs during rehydration. ([@chadhietala](https://github.com/chadhietala)) +* `@glimmer/node`, `@glimmer/runtime`, `@glimmer/test-helpers` + * [#679](https://github.com/glimmerjs/glimmer-vm/pull/679) Node is not a thing in SSR. ([@chadhietala](https://github.com/chadhietala)) + +#### Committers: 1 +- Chad Hietala ([chadhietala](https://github.com/chadhietala)) + + +## v0.29.1 (2017-09-26) + +#### :house: Internal +* `@glimmer/runtime` + * [#671](https://github.com/glimmerjs/glimmer-vm/pull/671) Move the element builder factory functions to their respective files. ([@chadhietala](https://github.com/chadhietala)) +* Other + * [#673](https://github.com/glimmerjs/glimmer-vm/pull/673) Explicitly publish public packages during deploy. ([@tomdale](https://github.com/tomdale)) +* `@glimmer/bundle-compiler`, `@glimmer/compiler`, `@glimmer/opcode-compiler`, `@glimmer/syntax`, `@glimmer/test-helpers` + * [#674](https://github.com/glimmerjs/glimmer-vm/pull/674) Use simple-html-tokenizer's built-in types. ([@tomdale](https://github.com/tomdale)) + +#### Committers: 2 +- Chad Hietala ([chadhietala](https://github.com/chadhietala)) +- Tom Dale ([tomdale](https://github.com/tomdale)) + + +## v0.29.0 (2017-09-20) + +#### :boom: Breaking Change +* `@glimmer/node`, `@glimmer/runtime`, `@glimmer/test-helpers` + * [#667](https://github.com/glimmerjs/glimmer-vm/pull/667) [Breaking] Pass Instances Of Element Builders. ([@chadhietala](https://github.com/chadhietala)) + +#### :rocket: Enhancement +* Other + * [#670](https://github.com/glimmerjs/glimmer-vm/pull/670) Nuke the debugging imports from opcode-compiler. ([@chadhietala](https://github.com/chadhietala)) +* `@glimmer/node`, `@glimmer/runtime`, `@glimmer/test-helpers` + * [#667](https://github.com/glimmerjs/glimmer-vm/pull/667) [Breaking] Pass Instances Of Element Builders. ([@chadhietala](https://github.com/chadhietala)) + +#### :bug: Bug Fix +* Other + * [#672](https://github.com/glimmerjs/glimmer-vm/pull/672) Path for expanding debug APIs correction. ([@chadhietala](https://github.com/chadhietala)) +* `@glimmer/program`, `@glimmer/test-helpers` + * [#669](https://github.com/glimmerjs/glimmer-vm/pull/669) Don't use subarray to dump heap. ([@chadhietala](https://github.com/chadhietala)) +* `@glimmer/interfaces` + * [#666](https://github.com/glimmerjs/glimmer-vm/pull/666) Break @glimmer/interfaces circular dependency. ([@tomdale](https://github.com/tomdale)) + +#### :memo: Documentation +* `@glimmer/bundle-compiler`, `@glimmer/compiler`, `@glimmer/interfaces`, `@glimmer/node`, `@glimmer/opcode-compiler`, `@glimmer/runtime`, `@glimmer/test-helpers`, `@glimmer/util`, `@glimmer/vm` + * [#663](https://github.com/glimmerjs/glimmer-vm/pull/663) Component terminology cleanup. ([@tomdale](https://github.com/tomdale)) +* `@glimmer/program` + * [#664](https://github.com/glimmerjs/glimmer-vm/pull/664) Document Heap. ([@chadhietala](https://github.com/chadhietala)) + +#### :house: Internal +* `@glimmer/runtime`, `@glimmer/syntax`, `@glimmer/test-helpers` + * [#668](https://github.com/glimmerjs/glimmer-vm/pull/668) Smoke test types before publishing. ([@tomdale](https://github.com/tomdale)) +* `@glimmer/debug`, `@glimmer/opcode-compiler`, `@glimmer/runtime`, `@glimmer/vm` + * [#662](https://github.com/glimmerjs/glimmer-vm/pull/662) Refactor call protocol. ([@mmun](https://github.com/mmun)) +* `@glimmer/bundle-compiler`, `@glimmer/interfaces`, `@glimmer/node`, `@glimmer/object-reference`, `@glimmer/opcode-compiler`, `@glimmer/program`, `@glimmer/runtime`, `@glimmer/test-helpers`, `@glimmer/util` + * [#661](https://github.com/glimmerjs/glimmer-vm/pull/661) Use an ArrayBuffer for storing the heap. ([@chadhietala](https://github.com/chadhietala)) +* `@glimmer/program` + * [#665](https://github.com/glimmerjs/glimmer-vm/pull/665) Intern Constants Pool. ([@chadhietala](https://github.com/chadhietala)) + +#### Committers: 3 +- Chad Hietala ([chadhietala](https://github.com/chadhietala)) +- Martin Muñoz ([mmun](https://github.com/mmun)) +- Tom Dale ([tomdale](https://github.com/tomdale)) + + +## v0.28.3 (2017-09-13) + +#### :rocket: Enhancement +* [#660](https://github.com/glimmerjs/glimmer-vm/pull/660) Update nukable import to allow for binaryexpr stripping. ([@chadhietala](https://github.com/chadhietala)) + +#### Committers: 1 +- Chad Hietala ([chadhietala](https://github.com/chadhietala)) + + +## v0.28.2 (2017-09-13) + +#### :house: Internal +* `@glimmer/opcode-compiler` + * [#659](https://github.com/glimmerjs/glimmer-vm/pull/659) Convert `@glimmer/local-debug-flags` to dev dependency. ([@chadhietala](https://github.com/chadhietala)) + +#### Committers: 1 +- Chad Hietala ([chadhietala](https://github.com/chadhietala)) + + +## v0.28.1 (2017-09-13) + +#### :house: Internal +* `@glimmer/runtime`, `@glimmer/test-helpers`, `@glimmer/vm` + * [#658](https://github.com/glimmerjs/glimmer-vm/pull/658) Fix deps on @glimmer/debug. ([@chadhietala](https://github.com/chadhietala)) + +#### Committers: 1 +- Chad Hietala ([chadhietala](https://github.com/chadhietala)) + + +## v0.28.0 (2017-09-13) + +#### :boom: Breaking Change +* `@glimmer/bundle-compiler`, `@glimmer/compiler`, `@glimmer/interfaces`, `@glimmer/object`, `@glimmer/opcode-compiler`, `@glimmer/program`, `@glimmer/runtime`, `@glimmer/test-helpers`, `@glimmer/vm`, `@glimmer/wire-format` + * [#631](https://github.com/glimmerjs/glimmer-vm/pull/631) [Breaking] Introduce Bundle Compiler. ([@chadhietala](https://github.com/chadhietala)) +* `@glimmer/runtime` + * [#619](https://github.com/glimmerjs/glimmer-vm/pull/619) Make in-element a public construct. ([@chadhietala](https://github.com/chadhietala)) +* `@glimmer/compiler`, `@glimmer/interfaces`, `@glimmer/node`, `@glimmer/runtime`, `@glimmer/syntax`, `@glimmer/test-helpers`, `@glimmer/wire-format`, `glimmer-demos` + * [#602](https://github.com/glimmerjs/glimmer-vm/pull/602) Capital components. ([@chadhietala](https://github.com/chadhietala)) +* `@glimmer/compiler`, `@glimmer/interfaces`, `@glimmer/node`, `@glimmer/reference`, `@glimmer/runtime`, `@glimmer/syntax`, `@glimmer/test-helpers`, `@glimmer/util`, `@glimmer/vm`, `@glimmer/wire-format` + * [#599](https://github.com/glimmerjs/glimmer-vm/pull/599) All internals now support serialization. ([@chancancode](https://github.com/chancancode)) + +#### :rocket: Enhancement +* `@glimmer/opcode-compiler`, `@glimmer/runtime`, `@glimmer/vm` + * [#646](https://github.com/glimmerjs/glimmer-vm/pull/646) Don't rely on callerScope to yield. ([@mmun](https://github.com/mmun)) +* `@glimmer/program` + * [#649](https://github.com/glimmerjs/glimmer-vm/pull/649) use `length` returned from push. ([@bekzod](https://github.com/bekzod)) +* `@glimmer/encoder`, `@glimmer/interfaces`, `@glimmer/opcode-compiler`, `@glimmer/program`, `@glimmer/runtime`, `@glimmer/util` + * [#643](https://github.com/glimmerjs/glimmer-vm/pull/643) First Pass At Encoder. ([@chadhietala](https://github.com/chadhietala)) +* `@glimmer/debug`, `@glimmer/local-debug-flags`, `@glimmer/opcode-compiler`, `@glimmer/reference`, `@glimmer/runtime`, `@glimmer/test-helpers` + * [#639](https://github.com/glimmerjs/glimmer-vm/pull/639) Add stack assertions. ([@chadhietala](https://github.com/chadhietala)) +* `@glimmer/opcode-compiler` + * [#634](https://github.com/glimmerjs/glimmer-vm/pull/634) Fix dependencies and add ability to compile with flags. ([@chadhietala](https://github.com/chadhietala)) +* `@glimmer/runtime` + * [#630](https://github.com/glimmerjs/glimmer-vm/pull/630) Don't allocate empty arguments. ([@chadhietala](https://github.com/chadhietala)) + * [#619](https://github.com/glimmerjs/glimmer-vm/pull/619) Make in-element a public construct. ([@chadhietala](https://github.com/chadhietala)) +* `@glimmer/bundle-compiler`, `@glimmer/compiler`, `@glimmer/interfaces`, `@glimmer/object`, `@glimmer/opcode-compiler`, `@glimmer/program`, `@glimmer/runtime`, `@glimmer/test-helpers`, `@glimmer/vm`, `@glimmer/wire-format` + * [#631](https://github.com/glimmerjs/glimmer-vm/pull/631) [Breaking] Introduce Bundle Compiler. ([@chadhietala](https://github.com/chadhietala)) + +#### :bug: Bug Fix +* Other + * [#655](https://github.com/glimmerjs/glimmer-vm/pull/655) Retain opcode metadata if RETAIN_FLAGS is set. ([@tomdale](https://github.com/tomdale)) +* `@glimmer/bundle-compiler`, `@glimmer/debug`, `@glimmer/interfaces`, `@glimmer/opcode-compiler`, `@glimmer/program`, `@glimmer/runtime`, `@glimmer/test-helpers`, `@glimmer/vm` + * [#650](https://github.com/glimmerjs/glimmer-vm/pull/650) Fix deps on the @glimmer/vm. ([@chadhietala](https://github.com/chadhietala)) +* `@glimmer/opcode-compiler`, `@glimmer/test-helpers` + * [#647](https://github.com/glimmerjs/glimmer-vm/pull/647) fixed issue negative number rendering. ([@bekzod](https://github.com/bekzod)) +* `@glimmer/opcode-compiler`, `@glimmer/runtime`, `@glimmer/test-helpers`, `@glimmer/vm` + * [#644](https://github.com/glimmerjs/glimmer-vm/pull/644) Pop args from the stack for static invocations. ([@chadhietala](https://github.com/chadhietala)) +* `@glimmer/opcode-compiler`, `@glimmer/runtime` + * [#645](https://github.com/glimmerjs/glimmer-vm/pull/645) Fix logging... off by one 👺. ([@chadhietala](https://github.com/chadhietala)) +* `@glimmer/runtime` + * [#621](https://github.com/glimmerjs/glimmer-vm/pull/621) don't store negative numbers in constants. ([@bekzod](https://github.com/bekzod)) + * [#573](https://github.com/glimmerjs/glimmer-vm/pull/573) fix for constant float/negative values/references. ([@bekzod](https://github.com/bekzod)) +* `@glimmer/syntax` + * [#616](https://github.com/glimmerjs/glimmer-vm/pull/616) Start location fix for dynamic attributes. ([@initram](https://github.com/initram)) +* `@glimmer/runtime`, `@glimmer/test-helpers` + * [#601](https://github.com/glimmerjs/glimmer-vm/pull/601) Fix Mixins For Rehydration. ([@chadhietala](https://github.com/chadhietala)) +* `@glimmer/test-helpers` + * [#582](https://github.com/glimmerjs/glimmer-vm/pull/582) Fix issues with generating invocations. ([@chadhietala](https://github.com/chadhietala)) + +#### :house: Internal +* `@glimmer/bundle-compiler`, `@glimmer/node`, `@glimmer/test-helpers` + * [#654](https://github.com/glimmerjs/glimmer-vm/pull/654) Add Node Bundle Compiler Tests. ([@chadhietala](https://github.com/chadhietala)) + * [#653](https://github.com/glimmerjs/glimmer-vm/pull/653) Move bundle compiler and node infra into test-helpers. ([@chadhietala](https://github.com/chadhietala)) +* `@glimmer/runtime` + * [#656](https://github.com/glimmerjs/glimmer-vm/pull/656) Remove absolute path to sibling. ([@chadhietala](https://github.com/chadhietala)) + * [#626](https://github.com/glimmerjs/glimmer-vm/pull/626) Remove all Opcode.toJSON references. ([@chadhietala](https://github.com/chadhietala)) + * [#624](https://github.com/glimmerjs/glimmer-vm/pull/624) Cleanup DOM Helper. ([@chadhietala](https://github.com/chadhietala)) + * [#623](https://github.com/glimmerjs/glimmer-vm/pull/623) Actually run the has-block-param-helper tests. ([@chadhietala](https://github.com/chadhietala)) + * [#618](https://github.com/glimmerjs/glimmer-vm/pull/618) Use const enums for primitive value type flag. ([@tomdale](https://github.com/tomdale)) + * [#574](https://github.com/glimmerjs/glimmer-vm/pull/574) refactor constant flags. ([@bekzod](https://github.com/bekzod)) + * [#572](https://github.com/glimmerjs/glimmer-vm/pull/572) use index returned by `push`. ([@bekzod](https://github.com/bekzod)) + * [#604](https://github.com/glimmerjs/glimmer-vm/pull/604) Remove references from Constants. ([@chadhietala](https://github.com/chadhietala)) + * [#583](https://github.com/glimmerjs/glimmer-vm/pull/583) Port in element tests. ([@piotrpalek](https://github.com/piotrpalek)) + * [#567](https://github.com/glimmerjs/glimmer-vm/pull/567) Remove commented out tests 😞. ([@chadhietala](https://github.com/chadhietala)) + * [#566](https://github.com/glimmerjs/glimmer-vm/pull/566) Migrate compile and syntax errors. ([@chadhietala](https://github.com/chadhietala)) +* `@glimmer/node`, `@glimmer/test-helpers` + * [#652](https://github.com/glimmerjs/glimmer-vm/pull/652) Introduce Node test infra. ([@chadhietala](https://github.com/chadhietala)) +* `@glimmer/bundle-compiler`, `@glimmer/compiler`, `@glimmer/debug`, `@glimmer/interfaces`, `@glimmer/opcode-compiler`, `@glimmer/program`, `@glimmer/runtime`, `@glimmer/test-helpers` + * [#641](https://github.com/glimmerjs/glimmer-vm/pull/641) Rename all instances of `referer` to `referrer`. ([@tomdale](https://github.com/tomdale)) +* `@glimmer/test-helpers` + * [#642](https://github.com/glimmerjs/glimmer-vm/pull/642) Remove absolute path to test components. ([@chadhietala](https://github.com/chadhietala)) + * [#590](https://github.com/glimmerjs/glimmer-vm/pull/590) Adding tests around snapshots and setting properties. ([@chadhietala](https://github.com/chadhietala)) + * [#586](https://github.com/glimmerjs/glimmer-vm/pull/586) Allow to skip tests completely through test decorator. ([@chadhietala](https://github.com/chadhietala)) + * [#578](https://github.com/glimmerjs/glimmer-vm/pull/578) CallExpression `@test` decorator. ([@chadhietala](https://github.com/chadhietala)) + * [#563](https://github.com/glimmerjs/glimmer-vm/pull/563) Stop publishing @glimmer/test-helpers. ([@robbiepitts](https://github.com/robbiepitts)) +* Other + * [#636](https://github.com/glimmerjs/glimmer-vm/pull/636) Suppress Rollup warnings. ([@mixonic](https://github.com/mixonic)) + * [#617](https://github.com/glimmerjs/glimmer-vm/pull/617) Cleanup multiple watchers during build. ([@chadhietala](https://github.com/chadhietala)) +* `@glimmer/bundle-compiler`, `@glimmer/opcode-compiler`, `@glimmer/runtime`, `@glimmer/util`, `@glimmer/vm` + * [#640](https://github.com/glimmerjs/glimmer-vm/pull/640) Wycats stack check. ([@wycats](https://github.com/wycats)) +* `@glimmer/bundle-compiler` + * [#638](https://github.com/glimmerjs/glimmer-vm/pull/638) Bundle Compiler refactoring pass. ([@tomdale](https://github.com/tomdale)) +* `@glimmer/reference` + * [#625](https://github.com/glimmerjs/glimmer-vm/pull/625) Remove ToBoolean conversions. ([@chadhietala](https://github.com/chadhietala)) +* `@glimmer/bundle-compiler`, `@glimmer/runtime`, `@glimmer/test-helpers` + * [#633](https://github.com/glimmerjs/glimmer-vm/pull/633) Move Migrated Tests To Suites. ([@chadhietala](https://github.com/chadhietala)) +* `@glimmer/runtime`, `@glimmer/test-helpers` + * [#627](https://github.com/glimmerjs/glimmer-vm/pull/627) Port Debugger Tests. ([@chadhietala](https://github.com/chadhietala)) + * [#614](https://github.com/glimmerjs/glimmer-vm/pull/614) Upgrade qunit. ([@chadhietala](https://github.com/chadhietala)) + * [#598](https://github.com/glimmerjs/glimmer-vm/pull/598) serializing in tests should serialize the Simple DOM document. ([@chadhietala](https://github.com/chadhietala)) + * [#596](https://github.com/glimmerjs/glimmer-vm/pull/596) Use TS mixin pattern for tests. ([@chadhietala](https://github.com/chadhietala)) + * [#588](https://github.com/glimmerjs/glimmer-vm/pull/588) Introduce tests for the test harness. ([@chadhietala](https://github.com/chadhietala)) + * [#580](https://github.com/glimmerjs/glimmer-vm/pull/580) Component Testing Infrastructure. ([@chadhietala](https://github.com/chadhietala)) + * [#560](https://github.com/glimmerjs/glimmer-vm/pull/560) More targeted test harnesses. ([@chadhietala](https://github.com/chadhietala)) +* `@glimmer/local-debug-flags`, `@glimmer/node`, `@glimmer/object`, `@glimmer/runtime`, `@glimmer/syntax`, `@glimmer/test-helpers`, `@glimmer/util`, `@glimmer/vm`, `@glimmer/wire-format`, `glimmer` + * [#606](https://github.com/glimmerjs/glimmer-vm/pull/606) Unify Broccoli build. ([@tomdale](https://github.com/tomdale)) +* `@glimmer/reference`, `@glimmer/runtime`, `@glimmer/vm` + * [#609](https://github.com/glimmerjs/glimmer-vm/pull/609) Moar GC Sweep. ([@chadhietala](https://github.com/chadhietala)) +* `@glimmer/compiler`, `@glimmer/reference`, `@glimmer/runtime`, `@glimmer/util` + * [#608](https://github.com/glimmerjs/glimmer-vm/pull/608) GC Sweep. ([@chadhietala](https://github.com/chadhietala)) +* `@glimmer/local-debug-flags`, `@glimmer/node` + * [#593](https://github.com/glimmerjs/glimmer-vm/pull/593) Revive Node tests. ([@tomdale](https://github.com/tomdale)) +* `@glimmer/object` + * [#595](https://github.com/glimmerjs/glimmer-vm/pull/595) Upgrade to TS 2.4. ([@chancancode](https://github.com/chancancode)) +* `@glimmer/object-model` + * [#594](https://github.com/glimmerjs/glimmer-vm/pull/594) Remove unused object model. ([@chancancode](https://github.com/chancancode)) + +#### Committers: 10 +- Chad Hietala ([chadhietala](https://github.com/chadhietala)) +- Godfrey Chan ([chancancode](https://github.com/chancancode)) +- Martin Midtgaard ([initram](https://github.com/initram)) +- Martin Muñoz ([mmun](https://github.com/mmun)) +- Matthew Beale ([mixonic](https://github.com/mixonic)) +- Peter ([piotrpalek](https://github.com/piotrpalek)) +- Robbie Pitts ([robbiepitts](https://github.com/robbiepitts)) +- Tom Dale ([tomdale](https://github.com/tomdale)) +- Yehuda Katz ([wycats](https://github.com/wycats)) +- bek ([bekzod](https://github.com/bekzod)) + + +## v0.26.1 (2017-07-03) + +#### :house: Internal +* `@glimmer/runtime` + * [#562](https://github.com/glimmerjs/glimmer-vm/pull/562) Fix import. ([@robbiepitts](https://github.com/robbiepitts)) + +#### Committers: 1 +- Robbie Pitts ([robbiepitts](https://github.com/robbiepitts)) + + +## v0.25.2 (2017-06-30) + +#### :boom: Breaking Change +* `@glimmer/syntax` + * [#557](https://github.com/glimmerjs/glimmer-vm/pull/557) [BREAKING] Update ASTPluginResult to use `visitor` (no plural form).. ([@rwjblue](https://github.com/rwjblue)) +* `@glimmer/reference`, `@glimmer/runtime`, `@glimmer/test-helpers` + * [#558](https://github.com/glimmerjs/glimmer-vm/pull/558) [BREAKING] Make the manager decide what tag to use. ([@chancancode](https://github.com/chancancode)) + +#### :rocket: Enhancement +* `@glimmer/interfaces`, `@glimmer/node`, `@glimmer/object`, `@glimmer/runtime`, `@glimmer/test-helpers`, `@glimmer/util`, `glimmer-demos`, `simple-dom` + * [#549](https://github.com/glimmerjs/glimmer-vm/pull/549) Rehydration. ([@wycats](https://github.com/wycats)) + +#### :house: Internal +* `@glimmer/runtime`, `@glimmer/test-helpers` + * [#559](https://github.com/glimmerjs/glimmer-vm/pull/559) Migrate initial render tests. ([@chadhietala](https://github.com/chadhietala)) + +#### Committers: 4 +- Chad Hietala ([chadhietala](https://github.com/chadhietala)) +- Godfrey Chan ([chancancode](https://github.com/chancancode)) +- Robert Jackson ([rwjblue](https://github.com/rwjblue)) +- Yehuda Katz ([wycats](https://github.com/wycats)) + + +## v0.25.0 (2017-06-20) + +#### :boom: Breaking Change +* `@glimmer/compiler`, `@glimmer/syntax` + * [#551](https://github.com/glimmerjs/glimmer-vm/pull/551) [BREAKING] Use plain functions for AST plugins.. ([@rwjblue](https://github.com/rwjblue)) + +#### Committers: 1 +- Robert Jackson ([rwjblue](https://github.com/rwjblue)) + + +## v0.24.0 (2017-06-20) + +#### :rocket: Enhancement +* `@glimmer/compiler`, `@glimmer/syntax` + * [#548](https://github.com/glimmerjs/glimmer-vm/pull/548) Types for AST transform plugins. ([@tomdale](https://github.com/tomdale)) + * [#540](https://github.com/glimmerjs/glimmer-vm/pull/540) Adds `SyntaxError`. ([@twokul](https://github.com/twokul)) +* `@glimmer/runtime`, `@glimmer/util` + * [#527](https://github.com/glimmerjs/glimmer-vm/pull/527) Implement memory compaction. ([@chadhietala](https://github.com/chadhietala)) +* `@glimmer/runtime` + * [#474](https://github.com/glimmerjs/glimmer-vm/pull/474) Unify dom. ([@chadhietala](https://github.com/chadhietala)) + +#### :bug: Bug Fix +* `@glimmer/runtime` + * [#555](https://github.com/glimmerjs/glimmer-vm/pull/555) Fix static multi select test for Edge 15. ([@t-sauer](https://github.com/t-sauer)) + * [#534](https://github.com/glimmerjs/glimmer-vm/pull/534) Use correct casing for `Element.prototype.insertAdjacentHTML` position.. ([@rwjblue](https://github.com/rwjblue)) + * [#523](https://github.com/glimmerjs/glimmer-vm/pull/523) Fix scanner. ([@chadhietala](https://github.com/chadhietala)) + * [#505](https://github.com/glimmerjs/glimmer-vm/pull/505) Ensure transactions are always. ([@stefanpenner](https://github.com/stefanpenner)) + * [#503](https://github.com/glimmerjs/glimmer-vm/pull/503) Use older syntax for binary operations.. ([@rwjblue](https://github.com/rwjblue)) + * [#502](https://github.com/glimmerjs/glimmer-vm/pull/502) Remove usage of `for...of`.. ([@rwjblue](https://github.com/rwjblue)) + * [#497](https://github.com/glimmerjs/glimmer-vm/pull/497) Don't leak objects on the stack. ([@chadhietala](https://github.com/chadhietala)) + * [#495](https://github.com/glimmerjs/glimmer-vm/pull/495) Avoid errors in debug tooling when handling circular structures.. ([@rwjblue](https://github.com/rwjblue)) + * [#499](https://github.com/glimmerjs/glimmer-vm/pull/499) Ensure positional arguments are accounted for in builder.. ([@rwjblue](https://github.com/rwjblue)) +* `@glimmer/syntax` + * [#550](https://github.com/glimmerjs/glimmer-vm/pull/550) Fix handlebars `parse` error. ([@robbiepitts](https://github.com/robbiepitts)) + * [#491](https://github.com/glimmerjs/glimmer-vm/pull/491) Fix @glimmer/syntax type errors. ([@tomdale](https://github.com/tomdale)) +* `@glimmer/runtime`, `@glimmer/test-helpers` + * [#509](https://github.com/glimmerjs/glimmer-vm/pull/509) Fix types 2. ([@krisselden](https://github.com/krisselden)) + * [#501](https://github.com/glimmerjs/glimmer-vm/pull/501) Ensure return value from `prepareArgs` properly handles @foo interop.. ([@rwjblue](https://github.com/rwjblue)) + * [#500](https://github.com/glimmerjs/glimmer-vm/pull/500) Ensure `hasDefault` and `hasInverse` function properly.. ([@rwjblue](https://github.com/rwjblue)) +* `@glimmer/node` + * [#507](https://github.com/glimmerjs/glimmer-vm/pull/507) Update NodeDOMTreeConstruction to match arg signature of `insertHTMLBefore`.. ([@rwjblue](https://github.com/rwjblue)) +* `@glimmer/runtime`, `@glimmer/test-helpers`, `simple-html-tokenizer` + * [#504](https://github.com/glimmerjs/glimmer-vm/pull/504) Fix types. ([@krisselden](https://github.com/krisselden)) + +#### :house: Internal +* `@glimmer/syntax` + * [#552](https://github.com/glimmerjs/glimmer-vm/pull/552) Convert `SyntaxError` and `TraversalError` to ES5 syntax. ([@robbiepitts](https://github.com/robbiepitts)) +* `@glimmer/public-runtime` + * [#538](https://github.com/glimmerjs/glimmer-vm/pull/538) Remove `packages/public-runtime`.. ([@rwjblue](https://github.com/rwjblue)) +* `@glimmer/runtime` + * [#533](https://github.com/glimmerjs/glimmer-vm/pull/533) Consolidate DOM Compat. ([@chadhietala](https://github.com/chadhietala)) + * [#531](https://github.com/glimmerjs/glimmer-vm/pull/531) Copy custom element tests forward from 0.22.x.. ([@rwjblue](https://github.com/rwjblue)) + * [#524](https://github.com/glimmerjs/glimmer-vm/pull/524) Add regression test for invoking component from another.. ([@rwjblue](https://github.com/rwjblue)) + * [#513](https://github.com/glimmerjs/glimmer-vm/pull/513) Remaining updating-test strict type checking fixes. ([@krisselden](https://github.com/krisselden)) + * [#506](https://github.com/glimmerjs/glimmer-vm/pull/506) Update DOMOperations to allow creation of the useless element to be customized.. ([@rwjblue](https://github.com/rwjblue)) + * [#498](https://github.com/glimmerjs/glimmer-vm/pull/498) Remove InitializeComponentState Opcode. ([@chadhietala](https://github.com/chadhietala)) + * [#489](https://github.com/glimmerjs/glimmer-vm/pull/489) Remove unused reserved NULL_REFERENCE and UNDEFINED_REFERENCE from consts. ([@chadhietala](https://github.com/chadhietala)) +* `@glimmer/runtime`, `@glimmer/test-helpers` + * [#528](https://github.com/glimmerjs/glimmer-vm/pull/528) Add more tests for `-in-element`.. ([@rwjblue](https://github.com/rwjblue)) + * [#510](https://github.com/glimmerjs/glimmer-vm/pull/510) more updating-test fixes. ([@krisselden](https://github.com/krisselden)) +* Other + * [#525](https://github.com/glimmerjs/glimmer-vm/pull/525) Skipped tests are bad. Hiding them doesn't fix anything.. ([@rwjblue](https://github.com/rwjblue)) + * [#522](https://github.com/glimmerjs/glimmer-vm/pull/522) Fix prod builds.. ([@rwjblue](https://github.com/rwjblue)) + * [#520](https://github.com/glimmerjs/glimmer-vm/pull/520) Fix production build.. ([@rwjblue](https://github.com/rwjblue)) + * [#517](https://github.com/glimmerjs/glimmer-vm/pull/517) update lockfile. ([@stefanpenner](https://github.com/stefanpenner)) + * [#516](https://github.com/glimmerjs/glimmer-vm/pull/516) bump ember-cli, because it has nice things. ([@stefanpenner](https://github.com/stefanpenner)) +* `@glimmer/local-debug-flags` + * [#512](https://github.com/glimmerjs/glimmer-vm/pull/512) Speed up tests by 73x by making logging opt-in. ([@stefanpenner](https://github.com/stefanpenner)) + +#### Committers: 8 +- Alex Navasardyan ([twokul](https://github.com/twokul)) +- Chad Hietala ([chadhietala](https://github.com/chadhietala)) +- Kris Selden ([krisselden](https://github.com/krisselden)) +- Robbie Pitts ([robbiepitts](https://github.com/robbiepitts)) +- Robert Jackson ([rwjblue](https://github.com/rwjblue)) +- Stefan Penner ([stefanpenner](https://github.com/stefanpenner)) +- Thomas Sauer ([t-sauer](https://github.com/t-sauer)) +- Tom Dale ([tomdale](https://github.com/tomdale)) + + +## v0.24.0-beta.6 (2017-06-16) + +#### :rocket: Enhancement +* `@glimmer/compiler`, `@glimmer/syntax` + * [#548](https://github.com/glimmerjs/glimmer-vm/pull/548) Types for AST transform plugins. ([@tomdale](https://github.com/tomdale)) + +#### :bug: Bug Fix +* `@glimmer/syntax` + * [#550](https://github.com/glimmerjs/glimmer-vm/pull/550) Fix handlebars `parse` error. ([@robbiepitts](https://github.com/robbiepitts)) + +#### Committers: 2 +- Robbie Pitts ([robbiepitts](https://github.com/robbiepitts)) +- Tom Dale ([tomdale](https://github.com/tomdale)) + + +## v0.24.0-beta.5 (2017-06-13) + +#### :rocket: Enhancement +* `@glimmer/compiler`, `@glimmer/syntax` + * [#540](https://github.com/glimmerjs/glimmer-vm/pull/540) Adds `SyntaxError`. ([@twokul](https://github.com/twokul)) +* `@glimmer/runtime`, `@glimmer/util` + * [#527](https://github.com/glimmerjs/glimmer-vm/pull/527) Implement memory compaction. ([@chadhietala](https://github.com/chadhietala)) + +#### :bug: Bug Fix +* `@glimmer/syntax` + * [#491](https://github.com/glimmerjs/glimmer-vm/pull/491) Fix @glimmer/syntax type errors. ([@tomdale](https://github.com/tomdale)) +* `@glimmer/runtime` + * [#534](https://github.com/glimmerjs/glimmer-vm/pull/534) Use correct casing for `Element.prototype.insertAdjacentHTML` position.. ([@rwjblue](https://github.com/rwjblue)) + +#### :house: Internal +* `@glimmer/public-runtime` + * [#538](https://github.com/glimmerjs/glimmer-vm/pull/538) Remove `packages/public-runtime`.. ([@rwjblue](https://github.com/rwjblue)) +* `@glimmer/runtime` + * [#533](https://github.com/glimmerjs/glimmer-vm/pull/533) Consolidate DOM Compat. ([@chadhietala](https://github.com/chadhietala)) + * [#531](https://github.com/glimmerjs/glimmer-vm/pull/531) Copy custom element tests forward from 0.22.x.. ([@rwjblue](https://github.com/rwjblue)) + * [#524](https://github.com/glimmerjs/glimmer-vm/pull/524) Add regression test for invoking component from another.. ([@rwjblue](https://github.com/rwjblue)) +* `@glimmer/runtime`, `@glimmer/test-helpers` + * [#528](https://github.com/glimmerjs/glimmer-vm/pull/528) Add more tests for `-in-element`.. ([@rwjblue](https://github.com/rwjblue)) +* Other + * [#525](https://github.com/glimmerjs/glimmer-vm/pull/525) Skipped tests are bad. Hiding them doesn't fix anything.. ([@rwjblue](https://github.com/rwjblue)) + +#### Committers: 4 +- Alex Navasardyan ([twokul](https://github.com/twokul)) +- Chad Hietala ([chadhietala](https://github.com/chadhietala)) +- Robert Jackson ([rwjblue](https://github.com/rwjblue)) +- Tom Dale ([tomdale](https://github.com/tomdale)) + + +## v0.24.0-beta.4 (2017-05-26) + +#### :bug: Bug Fix +* `@glimmer/runtime` + * [#523](https://github.com/glimmerjs/glimmer-vm/pull/523) Fix scanner. ([@chadhietala](https://github.com/chadhietala)) + * [#505](https://github.com/glimmerjs/glimmer-vm/pull/505) Ensure transactions are always. ([@stefanpenner](https://github.com/stefanpenner)) +* `@glimmer/runtime`, `@glimmer/test-helpers` + * [#509](https://github.com/glimmerjs/glimmer-vm/pull/509) Fix types 2. ([@krisselden](https://github.com/krisselden)) + +#### :house: Internal +* Other + * [#522](https://github.com/glimmerjs/glimmer-vm/pull/522) Fix prod builds.. ([@rwjblue](https://github.com/rwjblue)) + * [#520](https://github.com/glimmerjs/glimmer-vm/pull/520) Fix production build.. ([@rwjblue](https://github.com/rwjblue)) + * [#517](https://github.com/glimmerjs/glimmer-vm/pull/517) update lockfile. ([@stefanpenner](https://github.com/stefanpenner)) + * [#516](https://github.com/glimmerjs/glimmer-vm/pull/516) bump ember-cli, because it has nice things. ([@stefanpenner](https://github.com/stefanpenner)) +* `@glimmer/runtime` + * [#513](https://github.com/glimmerjs/glimmer-vm/pull/513) Remaining updating-test strict type checking fixes. ([@krisselden](https://github.com/krisselden)) +* `@glimmer/local-debug-flags` + * [#512](https://github.com/glimmerjs/glimmer-vm/pull/512) Speed up tests by 73x by making logging opt-in. ([@stefanpenner](https://github.com/stefanpenner)) +* `@glimmer/runtime`, `@glimmer/test-helpers` + * [#510](https://github.com/glimmerjs/glimmer-vm/pull/510) more updating-test fixes. ([@krisselden](https://github.com/krisselden)) + +#### Committers: 4 +- Chad Hietala ([chadhietala](https://github.com/chadhietala)) +- Kris Selden ([krisselden](https://github.com/krisselden)) +- Robert Jackson ([rwjblue](https://github.com/rwjblue)) +- Stefan Penner ([stefanpenner](https://github.com/stefanpenner)) + + +## v0.24.0-beta.3 (2017-05-24) + +#### :bug: Bug Fix +* `@glimmer/node` + * [#507](https://github.com/glimmerjs/glimmer-vm/pull/507) Update NodeDOMTreeConstruction to match arg signature of `insertHTMLBefore`.. ([@rwjblue](https://github.com/rwjblue)) +* `@glimmer/runtime`, `@glimmer/test-helpers`, `simple-html-tokenizer` + * [#504](https://github.com/glimmerjs/glimmer-vm/pull/504) Fix types. ([@krisselden](https://github.com/krisselden)) + +#### :house: Internal +* `@glimmer/runtime` + * [#506](https://github.com/glimmerjs/glimmer-vm/pull/506) Update DOMOperations to allow creation of the useless element to be customized.. ([@rwjblue](https://github.com/rwjblue)) + +#### Committers: 2 +- Kris Selden ([krisselden](https://github.com/krisselden)) +- Robert Jackson ([rwjblue](https://github.com/rwjblue)) + + +## v0.24.0-beta.2 (2017-05-23) + +#### :bug: Bug Fix +* `@glimmer/runtime` + * [#503](https://github.com/glimmerjs/glimmer-vm/pull/503) Use older syntax for binary operations.. ([@rwjblue](https://github.com/rwjblue)) + * [#502](https://github.com/glimmerjs/glimmer-vm/pull/502) Remove usage of `for...of`.. ([@rwjblue](https://github.com/rwjblue)) + +#### Committers: 1 +- Robert Jackson ([rwjblue](https://github.com/rwjblue)) + + +## v0.24.0-beta.1 (2017-05-23) + +#### :bug: Bug Fix +* `@glimmer/runtime`, `@glimmer/test-helpers` + * [#501](https://github.com/glimmerjs/glimmer-vm/pull/501) Ensure return value from `prepareArgs` properly handles @foo interop.. ([@rwjblue](https://github.com/rwjblue)) +* `@glimmer/runtime` + * [#497](https://github.com/glimmerjs/glimmer-vm/pull/497) Don't leak objects on the stack. ([@chadhietala](https://github.com/chadhietala)) + +#### :house: Internal +* `@glimmer/runtime` + * [#498](https://github.com/glimmerjs/glimmer-vm/pull/498) Remove InitializeComponentState Opcode. ([@chadhietala](https://github.com/chadhietala)) + +#### Committers: 2 +- Chad Hietala ([chadhietala](https://github.com/chadhietala)) +- Robert Jackson ([rwjblue](https://github.com/rwjblue)) + + +## v0.24.0-alpha.2 (2017-05-23) + +#### :rocket: Enhancement +* `@glimmer/runtime` + * [#474](https://github.com/glimmerjs/glimmer-vm/pull/474) Unify dom. ([@chadhietala](https://github.com/chadhietala)) + +#### :bug: Bug Fix +* `@glimmer/runtime`, `@glimmer/test-helpers` + * [#500](https://github.com/glimmerjs/glimmer-vm/pull/500) Ensure `hasDefault` and `hasInverse` function properly.. ([@rwjblue](https://github.com/rwjblue)) +* `@glimmer/runtime` + * [#495](https://github.com/glimmerjs/glimmer-vm/pull/495) Avoid errors in debug tooling when handling circular structures.. ([@rwjblue](https://github.com/rwjblue)) + * [#499](https://github.com/glimmerjs/glimmer-vm/pull/499) Ensure positional arguments are accounted for in builder.. ([@rwjblue](https://github.com/rwjblue)) + +#### Committers: 2 +- Chad Hietala ([chadhietala](https://github.com/chadhietala)) +- Robert Jackson ([rwjblue](https://github.com/rwjblue)) + + +## v0.24.0-alpha.1 (2017-05-19) + +#### :house: Internal +* `@glimmer/runtime` + * [#489](https://github.com/glimmerjs/glimmer-vm/pull/489) Remove unused reserved NULL_REFERENCE and UNDEFINED_REFERENCE from consts. ([@chadhietala](https://github.com/chadhietala)) + +#### Committers: 1 +- Chad Hietala ([chadhietala](https://github.com/chadhietala)) + + +## v0.23.0-alpha.15 (2017-05-16) + +#### :bug: Bug Fix +* `@glimmer/runtime` + * [#487](https://github.com/glimmerjs/glimmer-vm/pull/487) Fix predicate for iterator to be more declarative. ([@chadhietala](https://github.com/chadhietala)) +* Other + * [#485](https://github.com/glimmerjs/glimmer-vm/pull/485) Update @glimmer/build to 0.8.1. ([@tomdale](https://github.com/tomdale)) +* `@glimmer/runtime`, `@glimmer/wire-format` + * [#481](https://github.com/glimmerjs/glimmer-vm/pull/481) Fix some of the content deopt cases. ([@chadhietala](https://github.com/chadhietala)) + +#### :house: Internal +* `@glimmer/object-model`, `@glimmer/runtime`, `@glimmer/test-helpers`, `@glimmer/util` + * [#486](https://github.com/glimmerjs/glimmer-vm/pull/486) Remove forEach/map where we are creating context objects. ([@chadhietala](https://github.com/chadhietala)) +* `@glimmer/local-debug-flags`, `@glimmer/runtime` + * [#482](https://github.com/glimmerjs/glimmer-vm/pull/482) Skip top level custom element tests for now.. ([@krisselden](https://github.com/krisselden)) + +#### Committers: 3 +- Chad Hietala ([chadhietala](https://github.com/chadhietala)) +- Kris Selden ([krisselden](https://github.com/krisselden)) +- Tom Dale ([tomdale](https://github.com/tomdale)) + + +## v0.23.0-alpha.13 (2017-05-09) + +#### :rocket: Enhancement +* `@glimmer/compiler`, `@glimmer/object`, `@glimmer/runtime`, `@glimmer/syntax` + * [#475](https://github.com/glimmerjs/glimmer-vm/pull/475) More type fixes. ([@chadhietala](https://github.com/chadhietala)) + +#### :memo: Documentation +* [#478](https://github.com/glimmerjs/glimmer-vm/pull/478) Publish packages with licenses. ([@chadhietala](https://github.com/chadhietala)) + +#### :house: Internal +* `@glimmer/local-debug-flags`, `@glimmer/runtime` + * [#472](https://github.com/glimmerjs/glimmer-vm/pull/472) Introduce local dev flags. ([@chadhietala](https://github.com/chadhietala)) + +#### Committers: 2 +- Chad Hietala ([chadhietala](https://github.com/chadhietala)) +- Robert Jackson ([rwjblue](https://github.com/rwjblue)) + + +## v0.21.2 (2017-01-18) + +#### :bug: Bug Fix +* `@glimmer/syntax` + * [#390](https://github.com/glimmerjs/glimmer-vm/pull/390) Test nested 'else if' body location with whitespace eaten. ([@fhrbek](https://github.com/fhrbek)) + +#### Committers: 2 +- Filip Hrbek ([fhrbek](https://github.com/fhrbek)) +- Robbie Pitts ([robbiepitts](https://github.com/robbiepitts)) diff --git a/glimmer-vm/CLAUDE.md b/glimmer-vm/CLAUDE.md new file mode 100644 index 00000000000..f66d2a94102 --- /dev/null +++ b/glimmer-vm/CLAUDE.md @@ -0,0 +1,167 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Commands + +### Building + +- `pnpm build` - Build all packages via Turbo (recommended) +- `pnpm clean` - Clean build artifacts + +### Testing + +- `pnpm test` - Run all tests +- `pnpm dev` - Start Vite dev server for browser testing +- `pnpm test:node` - Run Node.js tests via Turbo + +To run a single test or test module, use the browser test interface with `pnpm dev` and filter tests using the QUnit UI. + +### Linting & Type Checking + +- `pnpm lint` - Run ESLint quietly +- `pnpm lint:fix` - Auto-fix linting issues and format with Prettier (required before commits) +- `pnpm lint:check` - Check Prettier formatting +- `pnpm lint:types` - Type check all packages via Turbo +- `pnpm lint:all` - Run all linting checks +- `pnpm lint:published` - Lint published packages + +### CI Preparation + +These commands MUST be run before pushing to ensure CI passes: + +- `pnpm lint:fix` - Fix formatting and linting +- `pnpm repo:update:conventions` - Update package conventions +- `pnpm repo:update:metadata` - Update package metadata + +The CI "Verify" job will fail if these commands produce uncommitted changes. + +## Architecture + +Glimmer VM is a **compiler-based rendering engine** that compiles Handlebars templates into bytecode for efficient execution and updates. + +### Core Flow + +1. **Templates** (Handlebars) → **Compiler** → **Bytecode** (Wire Format) +2. **Bytecode** → **Runtime VM** → **DOM Operations** +3. **State Changes** → **Validator System** → **Targeted Updates** + +### Key Packages + +**Compilation Pipeline**: + +- `@glimmer/syntax` - Template parser and AST (uses visitor pattern for traversal) +- `@glimmer/compiler` - Compiles templates to bytecode +- `@glimmer/wire-format` - Bytecode format definitions +- `@glimmer/opcode-compiler` - Bytecode generation + +**Runtime Engine**: + +- `@glimmer/runtime` - VM that executes bytecode +- `@glimmer/vm` - Core VM implementation +- `@glimmer/reference` - Reactive reference system for state tracking +- `@glimmer/validator` - Change detection and invalidation + +**Extension Points**: + +- `@glimmer/manager` - Component/helper/modifier manager APIs +- `@glimmer/interfaces` - TypeScript interfaces and contracts + +### Monorepo Structure + +- Uses pnpm workspaces with Turbo for orchestration +- Packages in `packages/@glimmer/*` are published to npm +- Packages in `packages/@glimmer-workspace/*` are internal tools +- Each package has its own tsconfig with varying strictness levels +- Node version requirement: >= 22.12.0 + +### TypeScript Patterns + +- "Friend" properties use bracket notation: `object['_privateProperty']` +- This allows cross-package internal access while maintaining type safety +- Different packages have different strictness levels in their tsconfig + +### Testing Strategy + +- Integration tests in `@glimmer-workspace/integration-tests` +- Unit tests colocated with packages +- Browser tests use QUnit + Vite +- Node tests use Vitest +- Smoke tests verify package compatibility + +### Debug Infrastructure + +The codebase includes sophisticated debug tooling: + +- `check()` function for runtime type checking (stripped in production by babel plugin) +- `@glimmer/debug` package for development-time debugging +- Stack checking and validation in development builds + +## Common Development Tasks + +### Running a specific test file + +```bash +# For Node tests (Vitest) +cd packages/@glimmer/[package-name] +pnpm test:node -- path/to/test.ts + +# For browser tests +pnpm dev +# Then navigate to the browser and use the QUnit filter +``` + +### After making AST changes + +If you modify the AST structure in `@glimmer/syntax`: + +1. Run smoke tests: `cd smoke-tests/node && pnpm test:node` +2. Update snapshots if needed: `pnpm vitest run -u` +3. Document why changes are not breaking (visitor pattern protection) + +### Before pushing changes + +Always run these commands to avoid CI failures: + +```bash +pnpm lint:fix +pnpm repo:update:conventions +pnpm repo:update:metadata +git add -A && git commit +``` + +## Contribution Guidelines + +### Commit Messages + +- Write clear, concise commit messages that explain the change +- Do not include Claude attribution or automated generation notices +- Focus on the "why" and "what" of the change, not implementation details + +### Git Workflow + +- Squashing commits is often preferred for complex PRs +- When rebasing, be prepared to resolve conflicts in package.json, eslint.config.js, and build configs +- The babel debug plugin pattern requires `check()` calls to be inline (not inside if blocks) for proper type narrowing + +## Turbo Configuration + +### Script Naming Conventions + +- Use `turbo <task>` directly (without `run`) for consistency +- Common aliases added for better DX: + - `pnpm build` → builds all packages + - `pnpm dev` → starts development server + +### Performance Optimizations + +- Caching enabled for deterministic tasks (lint, test:node, prepack) +- Proper input/output declarations for better cache hits +- Environment variables tracked: NODE_ENV, CI +- TUI enabled for better progress visualization + +### Task Dependencies + +- `prepack` depends on upstream packages (`^prepack`) +- `test:publint` depends on `prepack` to validate built packages +- Type checking depends on all packages being built first diff --git a/glimmer-vm/LICENSE b/glimmer-vm/LICENSE new file mode 100644 index 00000000000..373242e067d --- /dev/null +++ b/glimmer-vm/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2015 Tilde, Inc. + +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/glimmer-vm/README.md b/glimmer-vm/README.md new file mode 100644 index 00000000000..374959fa5cd --- /dev/null +++ b/glimmer-vm/README.md @@ -0,0 +1,92 @@ +# Status [![Build Status](https://travis-ci.org/glimmerjs/glimmer-vm.svg?branch=main)](https://travis-ci.org/glimmerjs/glimmer-vm) + + +Glimmer is a flexible, low-level rendering pipeline for building a "live" DOM +from [Handlebars][handlebars] templates that can subsequently be updated cheaply +when data changes. + +It is written in [TypeScript][typescript]. + +The project is still going through rapid changes at the moment. For the time +being, please refer the [architecture overview][guides] for more information. + +# Building Glimmer + +1. Ensure that [Node.js](http://nodejs.org/) is installed. +2. Run `npm install` or `yarn install` to ensure the required dependencies are installed. +3. Run `npm run build` to build each Glimmer package. The builds will be placed in the `dist/` directory. + +Glimmer's packages are only built when running `npm run build` (or `ember build --env production`). +If you run `ember build` without setting the production environment, `dist/` +will only contain test assets. + +If you want to use the built packages in other projects, you can use `npm run +yarn:link` to execute the `yarn link` command inside each built package. (You +must build the packages first with `npm run build`). + +# How to Run Tests + +## Running all tests + +1. Run `pnpm test` to run all tests. + +## In a browser + +1. Run `pnpm start` to start the Vite dev server. +2. Open your browser and navigate to the provided URL. +3. Use the QUnit interface to filter and run specific tests. + +## Node.js tests + +1. Run `pnpm test:node` to run Node.js tests via Turbo. +2. Visit <http://localhost:7357/tests/>. + +# TypeScript Notes + +## "Friend" Properties and Methods + +In TypeScript, `private` and `protected` refer to the class itself +(and its subclasses). + +Sometimes, you want to add a property or method that shouldn't be +considered part of the external API (for other packages or Ember) +but is expected to be used as part of an internal protocol. + +In that case, it's ok to mark the property as `private` or +`protected` and use `['property']` syntax to access the property +inside of the same package. + +```js +class Layout { + private template: Template; +} + +function compile(layout: Layout, environment: Environment): CompiledBlock { + return layout['template'].compile(environment); +} +``` + +The idea is that the `compile` function might as well be a private method +on the class, but because the function leaks into untyped code, we want +to be more careful and avoid exporting it. + +Other use-cases might include protocols where a cluster of classes is +intended to work together internally, but it's difficult to describe +as a single class hierarchy. + +This is a semi-blessed workflow according to the TypeScript team, and +Visual Studio Code (and tsc) correctly type check uses of indexed +properties, and provide autocompletion, etc. + +**You should not treat use of `['foo']` syntax as license to access +private properties outside of the package.** + +[handlebars]: http://handlebarsjs.com +[typescript]: http://www.typescriptlang.org +[guides]: ./guides/01-introduction.md + + +--- + +Cross-browser testing provided by: + diff --git a/glimmer-vm/RELEASE.md b/glimmer-vm/RELEASE.md new file mode 100644 index 00000000000..941d489f899 --- /dev/null +++ b/glimmer-vm/RELEASE.md @@ -0,0 +1,27 @@ +# Release Process + +Releases in this repo are mostly automated using [release-plan](https://github.com/embroider-build/release-plan/). Once you label all your PRs correctly (see below) you will have an automatically generated PR that updates your CHANGELOG.md file and a `.release-plan.json` that is used to prepare the release once the PR is merged. + +## Preparation + +Since the majority of the actual release process is automated, the remaining tasks before releasing are: + +- correctly labeling **all** pull requests that have been merged since the last release +- updating pull request titles so they make sense to our users + +Some great information on why this is important can be found at [keepachangelog.com](https://keepachangelog.com/en/1.1.0/), but the overall +guiding principle here is that changelogs are for humans, not machines. + +When reviewing merged PR's the labels to be used are: + +- breaking - Used when the PR is considered a breaking change. +- enhancement - Used when the PR adds a new feature or enhancement. +- bug - Used when the PR fixes a bug included in a previous release. +- documentation - Used when the PR adds or updates documentation. +- internal - Internal changes or things that don't fit in any other category. + +**Note:** `release-plan` requires that **all** PRs are labeled. If a PR doesn't fit in a category it's fine to label it as `internal` + +## Release + +Once the prep work is completed, the actual release is straight forward: you just need to merge the open [Plan Release](https://github.com/glimmerjs/glimmer-vm/pulls?q=is%3Apr+is%3Aopen+%22Prepare+Release%22+in%3Atitle) PR diff --git a/glimmer-vm/benchmark/benchmarks/krausest/.gitignore b/glimmer-vm/benchmark/benchmarks/krausest/.gitignore new file mode 100644 index 00000000000..8d12edbe864 --- /dev/null +++ b/glimmer-vm/benchmark/benchmarks/krausest/.gitignore @@ -0,0 +1,2 @@ +packages/ +pnpm-lock.yaml diff --git a/glimmer-vm/benchmark/benchmarks/krausest/browser.js b/glimmer-vm/benchmark/benchmarks/krausest/browser.js new file mode 100644 index 00000000000..06211ad38c5 --- /dev/null +++ b/glimmer-vm/benchmark/benchmarks/krausest/browser.js @@ -0,0 +1,5 @@ +import render from './lib/index'; + +export default async function run() { + await render(document.body, true); +} diff --git a/glimmer-vm/benchmark/benchmarks/krausest/index.html b/glimmer-vm/benchmark/benchmarks/krausest/index.html new file mode 100644 index 00000000000..ff5758d5956 --- /dev/null +++ b/glimmer-vm/benchmark/benchmarks/krausest/index.html @@ -0,0 +1,179 @@ +<!doctype html> +<html> + <head> + <meta charset="UTF-8" /> + <title>krausest benchmark + + + + + diff --git a/glimmer-vm/benchmark/benchmarks/krausest/lib/components/Application.d.hbs.ts b/glimmer-vm/benchmark/benchmarks/krausest/lib/components/Application.d.hbs.ts new file mode 100644 index 00000000000..d0abe3ecb81 --- /dev/null +++ b/glimmer-vm/benchmark/benchmarks/krausest/lib/components/Application.d.hbs.ts @@ -0,0 +1,4 @@ +import type { SerializedTemplateWithLazyBlock } from '@glimmer/interfaces'; + +declare const template: SerializedTemplateWithLazyBlock; +export default template; diff --git a/glimmer-vm/benchmark/benchmarks/krausest/lib/components/Application.hbs b/glimmer-vm/benchmark/benchmarks/krausest/lib/components/Application.hbs new file mode 100644 index 00000000000..ef116217ffd --- /dev/null +++ b/glimmer-vm/benchmark/benchmarks/krausest/lib/components/Application.hbs @@ -0,0 +1,57 @@ +
+
+
+
+

Glimmer-VM

+
+
+
+
+ + Create 1,000 rows + +
+
+ + Create 5,000 rows + +
+
+ + Append 1,000 rows + +
+
+ + Update every 10th row + +
+
+ + Clear + +
+
+ + Swap Rows + +
+
+
+
+
+ + + + {{#each this.items as |item|}} + + {{/each}} + +
+ +
\ No newline at end of file diff --git a/glimmer-vm/benchmark/benchmarks/krausest/lib/components/Application.ts b/glimmer-vm/benchmark/benchmarks/krausest/lib/components/Application.ts new file mode 100644 index 00000000000..19a8078e19b --- /dev/null +++ b/glimmer-vm/benchmark/benchmarks/krausest/lib/components/Application.ts @@ -0,0 +1,58 @@ +import { fn } from '@glimmer/runtime'; +import { createCell } from '@glimmer-workspace/benchmark-env'; + +import type { Item } from '#utils/data.ts'; +import { buildData, swapRows, updateData } from '#utils/data.ts'; + +export default class Application { + cell!: ReturnType; + selectedItemCell!: ReturnType; + constructor() { + this.cell = createCell(this, 'cell', []); + this.selectedItemCell = createCell(this, 'selectedItem', null); + } + fn = fn; + eq = (a: Item | null, b: Item | null) => { + return a === b; + }; + get selectedItem() { + return this.selectedItemCell.get() as Item | null; + } + set selectedItem(value: Item | null) { + this.selectedItemCell.set(value); + } + get items() { + return this.cell.get() as Item[]; + } + set items(value: Item[]) { + this.cell.set(value); + } + select = (item: Item) => { + this.selectedItem = item; + }; + create = () => { + this.items = buildData(1000); + }; + runLots = () => { + this.items = buildData(5000); + }; + add = () => { + this.items = this.items.concat(buildData(1000)); + }; + update = () => { + this.items = updateData(this.items); + }; + clear = () => { + this.items = []; + this.selectedItem = null; + }; + swapRows = () => { + this.items = swapRows(this.items); + }; + remove = (item: Item) => { + this.items = this.items.filter((el) => el !== item); + if (this.selectedItem === item) { + this.selectedItem = null; + } + }; +} diff --git a/glimmer-vm/benchmark/benchmarks/krausest/lib/components/BsButton.d.hbs.ts b/glimmer-vm/benchmark/benchmarks/krausest/lib/components/BsButton.d.hbs.ts new file mode 100644 index 00000000000..d0abe3ecb81 --- /dev/null +++ b/glimmer-vm/benchmark/benchmarks/krausest/lib/components/BsButton.d.hbs.ts @@ -0,0 +1,4 @@ +import type { SerializedTemplateWithLazyBlock } from '@glimmer/interfaces'; + +declare const template: SerializedTemplateWithLazyBlock; +export default template; diff --git a/glimmer-vm/benchmark/benchmarks/krausest/lib/components/BsButton.hbs b/glimmer-vm/benchmark/benchmarks/krausest/lib/components/BsButton.hbs new file mode 100644 index 00000000000..19170b8fc2d --- /dev/null +++ b/glimmer-vm/benchmark/benchmarks/krausest/lib/components/BsButton.hbs @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/glimmer-vm/benchmark/benchmarks/krausest/lib/components/Row.d.hbs.ts b/glimmer-vm/benchmark/benchmarks/krausest/lib/components/Row.d.hbs.ts new file mode 100644 index 00000000000..d0abe3ecb81 --- /dev/null +++ b/glimmer-vm/benchmark/benchmarks/krausest/lib/components/Row.d.hbs.ts @@ -0,0 +1,4 @@ +import type { SerializedTemplateWithLazyBlock } from '@glimmer/interfaces'; + +declare const template: SerializedTemplateWithLazyBlock; +export default template; diff --git a/glimmer-vm/benchmark/benchmarks/krausest/lib/components/Row.hbs b/glimmer-vm/benchmark/benchmarks/krausest/lib/components/Row.hbs new file mode 100644 index 00000000000..83317551cc7 --- /dev/null +++ b/glimmer-vm/benchmark/benchmarks/krausest/lib/components/Row.hbs @@ -0,0 +1,10 @@ + + {{@item.id}} +
{{@item.label}} + + + + + + + \ No newline at end of file diff --git a/glimmer-vm/benchmark/benchmarks/krausest/lib/components/Row.ts b/glimmer-vm/benchmark/benchmarks/krausest/lib/components/Row.ts new file mode 100644 index 00000000000..ab42ffc763e --- /dev/null +++ b/glimmer-vm/benchmark/benchmarks/krausest/lib/components/Row.ts @@ -0,0 +1,20 @@ +import type { Item } from '#utils/data.ts'; + +type RowArgs = { + item: Item; + select: () => void; + remove: (item: Item) => void; +}; + +export default class Row { + args!: RowArgs; + constructor(args: RowArgs) { + this.args = args; + } + onRemove = () => { + this.args.remove(this.args.item); + }; + onSelect = () => { + this.args.select(); + }; +} diff --git a/glimmer-vm/benchmark/benchmarks/krausest/lib/index.ts b/glimmer-vm/benchmark/benchmarks/krausest/lib/index.ts new file mode 100644 index 00000000000..02af607f3bb --- /dev/null +++ b/glimmer-vm/benchmark/benchmarks/krausest/lib/index.ts @@ -0,0 +1,150 @@ +import { createBenchmark } from '@glimmer-workspace/benchmark-env'; + +import ApplicationTemplate from '#components/Application.hbs'; +import Application from '#components/Application.ts'; +import ButtonTemplate from '#components/BsButton.hbs'; +import RowTemplate from '#components/Row.hbs'; +import Row from '#components/Row.ts'; +import { + ButtonSelectors, + emitDomClickEvent, + enforcePaintEvent, + waitForIdle, +} from '#utils/compat.ts'; + +export default async function render(element: HTMLElement, isInteractive: boolean) { + const benchmark = createBenchmark(); + + benchmark.templateOnlyComponent('BsButton', ButtonTemplate); + benchmark.basicComponent('Row', RowTemplate, Row); + benchmark.basicComponent('Application', ApplicationTemplate, Application); + + // starting app + + await waitForIdle(); + + const app = await benchmark.render('Application', {}, element, isInteractive); + + await waitForIdle(); + + await app('render1000Items1', () => { + emitDomClickEvent(ButtonSelectors.Create1000); + }); + + await waitForIdle(); + + await app('clearItems1', () => { + emitDomClickEvent(ButtonSelectors.Clear); + }); + + await waitForIdle(); + + await app('render1000Items2', () => { + emitDomClickEvent(ButtonSelectors.Create1000); + }); + + await waitForIdle(); + + await app('clearItems2', () => { + emitDomClickEvent(ButtonSelectors.Clear); + }); + + await waitForIdle(); + + await app('render5000Items1', () => { + emitDomClickEvent(ButtonSelectors.Create5000); + }); + + await waitForIdle(); + + await app('clearManyItems1', () => { + emitDomClickEvent(ButtonSelectors.Clear); + }); + + await waitForIdle(); + + await app('render5000Items2', () => { + emitDomClickEvent(ButtonSelectors.Create5000); + }); + + await waitForIdle(); + + await app('clearManyItems2', () => { + emitDomClickEvent(ButtonSelectors.Clear); + }); + + await waitForIdle(); + + await app('render1000Items3', () => { + emitDomClickEvent(ButtonSelectors.Create1000); + }); + + await waitForIdle(); + + await app('append1000Items1', () => { + emitDomClickEvent(ButtonSelectors.Append1000); + }); + + await waitForIdle(); + + await app('append1000Items2', () => { + emitDomClickEvent(ButtonSelectors.Append1000); + }); + + await waitForIdle(); + + await app('updateEvery10thItem1', () => { + emitDomClickEvent(ButtonSelectors.UpdateEvery10th); + }); + + await waitForIdle(); + + await app('updateEvery10thItem2', () => { + emitDomClickEvent(ButtonSelectors.UpdateEvery10th); + }); + + await waitForIdle(); + + await app('selectFirstRow1', () => { + emitDomClickEvent(ButtonSelectors.SelectFirstRow); + }); + + await waitForIdle(); + + await app('selectSecondRow1', () => { + emitDomClickEvent(ButtonSelectors.SelectSecondRow); + }); + + await waitForIdle(); + + await app('removeFirstRow1', () => { + emitDomClickEvent(ButtonSelectors.RemoveFirstRow); + }); + + await waitForIdle(); + + await app('removeSecondRow1', () => { + emitDomClickEvent(ButtonSelectors.RemoveSecondRow); + }); + + await waitForIdle(); + + await app('swapRows1', () => { + emitDomClickEvent(ButtonSelectors.SwapRows); + }); + + await waitForIdle(); + + await app('swapRows2', () => { + emitDomClickEvent(ButtonSelectors.SwapRows); + }); + + await waitForIdle(); + + await app('clearItems4', () => { + emitDomClickEvent(ButtonSelectors.Clear); + }); + + // finishing bench + enforcePaintEvent(); +} diff --git a/glimmer-vm/benchmark/benchmarks/krausest/lib/utils/compat.ts b/glimmer-vm/benchmark/benchmarks/krausest/lib/utils/compat.ts new file mode 100644 index 00000000000..a58656769fb --- /dev/null +++ b/glimmer-vm/benchmark/benchmarks/krausest/lib/utils/compat.ts @@ -0,0 +1,54 @@ +export enum ButtonSelectors { + Create1000 = '#run', + Create5000 = '#runlots', + Append1000 = '#add', + UpdateEvery10th = '#update', + SelectFirstRow = 'tr:nth-child(1) a[data-test-select]', + SelectSecondRow = 'tr:nth-child(2) a[data-test-select]', + RemoveFirstRow = 'tr:nth-child(1) a[data-test-remove]', + RemoveSecondRow = 'tr:nth-child(2) a[data-test-remove]', + Clear = '#clear', + SwapRows = '#swaprows', +} + +export function emitDomClickEvent(selector: ButtonSelectors) { + const button = document.querySelector(selector); + if (button) { + button.dispatchEvent( + new MouseEvent('click', { + bubbles: true, + cancelable: true, + view: window, + }) + ); + } else { + throw new Error(`Could not find element with selector ${selector}`); + } +} + +export function waitForIdle() { + return new Promise((resolve) => { + requestIdleCallback(resolve); + }); +} + +export function enforcePaintEvent() { + const docElem = document.documentElement; + const refNode = docElem.firstElementChild || docElem.firstChild; + const fakeBody = document.createElement('body'); + const div = document.createElement('div'); + + div.id = 'mq-test-1'; + div.style.cssText = 'position:absolute;top:-100em'; + fakeBody.style.background = 'none'; + fakeBody.appendChild(div); + div.innerHTML = '­'; + docElem.insertBefore(fakeBody, refNode); + + try { + return div.offsetWidth === 42; + } finally { + fakeBody.removeChild(div); + docElem.removeChild(fakeBody); + } +} diff --git a/glimmer-vm/benchmark/benchmarks/krausest/lib/utils/data.ts b/glimmer-vm/benchmark/benchmarks/krausest/lib/utils/data.ts new file mode 100644 index 00000000000..3a4483c50b9 --- /dev/null +++ b/glimmer-vm/benchmark/benchmarks/krausest/lib/utils/data.ts @@ -0,0 +1,116 @@ +/* eslint-disable @typescript-eslint/restrict-plus-operands */ +import { createCell } from '@glimmer-workspace/benchmark-env'; + +export class Item { + /** @type {number} */ + id; + + /** @type {string} */ + _label = createCell(this, 'label', ''); + + constructor(id: number, label: string) { + this.id = id; + this.label = label; + } + get label() { + return this._label.get(); + } + set label(value: string) { + this._label.set(value); + } +} + +function _random(max: number) { + return (Math.random() * max) | 0; +} + +let rowId = 1; + +export function buildData(count = 1000) { + const adjectives = [ + 'pretty', + 'large', + 'big', + 'small', + 'tall', + 'short', + 'long', + 'handsome', + 'plain', + 'quaint', + 'clean', + 'elegant', + 'easy', + 'angry', + 'crazy', + 'helpful', + 'mushy', + 'odd', + 'unsightly', + 'adorable', + 'important', + 'inexpensive', + 'cheap', + 'expensive', + 'fancy', + ], + colours = [ + 'red', + 'yellow', + 'blue', + 'green', + 'pink', + 'brown', + 'purple', + 'brown', + 'white', + 'black', + 'orange', + ], + nouns = [ + 'table', + 'chair', + 'house', + 'bbq', + 'desk', + 'car', + 'pony', + 'cookie', + 'sandwich', + 'burger', + 'pizza', + 'mouse', + 'keyboard', + ], + data = []; + for (let i = 0; i < count; i++) + data.push( + new Item( + rowId++, + adjectives[_random(adjectives.length)] + + ' ' + + colours[_random(colours.length)] + + ' ' + + nouns[_random(nouns.length)] + ) + ); + return data; +} + +export const swapRows = (data: Item[]): Item[] => { + const newData: Item[] = [...data]; + if (newData.length > 998) { + const temp = newData[1]; + newData[1] = newData[998] as Item; + newData[998] = temp as Item; + } + return newData; +}; + +export const updateData = (data: Item[], mod = 10): Item[] => { + for (let i = 0; i < data.length; i += mod) { + let item = data[i] as Item; + item.label = item.label + ' !!!'; + } + return data; +}; diff --git a/glimmer-vm/benchmark/benchmarks/krausest/package.json b/glimmer-vm/benchmark/benchmarks/krausest/package.json new file mode 100644 index 00000000000..9c70d30501f --- /dev/null +++ b/glimmer-vm/benchmark/benchmarks/krausest/package.json @@ -0,0 +1,49 @@ +{ + "private": true, + "name": "@glimmer-workspace/krausest", + "type": "module", + "imports": { + "#*": "./lib/*" + }, + "scripts": { + "start": "vite --mode production", + "test:lint": "eslint . --quiet" + }, + "dependencies": { + "@glimmer-workspace/benchmark-env": "file:packages/@glimmer-workspace/benchmark-env.tgz", + "@glimmer/compiler": "file:packages/@glimmer/compiler.tgz", + "@glimmer/interfaces": "file:packages/@glimmer/interfaces.tgz", + "@glimmer/runtime": "file:packages/@glimmer/runtime.tgz", + "@simple-dom/document": "^1.4.0", + "@simple-dom/serializer": "^1.4.0", + "@simple-dom/void-map": "^1.4.0" + }, + "devDependencies": { + "@types/node": "^20.9.4", + "eslint": "^9.18.0", + "type-fest": "^4.32.0", + "vite": "^5.4.10" + }, + "engines": { + "node": ">=18.0.0" + }, + "config": { + "tsconfig": "../../tsconfig.json" + }, + "pnpm": { + "overrides": { + "@glimmer-workspace/build-support": "file:packages/@glimmer-workspace/build-support.tgz", + "@glimmer/debug-util": "file:packages/@glimmer/debug-util.tgz", + "@glimmer/global-context": "file:packages/@glimmer/global-context.tgz", + "@glimmer/manager": "file:packages/@glimmer/manager.tgz", + "@glimmer/opcode-compiler": "file:packages/@glimmer/opcode-compiler.tgz", + "@glimmer/program": "file:packages/@glimmer/program.tgz", + "@glimmer/reference": "file:packages/@glimmer/reference.tgz", + "@glimmer/syntax": "file:packages/@glimmer/syntax.tgz", + "@glimmer/util": "file:packages/@glimmer/util.tgz", + "@glimmer/validator": "file:packages/@glimmer/validator.tgz", + "@glimmer/wire-format": "file:packages/@glimmer/wire-format.tgz", + "@glimmer-workspace/env": "file:packages/@glimmer-workspace/env.tgz" + } + } +} diff --git a/glimmer-vm/benchmark/benchmarks/krausest/vite.config.mts b/glimmer-vm/benchmark/benchmarks/krausest/vite.config.mts new file mode 100644 index 00000000000..d886422f522 --- /dev/null +++ b/glimmer-vm/benchmark/benchmarks/krausest/vite.config.mts @@ -0,0 +1,69 @@ +import fs from 'node:fs'; + +import { precompile } from '@glimmer/compiler'; +import { defineConfig, type Plugin } from 'vite'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; + +const self = import.meta.url; + +const currentPath = path.dirname(fileURLToPath(self)); +const packagesPath = path.resolve(currentPath, '..', '..', './../packages'); + +const packagePath = (name: string) => { + return path.join(packagesPath, name, 'dist/prod/index.js'); +}; + +export default defineConfig({ + plugins: [importMeta(), benchmark()], + preview: { + strictPort: true, + }, + resolve: { + alias: { + // This shouldn't be necessary, but the current `main` doesn't have properly + // set up `package.json` files, so the built package isn't properly resolved. + '@glimmer/compiler': packagePath('@glimmer/compiler'), + '#components': path.join(currentPath, 'lib', 'components'), + '#utils': path.join(currentPath, 'lib', 'utils'), + }, + }, +}); + +function importMeta(): Plugin { + return { + name: 'define custom import.meta.env', + async transform(code) { + if (code.includes('import.meta.env.VM_LOCAL_DEV')) { + return code.replace(/import.meta.env.VM_LOCAL_DEV/g, 'false'); + } + return undefined; + }, + enforce: 'pre', + }; +} + +function benchmark(): Plugin { + return { + enforce: 'pre', + name: '@glimmer/benchmark', + resolveId(id) { + if (id === '@glimmer/env') { + return '\0@glimmer/env'; + } + }, + load(id) { + if (id === '\0@glimmer/env') { + return `export const DEBUG = false;`; + } + /** @type {string | undefined} */ + let result: string | undefined; + if (id.endsWith('.hbs')) { + const source = fs.readFileSync(id, 'utf8'); + const compiled = precompile(source); + result = `export default ${compiled};`; + } + return result; + }, + }; +} diff --git a/glimmer-vm/bin/bench-packages.mts b/glimmer-vm/bin/bench-packages.mts new file mode 100644 index 00000000000..fd32c3e9b75 --- /dev/null +++ b/glimmer-vm/bin/bench-packages.mts @@ -0,0 +1,228 @@ +import { join, relative, resolve } from 'node:path'; + +import type { Project } from '@pnpm/workspace.find-packages'; +import type { PackageJson } from 'type-fest'; +import { findWorkspacePackagesNoCheck } from '@pnpm/workspace.find-packages'; +import chalk from 'chalk'; +import { $ } from 'execa'; +import fs from 'fs-extra'; +import pMap from 'p-map'; + +const { writeFile } = fs; + +interface Roots { + /** + * The target directory containing the `krausest` benchmark that will get the build packages. + */ + benchmark: string; + /** + * The workspace containing the packages that will be built. + */ + workspace: string; +} + +/** + * Build the dependencies of the `krausest` benchmark, put them into the (gitignored) `packages/` + * directory, and update the `package.json` to point to them if necessary. + * + * @param format Whether to run `eslint --fix` and `prettier --write` on the manifest. + */ +export async function buildKrausestDeps({ + roots, + format = false, +}: { + roots: Roots; + format?: boolean | undefined; +}) { + const packages = await findWorkspacePackagesNoCheck(roots.workspace); + + const benchEnvPkg = getPkg(packages, '@glimmer-workspace/benchmark-env'); + const benchEnvManifest = await getManifest(roots, benchEnvPkg.rootDir); + + const krausestManifest = await getManifest(roots, roots.benchmark); + + const benchEnvDeps = neededDeps(packages, benchEnvManifest); + const krausestDeps = neededDeps(packages, krausestManifest); + + await buildPkg(roots, benchEnvPkg); + + const allDeps = new Set([...benchEnvDeps, ...krausestDeps]); + + const built = await pMap( + [...allDeps], + async (pkg) => { + return await buildPkg(roots, pkg); + }, + { concurrency: 1 } + ); + + // const built: { name: string; filename: string }[] = []; + // for (const pkg of allDeps) { + // built.push(await buildPkg(roots, pkg)); + // } + + // const built = await Promise.all([...allDeps].map((pkg) => buildPkg(roots, pkg))); + + { + const deps = krausestManifest.dependencies ?? {}; + krausestManifest.dependencies = deps; + const devDeps = krausestManifest.devDependencies ?? {}; + krausestManifest.devDependencies = devDeps; + const overrides = krausestManifest.pnpm?.overrides ?? {}; + krausestManifest.pnpm ??= {}; + krausestManifest.pnpm.overrides = overrides; + + for (const pkg of built) { + const filename = `file:${pkg.filename}`; + + // eslint-disable-next-line @typescript-eslint/no-unused-expressions + update(pkg.name, ['dependencies', deps], filename) || + update(pkg.name, ['devDependencies', devDeps], filename) || + update(pkg.name, ['pnpm.overrides', overrides], filename, { fallback: true }); + } + + /** + * Remove any leftover overrides for packages that no longer exist. Since the overrides are + * added to the package.json file based on transitive dependencies, it's possible that a + * previous run of `buildKrausestDeps` added a transitive override that is no longer used by any + * direct dependencies of the `krausest` benchmark package. + */ + for (const [name, value] of Object.entries(overrides)) { + if (isNeededDep(value) && !allDeps.has(getPkg(packages, name))) { + console.log( + `${chalk.red('[-]')} ${chalk.strikethrough(name)} ${chalk.gray('from')} ${'pnpm.overrides'.padEnd(MAX_PAD)}` + ); + + delete overrides[name]; + } + } + + await writeManifest(roots, join(roots.benchmark, 'package.json'), krausestManifest, format); + } +} + +type PnpmPackageJson = PackageJson & { + pnpm?: { + overrides?: Record; + }; +}; + +async function getManifest(roots: Roots, path: string): Promise { + const { default: manifest }: { default: PnpmPackageJson } = await import( + path.startsWith('.') + ? resolve(`${roots.workspace}`, path, 'package.json') + : resolve(path, 'package.json'), + { with: { type: 'json' } } + ); + + return manifest; +} + +async function writeManifest( + roots: Roots, + path: string, + manifest: PnpmPackageJson, + format: boolean +) { + await writeFile(path, JSON.stringify(manifest, null, 2)); + + if (format) { + await $({ cwd: roots.workspace })`eslint --fix ${path}`; + await $({ cwd: roots.workspace })`prettier --write ${path}`; + } +} + +function getPkg(packages: Project[], name: string): Project { + const pkg = packages.find((pkg) => pkg.manifest.name === name); + + if (!pkg) { + throw new Error(`Could not find package ${name}`); + } + + return pkg; +} + +function neededDeps(packages: Project[], manifest: PnpmPackageJson): Project[] { + const allDeps = { + ...manifest.dependencies, + ...manifest.devDependencies, + ...manifest.pnpm?.overrides, + }; + + const workspaceDeps = Object.entries(allDeps) + .flatMap(([name, value]) => (value && isNeededDep(value) ? [name] : [])) + .flatMap((name) => packages.find((pkg) => pkg.manifest.name === name)!); + + return workspaceDeps; +} + +function isNeededDep(version: string) { + return version.startsWith('workspace:') || version.startsWith('file:'); +} + +const MAX_PAD = 'devDependencies'.length; + +function update( + pkg: string, + location: [name: string, container: Partial>], + to: string, + options?: { fallback: true } +) { + const [containerName, container] = location; + + if (pkg in container) { + if (container[pkg] !== to) { + console.log( + `${chalk.yellow('[~]')} ${chalk.cyan(pkg)} ${containerName.padEnd(MAX_PAD)} ${chalk.gray('from')} ${chalk.red.strikethrough(container[pkg])} ${chalk.gray('->')} ${chalk.green(to)}` + ); + container[pkg] = to; + } + + return true; + } else if (options?.fallback) { + console.log( + `${chalk.green('[+]')} ${chalk.cyan(pkg)} ${containerName.padEnd(MAX_PAD)} ${chalk.gray('as')} ${chalk.green(to)}` + ); + + container[pkg] = to; + + return true; + } + + return false; +} + +async function buildPkg(roots: Roots, pkg: Project): Promise<{ name: string; filename: string }> { + if (!pkg.manifest.name) { + throw new Error(`Package at ${pkg.rootDir} has no name`); + } + + const packagesDest = join(roots.benchmark, 'packages'); + const dest = join(packagesDest, `${pkg.manifest.name}.tgz`); + + const result = await $({ + stdio: 'pipe', + verbose: true, + })`pnpm -C ${pkg.rootDir} pack --out ${dest}`; + + if (result.failed) { + console.error(`Failed to build ${pkg.manifest.name}`); + throw new Error(result.stderr); + } + + return { name: pkg.manifest.name, filename: relative(roots.benchmark, dest) }; +} + +if (process.argv[1] === import.meta.filename) { + const { BENCHMARK_ROOT, WORKSPACE_ROOT } = await import('@glimmer-workspace/repo-metadata'); + + await buildKrausestDeps({ + roots: { benchmark: BENCHMARK_ROOT, workspace: WORKSPACE_ROOT }, + format: true, + }); + await $({ + cwd: BENCHMARK_ROOT, + verbose: true, + env: { CI: 'false' }, + })`pnpm install --ignore-workspace --no-lockfile`; +} diff --git a/glimmer-vm/bin/clean.mjs b/glimmer-vm/bin/clean.mjs new file mode 100644 index 00000000000..8f4467d1cf0 --- /dev/null +++ b/glimmer-vm/bin/clean.mjs @@ -0,0 +1,11 @@ +import { join } from 'node:path'; + +import repo, { isRoot } from '@glimmer-workspace/repo-metadata'; +import { rimraf } from 'rimraf'; + +for (const pkg of repo.packages) { + if (isRoot(pkg)) continue; + await rimraf(join(pkg.root, 'dist')); +} + +// await rimraf('**/{dist,.turbo,node_modules}/', { glob: true }); diff --git a/glimmer-vm/bin/codemods/devmode.toml b/glimmer-vm/bin/codemods/devmode.toml new file mode 100644 index 00000000000..6a55621c2c6 --- /dev/null +++ b/glimmer-vm/bin/codemods/devmode.toml @@ -0,0 +1,7 @@ +[devmode] +match = "devmode({ :[block] })" +rewrite = "devmode(() => ({ :[block] }))" + +[devmode2] +match = "if (import.meta.env.DEV) { :[[name]].description = :[description]; }" +rewrite = "setDescription(:[name], devmode(() => :[description]));" diff --git a/glimmer-vm/bin/codemods/new-spec-suite.toml b/glimmer-vm/bin/codemods/new-spec-suite.toml new file mode 100644 index 00000000000..ef577e8b8d5 --- /dev/null +++ b/glimmer-vm/bin/codemods/new-spec-suite.toml @@ -0,0 +1,21 @@ +[test] +match = """ +export class :[class] extends :[extends] { + static suiteName = :[suite]; + :[block] +} +""" +rewrite = """ +import { matrix } from "@glimmer-workspace/integration-tests"; +matrix(:[suite], (spec) => { :[block] }).client(); +""" +rule = """ +where +rewrite :[block] { "this" -> "ctx" }, +rewrite :[block] { + "@render(:[type]) :[string]() { :[body] }" -> "spec({ type: :[type] }, :[string], (ctx) => { :[body] })" +}, +rewrite :[block] { + "@render :[string]() { :[body] }" -> "spec(:[string], (ctx) => { :[body] })" +} +""" diff --git a/glimmer-vm/bin/opcodes.json b/glimmer-vm/bin/opcodes.json new file mode 100644 index 00000000000..97c737d4b1e --- /dev/null +++ b/glimmer-vm/bin/opcodes.json @@ -0,0 +1,112 @@ +{ + "$schema": "./opcodes/opcodes.schema.json", + "outputs": { + "interface": "@glimmer/interfaces/lib/generated/vm-opcodes.d.ts", + "code": "@glimmer/vm/lib/generated/opcodes.ts", + "debug": "@glimmer/debug/lib/generated/op-list.ts" + }, + "machine": ["PushFrame", "PopFrame", "Jump", "ReturnTo", "UnwindTypeFrame"], + "syscall": [ + "PushBegin", + "Begin", + "Catch", + "Finally", + "InvokeVirtual", + "InvokeStatic", + "Start", + "Return", + "Helper", + "SetNamedVariables", + "SetBlocks", + "SetVariable", + "SetBlock", + "GetVariable", + "GetProperty", + "GetBlock", + "SpreadBlock", + "HasBlock", + "HasBlockParams", + "Concat", + "Constant", + "ConstantReference", + "Primitive", + "PrimitiveReference", + "ReifyU32", + "Dup", + "Pop", + "Load", + "Fetch", + "RootScope", + "VirtualRootScope", + "ChildScope", + "PopScope", + "Text", + "Comment", + "AppendHTML", + "AppendSafeHTML", + "AppendDocumentFragment", + "AppendNode", + "AppendText", + "OpenElement", + "OpenDynamicElement", + "PushRemoteElement", + "StaticAttr", + "DynamicAttr", + "ComponentAttr", + "FlushElement", + "CloseElement", + "PopRemoteElement", + "Modifier", + "BindDynamicScope", + "PushDynamicScope", + "PopDynamicScope", + "CompileBlock", + "PushBlockScope", + "PushSymbolTable", + "InvokeYield", + "JumpIf", + "JumpUnless", + "JumpEq", + "AssertSame", + "Enter", + "Exit", + "ToBoolean", + "EnterList", + "ExitList", + "Iterate", + "Main", + "ContentType", + "Curry", + "PushComponentDefinition", + "PushDynamicComponentInstance", + "ResolveDynamicComponent", + "ResolveCurriedComponent", + "PushArgs", + "PushEmptyArgs", + "PrepareArgs", + "CaptureArgs", + "CreateComponent", + "RegisterComponentDestructor", + "PutComponentOperations", + "GetComponentSelf", + "GetComponentTagName", + "GetComponentLayout", + "SetupForDebug", + "PopulateLayout", + "InvokeComponentLayout", + "BeginComponentTransaction", + "CommitComponentTransaction", + "DidCreateElement", + "DidRenderLayout", + "Debugger", + "StaticComponentAttr", + "DynamicContentType", + "DynamicHelper", + "DynamicModifier", + "IfInline", + "Not", + "GetDynamicVar", + "Log", + "PushUnwindTarget" + ] +} diff --git a/glimmer-vm/bin/opcodes.mts b/glimmer-vm/bin/opcodes.mts new file mode 100644 index 00000000000..cf37215f5ea --- /dev/null +++ b/glimmer-vm/bin/opcodes.mts @@ -0,0 +1,131 @@ +/* eslint-disable n/no-process-exit */ +import chalk from 'chalk'; + +import { Emitter } from './opcodes/utils.mjs'; + +const emitter = Emitter.argv('opcodes.json', import.meta); + +const { machine, system } = emitter.opcodes; + +const ALL: (string | null)[] = [ + ...machine, + ...new Array(16 - machine.length).fill(null), + ...system, +]; + +const TYPES = ['interface', 'code', 'debug', 'all'] as const; + +if (emitter.options.help) { + usage(); +} + +if (emitter.type === undefined) { + usage('Missing type'); +} + +compute(emitter.type); + +function compute(type: string) { + switch (type) { + case 'interface': { + const members = Object.fromEntries( + ALL.flatMap((name, i) => { + if (name === null) return []; + return [[name, i]]; + }) + ); + + const INTERFACE_MEMBERS = ALL.flatMap((name, i) => { + if (name === null) return []; + return [` ${name}: ${i};`]; + }).join('\n'); + + emitter.writeTarget('interface')([ + `export interface VmOpMap {\n${INTERFACE_MEMBERS}\n}`, + '', + `export type VmMachineOp =`, + ...machine.flatMap((m) => [`// ${m}`, `| ${members[m]}`]), + '', + `export type VmSyscallOp =`, + ...system.flatMap((m) => [`// ${m}`, `| ${members[m]}`]), + '', + `export type OpSize = ${ALL.length};`, + ]); + break; + } + + case 'code': { + const CODE_MEMBERS = ALL.flatMap((name, i) => { + if (name === null) return []; + return [` ${name}: ${i},`]; + }).join('\n'); + + emitter.writeTarget('code')([ + `export interface Op {\n${CODE_MEMBERS}\n}`, + '', + `export const Op: Op = {\n${CODE_MEMBERS}\n};`, + '', + `export const OpSize = ${ALL.length} as const;`, + ]); + break; + } + + case 'debug': { + emitter.writeTarget('debug')([ + `import type { VmOpMap } from "${emitter.imports.interface}";`, + '', + `export const DebugOpList = ${JSON.stringify( + ALL + )} as const satisfies { [P in keyof VmOpMap as VmOpMap[P]]: P };`, + '', + `export type DebugOpList = ${JSON.stringify(ALL)}`, + ]); + break; + } + + case 'all': + compute('code'); + compute('interface'); + compute('debug'); + break; + + default: + usage(`Invalid type ${chalk.cyan(type)}`); + } +} + +function usage(error?: string): never { + emitter.human(chalk.cyan.inverse('Usage:'), chalk.cyan('node opcodes.mts [target]')); + emitter.newline(); + emitter.human( + chalk.yellow(` `), + chalk.grey.inverse('one of'), + chalk.cyanBright(TYPES.join(', ')) + ); + emitter.human( + chalk.yellow(`[target] `), + chalk.grey(`Output path or '-' (defaults to target in opcodes.json).`) + ); + emitter.newline(); + emitter.human(chalk.yellowBright.inverse('NOTE')); + emitter.human( + chalk.yellow( + `targets in ${chalk.cyan(`opcodes.json`)} are ${chalk.magentaBright( + 'relative to the packages directory' + )}.` + ) + ); + emitter.human( + chalk.yellow( + `targets ${chalk.cyan('specified on the command-line')} are ${chalk.magentaBright( + 'relative to the workspace root' + )}.` + ) + ); + + if (error) { + emitter.newline(); + emitter.human(chalk.red.inverse('ERROR'), chalk.red(error)); + } + process.exit(error ? 1 : 0); +} diff --git a/glimmer-vm/bin/opcodes/opcodes.schema.json b/glimmer-vm/bin/opcodes/opcodes.schema.json new file mode 100644 index 00000000000..c9a8a78bdfb --- /dev/null +++ b/glimmer-vm/bin/opcodes/opcodes.schema.json @@ -0,0 +1,30 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "required": ["outputs", "machine", "syscall"], + "additionalProperties": false, + "properties": { + "$schema": { + "type": "string", + "format": "path" + }, + "outputs": { + "type": "object", + "additionalProperties": false, + "properties": { + "interface": { "type": "string" }, + "code": { "type": "string" }, + "debug": { "type": "string" } + }, + "required": ["interface", "code", "debug"] + }, + "machine": { + "type": "array", + "items": { "type": "string" } + }, + "syscall": { + "type": "array", + "items": { "type": "string" } + } + } +} diff --git a/glimmer-vm/bin/opcodes/utils.mts b/glimmer-vm/bin/opcodes/utils.mts new file mode 100644 index 00000000000..d272929f1d1 --- /dev/null +++ b/glimmer-vm/bin/opcodes/utils.mts @@ -0,0 +1,225 @@ +import { existsSync, readFileSync, writeFileSync } from 'node:fs'; +import { dirname, relative, resolve } from 'node:path'; +import chalk from 'chalk'; +import { spawnSync } from 'node:child_process'; + +const MISSING_INDEX = -1; +const REMOVE = 1; + +interface OpcodesJson { + outputs: { + code: string; + interface: string; + debug: string; + }; + machine: string[]; + syscall: string[]; +} + +interface Paths { + config: string; + root: string; + packages: string; +} + +interface Options { + verbose: boolean; + dryRun: boolean; + help: boolean; +} + +type Target = keyof OpcodesJson['outputs']; + +export class Emitter { + static argv(config: string, here: ImportMeta) { + const __dirname = new URL('.', here.url).pathname; + const configPath = resolve(__dirname, config); + const json = JSON.parse(readFileSync(configPath, 'utf-8')); + + const root = dirname(__dirname); + const packages = resolve(root, 'packages'); + const ARGV = [...process.argv.slice(2)]; + + const verbose = extractFlag(ARGV, '--verbose') || extractFlag(ARGV, '-v'); + const dryRun = extractFlag(ARGV, '--dry-run') || extractFlag(ARGV, '-d'); + const help = extractFlag(ARGV, '--help') || extractFlag(ARGV, '-h'); + + return new Emitter(json, { root, packages, config: configPath }, ARGV, { + verbose, + dryRun, + help, + }); + } + + readonly #json: OpcodesJson; + readonly #paths: Paths; + readonly #args: string[]; + readonly #options: Options; + + constructor(json: OpcodesJson, paths: Paths, args: string[], options: Options) { + this.#json = json; + this.#paths = paths; + this.#args = args; + this.#options = options; + } + + get type(): string | undefined { + return this.#args[0]; + } + + get target(): string | undefined { + return this.#args[1]; + } + + get options(): Options { + return this.#options; + } + + get opcodes(): { machine: string[]; system: string[] } { + return { + machine: this.#json.machine, + system: this.#json.syscall, + }; + } + + writeTarget(name: Target): (code: string[]) => void { + return (code) => { + this.write(code, this.#resolvePath(name)); + }; + } + + newline(): void { + this.human(''); + } + + #resolvePath(name: Target) { + switch (this.target) { + case '-': + return '-'; + case undefined: + return resolve(this.#paths.packages, this.#json.outputs[name]); + default: + return resolve(this.#paths.root, this.target); + } + } + + write(code: string[], path: string) { + const outputString = [ + `// This code was generated by $root/bin/opcodes.mts.`, + `// Do not change it manually.`, + '', + ...code, + ].join('\n'); + + const dir = dirname(path); + + if (!existsSync(dir)) { + this.human(`Directory ${chalk.cyan(dir)} does not exist.`); + process.exit(1); + } + + const result = spawnSync(`pnpm`, ['prettier', '--parser', 'typescript'], { + cwd: this.#paths.root, + input: outputString, + stdio: ['pipe', 'pipe', 'inherit'], + encoding: 'utf-8', + }); + + const { stdout: formatted } = result; + + if (formatted === null) { + this.human( + chalk.red.inverse('ERROR'), + 'running', + `pnpm prettier --parser typescript`, + 'at', + chalk.cyan(this.#paths.root) + ); + this.newline(); + this.human(chalk.yellow.inverse('STDIN')); + this.logOutput(outputString); + this.newline(); + process.exit(1); + } + + if (this.#options.dryRun) { + this.human( + chalk.cyan.inverse('[DRY RUN]'), + chalk.grey(`Writing ${chalk.cyan(relative(this.#paths.root, path))}...`) + ); + } + + if (path === '-') { + this.emit(formatted); + return; + } else if (this.#options.dryRun) { + this.logOutput(formatted); + this.newline(); + return; + } + + this.human(chalk.grey(`Writing ${chalk.cyan(path)}...`)); + writeFileSync(path, formatted); + + if (this.#options.verbose) { + const written = readFileSync(path, 'utf-8'); + this.human(''); + this.human(chalk.bgGrey('Output:')); + this.logOutput(written); + this.newline(); + } + } + + logOutput(output: string) { + this.human(''); + for (const line of output.split('\n')) { + this.human(`${chalk.grey('|')} ${chalk.green.dim(line)}`); + } + } + + get imports(): { code: string; interface: string; debug: string } { + return { + code: this.#extractImport('code'), + interface: this.#extractImport('interface'), + debug: this.#extractImport('debug'), + }; + } + + #extractImport(type: Target): string { + const match = /^@glimmer\/[^/]*/.exec(this.#json.outputs[type])?.[0]; + + if (!match) { + this.human(`Invalid output.${type} in opcodes.json: ${chalk.cyan(this.#paths.config)}`); + this.human(chalk.yellow(`Output files must be nested in '@glimmer/*' packages`)); + process.exit(1); + } + + return match; + } + + /** + * Anything intended to be piped should be sent to `stdout`. + */ + emit(...args: unknown[]) { + console.log(...args); + } + + /** + * Anything that isn't intended to be piped should be sent to `stderr` (really + * should be called `stdlog` imo). + */ + human(...args: unknown[]) { + console.error(...args); + } +} + +function extractFlag(argv: string[], name: string): boolean { + const index = argv.indexOf(name); + + if (index === MISSING_INDEX) { + return false; + } + + argv.splice(index, REMOVE); + return true; +} diff --git a/glimmer-vm/bin/package.json b/glimmer-vm/bin/package.json new file mode 100644 index 00000000000..4d0bb42b55e --- /dev/null +++ b/glimmer-vm/bin/package.json @@ -0,0 +1,52 @@ +{ + "name": "@glimmer-workspace/bin", + "version": "0.92.0", + "type": "module", + "private": true, + "repo-meta": { + "strictness": "loose", + "env": [ + "node", + "console" + ], + "lint": [ + "*" + ] + }, + "scripts": {}, + "dependencies": { + "@glimmer-workspace/repo-metadata": "workspace:*", + "@pnpm/workspace.find-packages": "^1000.0.10", + "@types/glob": "^8.1.0", + "@types/js-yaml": "^4.0.9", + "@types/node": "^22.13.4", + "@types/puppeteer-chromium-resolver": "workspace:*", + "@types/tar": "^6.1.13", + "chalk": "^5.4.1", + "execa": "^7.1.1", + "fs-extra": "^11.3.0", + "glob": "^10.2.3", + "js-yaml": "^4.1.0", + "mkdirp": "^3.0.1", + "p-map": "^7.0.3", + "puppeteer-chromium-resolver": "^23.0.0", + "rimraf": "^6.0.1", + "strip-ansi": "^7.1.0", + "tar": "^6.2.0", + "which": "^5.0.0", + "zx": "^8.3.2" + }, + "devDependencies": { + "@pnpm/types": "^1000.1.1", + "@types/fs-extra": "^11.0.4", + "eslint": "^9.20.1", + "esno": "^0.16.3", + "type-fest": "^4.35.0" + }, + "engines": { + "node": ">=18.0.0" + }, + "config": { + "tsconfig": "./tsconfig.json" + } +} diff --git a/glimmer-vm/bin/packages.mts b/glimmer-vm/bin/packages.mts new file mode 100644 index 00000000000..0a49eca3170 --- /dev/null +++ b/glimmer-vm/bin/packages.mts @@ -0,0 +1,16 @@ +import { execSync } from 'node:child_process'; + +export interface Package { + readonly name: string; + readonly version: string; + readonly path: string; + readonly private: boolean; +} + +export function packages(namespace: string): Package[] { + return JSON.parse( + execSync(`pnpm ls -r --depth -1 --filter "${namespace}/*" --json`, { + encoding: 'utf-8', + }) + ) as Package[]; +} diff --git a/glimmer-vm/bin/patch-all.mjs b/glimmer-vm/bin/patch-all.mjs new file mode 100644 index 00000000000..bfa39e1e174 --- /dev/null +++ b/glimmer-vm/bin/patch-all.mjs @@ -0,0 +1,48 @@ +import { existsSync } from 'node:fs'; +import { readFile, writeFile } from 'node:fs/promises'; + +import fsExtra from 'fs-extra'; + +const { readJSONSync, writeJSONSync } = fsExtra; + +let file; + +if (existsSync('.release-plan.json')) { + let buffer = await readFile('.release-plan.json'); + let string = buffer.toString(); + file = JSON.parse(string); +} + +for (let [pkgName, existing] of Object.entries(file.solution)) { + let [major, minor, patch] = existing.oldVersion.split('.'); + let newVersion = `${major}.${minor}.${Number(patch) + 1}`; + + let pkgJSONPath = `packages/${pkgName}/package.json`; + file.solution[pkgName] = { + ...existing, + newVersion, + impact: 'patch', + pkgJSONPath, + }; +} + +await writeFile('.release-plan.json', JSON.stringify(file, null, 2)); + +// copied from release-plan +// This is temporary just fix the VM release, since it's a bit pressing. +// Loneger term fix for this is happening +// https://github.com/embroider-build/release-plan/pull/79 +/** + * @param {any} solution + */ +function updateVersions(solution) { + for (const entry of Object.values(solution)) { + if (entry.impact) { + const pkg = readJSONSync(entry.pkgJSONPath); + pkg.version = entry.newVersion; + writeJSONSync(entry.pkgJSONPath, pkg, { spaces: 2 }); + } + } +} + +updateVersions(file.solution); diff --git a/glimmer-vm/bin/post-install.sh b/glimmer-vm/bin/post-install.sh new file mode 100755 index 00000000000..049612ea248 --- /dev/null +++ b/glimmer-vm/bin/post-install.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash + +if [ "$CI" != "" ]; then + echo "We don't run postinstall in CI" + + exit 0 +fi + + node --disable-warning=ExperimentalWarning --experimental-strip-types ./bin/bench-packages.mts + diff --git a/glimmer-vm/bin/published-packages.mts b/glimmer-vm/bin/published-packages.mts new file mode 100644 index 00000000000..f4e3db1e38b --- /dev/null +++ b/glimmer-vm/bin/published-packages.mts @@ -0,0 +1,42 @@ +import chalk from 'chalk'; + +import { packages } from './packages.mjs'; + +/* + Example JSON entry: + + { + name: '@glimmer/validator', + version: '0.92.3', + path: '/home/ykatz/Code/Ember/glimmer-vm/packages/@glimmer/validator', + private: false, + dependencies: { + '@glimmer/env': [Object], + '@glimmer/global-context': [Object], + '@glimmer/interfaces': [Object], + '@glimmer/util': [Object] + }, + devDependencies: { + '@glimmer-workspace/build-support': [Object], + '@glimmer/debug-util': [Object], + '@glimmer/local-debug-flags': [Object], + eslint: [Object], + publint: [Object], + rollup: [Object], + typescript: [Object] + } + } +*/ + +/** + * @typedef {} PackageEntry + */ + +const entries = packages('@glimmer'); + +const quiet = process.argv.includes('--quiet') || process.argv.includes('-q'); + +for (const entry of entries) { + console.log(entry.name); + if (!quiet) console.error(chalk.gray(` ${entry.path}`)); +} diff --git a/glimmer-vm/bin/run-tests.mjs b/glimmer-vm/bin/run-tests.mjs new file mode 100644 index 00000000000..431a16e9255 --- /dev/null +++ b/glimmer-vm/bin/run-tests.mjs @@ -0,0 +1,99 @@ +/* eslint-disable n/no-process-exit */ +// @ts-check + +import child from 'child_process'; +import { resolve } from 'path'; +import PCR from 'puppeteer-chromium-resolver'; +import stripAnsi from 'strip-ansi'; +import { fileURLToPath } from 'url'; + +const { puppeteer, executablePath } = await PCR({}); + +const __root = fileURLToPath(new URL('..', import.meta.url)); + +console.log('[ci] starting'); + +await /** @type {Promise} */ ( + new Promise((fulfill) => { + const runvite = child.fork( + resolve(__root, 'node_modules', 'vite', 'bin', 'vite.js'), + ['--port', '60173', '--no-open'], + { + stdio: 'pipe', + } + ); + + process.on('exit', () => runvite.kill()); + + runvite.stderr?.on('data', (data) => { + console.log('stderr', String(data)); + }); + + runvite.stdout?.on('data', (data) => { + const chunk = String(data); + console.log('stdout', chunk); + if (chunk.includes('Local') && chunk.includes('60173')) { + fulfill(); + } + }); + + console.log('[ci] spawning'); + }) +); + +console.log('[ci] spawned'); + +const browser = await puppeteer.launch({ + headless: true, + executablePath, + args: ['--no-sandbox', '--disable-setuid-sandbox'], +}); + +console.log('[ci] puppeteer launched'); + +try { + console.log('[ci] navigating to new page'); + const page = await browser.newPage(); + console.log('[ci] done navigating'); + + console.log('[ci] waiting for console'); + const promise = /** @type {Promise} */ ( + new Promise((fulfill, reject) => { + page.on('console', (msg) => { + console.error(msg.text()); + const location = msg.location(); + const text = stripAnsi(msg.text()); + + if (text.includes('# fail')) { + if (!text.includes('# fail 0')) { + console.error(text); + process.exit(1); + } + } + + if (location.url?.includes(`/qunit.js`)) { + console.log(text); + } else if (text === `[HARNESS] done`) { + fulfill(); + } else if (text === `[HARNESS] fail`) { + // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors + reject(); + } + }); + }) + ); + console.log('[ci] done waiting'); + + console.log('[ci] navigating to test page'); + void page.goto('http://localhost:60173?hidepassed&ci'); + console.log('[ci] done navigating'); + + await promise; +} catch { + await browser.close(); + process.exit(1); +} + +await browser.close(); + +process.exit(0); diff --git a/glimmer-vm/bin/run-types-tests.mjs b/glimmer-vm/bin/run-types-tests.mjs new file mode 100755 index 00000000000..31c6631775f --- /dev/null +++ b/glimmer-vm/bin/run-types-tests.mjs @@ -0,0 +1,69 @@ +import { inspect } from 'node:util'; + +import { execSync } from 'child_process'; +import { execa } from 'execa'; +import yaml from 'js-yaml'; +import { resolve } from 'path'; +import { fileURLToPath } from 'url'; + +const __dirname = fileURLToPath(new URL('.', import.meta.url)); +const root = resolve(__dirname, '..'); + +const PACKAGES_WITH_NO_PUBLISHED_TYPES = new Set(['@glimmer/vm-babel-plugins', '@glimmer/debug']); + +async function main() { + const packages = getPackages().filter((pkg) => !PACKAGES_WITH_NO_PUBLISHED_TYPES.has(pkg.name)); + + /** + * Runs a smoke test of the generated type definitions by importing every module + * and running it through the TypeScript compiler. + */ + console.log('TAP version 14'); + console.log(`1..${packages.length}`); + + let testNo = 1; + + for (const pkg of packages) { + try { + console.log(`# Smoke testing ${pkg.name}`); + await execa('tsc', ['-p', resolve(root, 'tsconfig.dist.json')], { + cwd: resolve(pkg.path, 'dist'), + preferLocal: true, + }); + console.log(`ok ${testNo++} - ${pkg.name} types passed`); + } catch (err) { + let message = getMessage(err); + console.log(`not ok ${testNo++} - types failed smoke test`); + console.log(` --- + ${yaml.dump({ message })} + ...`); + + process.exitCode = 1; + } + } +} + +/** + * @param {unknown} err + * @returns {string | undefined} + */ +function getMessage(err) { + if (err && typeof err === 'object' && 'message' in err && typeof err.message === 'string') { + return err.message; + } + return inspect(err); +} + +// @fixme Investigate and document why this shouldn't be `await`ed +void main(); + +/** @typedef {{ name: string; version: string; path: string; main: string; private: boolean; }} PnpmPackage */ + +function getPackages() { + /** @type {PnpmPackage[]} */ + const allPackages = JSON.parse( + execSync(`pnpm -r ls --depth -1 --json`, { encoding: 'utf-8' }).trim() + ); + + return allPackages.filter((pkg) => !pkg.private && pkg.name !== '@glimmer/interfaces'); +} diff --git a/glimmer-vm/bin/setup-bench.mts b/glimmer-vm/bin/setup-bench.mts new file mode 100644 index 00000000000..3ae0137a592 --- /dev/null +++ b/glimmer-vm/bin/setup-bench.mts @@ -0,0 +1,218 @@ +/* eslint-disable n/no-process-exit */ +import os from 'node:os'; +import { join } from 'node:path'; + +import type { PackageJson } from 'type-fest'; +import { WORKSPACE_ROOT } from '@glimmer-workspace/repo-metadata'; +import fs from 'fs-extra'; +import { $, which } from 'zx'; + +import { buildKrausestDeps } from './bench-packages.mts'; + +const { ensureDirSync, writeFileSync } = fs; + +const ROOT = new URL('..', import.meta.url).pathname; +$.verbose = true; + +/** + * By default, we rebuild the control branch every time. The `REUSE_CONTROL` env var + * can be used to reuse the checked out control branch. + */ +const FRESH_CONTROL_CHECKOUT = !process.env['REUSE_CONTROL']; +const FRESH_EXPERIMENT_CHECKOUT = !process.env['REUSE_EXPERIMENT']; + +/* + + To run proper bench setup we need to do following things: + + 1.) Compile control packages + 2.) Compile experiment packages + 3.) Use SAME benchmark source + * we should be able to tweak bench + (add more cases, and still be able to compare with control) + * we should be able to re-run bench in CI from current branch with updated perf source + +*/ + +const experimentRef = + process.env['EXPERIMENT_BRANCH_NAME'] || (await $`git rev-parse HEAD`).stdout.trim(); +const controlBranchName = process.env['CONTROL_BRANCH_NAME'] || 'main'; + +// same order as in benchmark/benchmarks/krausest/lib/index.ts +const appMarkers = [ + 'render', + 'render1000Items1', + 'clearItems1', + 'render1000Items2', + 'clearItems2', + 'render5000Items1', + 'clearManyItems1', + 'render5000Items2', + 'clearManyItems2', + 'render1000Items3', + 'append1000Items1', + 'append1000Items2', + 'updateEvery10thItem1', + 'updateEvery10thItem2', + 'selectFirstRow1', + 'selectSecondRow1', + 'removeFirstRow1', + 'removeSecondRow1', + 'swapRows1', + 'swapRows2', + 'clearItems4', +].reduce((acc, marker) => { + return acc + ',' + marker + 'Start,' + marker + 'End'; +}, ''); + +const markers = (process.env['MARKERS'] || appMarkers) + .split(',') + .filter((el) => el.length) + .join(','); +const fidelity = process.env['FIDELITY'] || '20'; +const throttleRate = process.env['THROTTLE'] || '2'; + +const tempDir = os.tmpdir(); + +const CONTROL_DIRS = { + root: join(tempDir, 'control'), + repo: join(tempDir, 'control/repo'), + bench: join(tempDir, 'control/bench'), +}; +const EXPERIMENT_DIRS = { + root: join(tempDir, 'experiment'), + bench: join(tempDir, 'experiment/bench'), + src: join(WORKSPACE_ROOT, 'benchmark/benchmarks/krausest'), +}; + +const CONTROL_PORT = 4020; +const EXPERIMENT_PORT = 4021; +const CONTROL_URL = `http://localhost:${CONTROL_PORT}`; +const EXPERIMENT_URL = `http://localhost:${EXPERIMENT_PORT}`; + +const pnpm = await which('pnpm'); + +// set up experiment +{ + if (FRESH_EXPERIMENT_CHECKOUT) { + await $`rm -rf ${EXPERIMENT_DIRS.root}`; + await $`mkdir -p ${EXPERIMENT_DIRS.bench}`; + await $`cp -r ${EXPERIMENT_DIRS.src}/* ${EXPERIMENT_DIRS.bench}/`; + await $`${pnpm} turbo prepack --output-logs=new-only`; + await buildKrausestDeps({ + roots: { benchmark: EXPERIMENT_DIRS.bench, workspace: WORKSPACE_ROOT }, + }); + await $`rm -rf ${EXPERIMENT_DIRS.bench}/node_modules`; + await $({ cwd: EXPERIMENT_DIRS.bench })`${pnpm} install`; + await $({ cwd: EXPERIMENT_DIRS.bench })`${pnpm} vite build`; + } +} + +// make sure that the origin is up to date so we get the right control +await $`git fetch origin`; + +// now we can get the ref of the control branch so we can check it out later +const controlRef = (await $`git rev-parse origin/main`).stdout.trim(); + +console.info({ + control: controlBranchName, + experiment: experimentRef, + EXPERIMENT_DIRS, + CONTROL_DIRS, +}); + +// set up control +{ + if (FRESH_CONTROL_CHECKOUT) { + // A fresh checkout will reset the control directory and re-clone the repo from scratch at the + // control ref (i.e. `main`). + await $`rm -rf ${CONTROL_DIRS.root}`; + await $`mkdir -p ${CONTROL_DIRS.bench}`; + + // clone the raw git repo for the experiment + await $`git clone ${join(ROOT, '.git')} ${CONTROL_DIRS.repo}`; + } else { + // When reusing the control checkout, we just need to make sure the repo is up to date. + await $({ cwd: CONTROL_DIRS.repo })`git fetch`; + } + + // Update the checkout to the control ref. + await $({ cwd: CONTROL_DIRS.repo })`git checkout --force ${controlRef}`; + + await $`rm -rf ${CONTROL_DIRS.bench}`; + // Intentionally use the `krausest` folder from the experiment in both + // control and experiment + await $`mkdir -p ${CONTROL_DIRS.bench}`; + await $`cp -r ${EXPERIMENT_DIRS.src}/* ${CONTROL_DIRS.bench}/`; + + await $({ cwd: CONTROL_DIRS.repo })`${pnpm} install`; + await $({ cwd: CONTROL_DIRS.repo })`${pnpm} turbo prepack --output-logs=new-only`; + + const benchmarkEnv = join(CONTROL_DIRS.repo, 'packages/@glimmer-workspace/benchmark-env'); + + /** @bandaid{@link patchControl} */ + await patchControl(benchmarkEnv); + + await buildKrausestDeps({ + roots: { benchmark: CONTROL_DIRS.bench, workspace: CONTROL_DIRS.repo }, + }); + + await $`rm -rf ${CONTROL_DIRS.bench}/node_modules`; + await $({ cwd: CONTROL_DIRS.bench })`${pnpm} install`; + await $({ cwd: CONTROL_DIRS.bench })`${pnpm} vite build`; +} + +// Intentionally don't await these. TODO: Investigate if theer's a better structure. +const control = $`cd ${CONTROL_DIRS.bench} && pnpm vite preview --port ${CONTROL_PORT}`; +const experiment = $`cd ${EXPERIMENT_DIRS.bench} && pnpm vite preview --port ${EXPERIMENT_PORT}`; + +process.on('exit', () => { + void Promise.allSettled([control.kill(), experiment.kill()]); +}); + +await new Promise((resolve) => { + // giving 5 seconds for the server to start + setTimeout(resolve, 5000); +}); + +try { + const output = + await $`node --single-threaded-gc ./node_modules/tracerbench/bin/run compare --regressionThreshold 25 --sampleTimeout 60 --fidelity ${fidelity} --markers ${markers} --controlURL ${CONTROL_URL} --experimentURL ${EXPERIMENT_URL} --report --headless --cpuThrottleRate ${throttleRate}`; + + ensureDirSync('tracerbench-results'); + writeFileSync( + 'tracerbench-results/msg.txt', + output.stdout.split('Benchmark Results Summary').pop() ?? '' + ); +} catch (p) { + console.error(p); + process.exit(1); +} + +// @bandaid(until: the current PR is merged) +// +// Right now, the `main` branch of `@glimmer-workspace/benchmark-env` does not have a buildable +// version of `@glimmer-workspace/benchmark-env`, so we need to manually build it. +// +// Once this PR is merged, we can remove this code because all future control branches will have +// built `@glimmer-workspace/benchmark-env` in the `pnpm build` step above. +async function patchControl(benchmarkEnv: string) { + writeFileSync( + join(benchmarkEnv, 'rollup.config.mjs'), + [ + `import { Package } from '@glimmer-workspace/build-support';`, + + `export default Package.config(import.meta);`, + ].join('\n\n') + ); + + const manifest = JSON.parse( + await fs.readFile(join(benchmarkEnv, 'package.json'), 'utf8') + ) as PackageJson; + manifest.publishConfig ??= {}; + manifest.publishConfig['exports'] = './dist/prod/index.js'; + writeFileSync(join(benchmarkEnv, 'package.json'), JSON.stringify(manifest, null, 2), 'utf8'); + + // This is also a patch for incorrect behavior on the current `main`. + await $({ cwd: benchmarkEnv })`${pnpm} rollup --config rollup.config.mjs --external`; +} diff --git a/glimmer-vm/bin/sync-npm-owners.mjs b/glimmer-vm/bin/sync-npm-owners.mjs new file mode 100755 index 00000000000..268e2f17691 --- /dev/null +++ b/glimmer-vm/bin/sync-npm-owners.mjs @@ -0,0 +1,47 @@ +// This script fetches the npm owners of the root package (glimmer-engine) and +// makes them owners of all of individual subpackages. Note that the script will +// add new people, but won't remove anyone who has been removed from +// glimmer-engine. + +import { execSync } from 'node:child_process'; +import { readFileSync } from 'node:fs'; +import { resolve } from 'node:path'; + +import { globSync } from 'glob'; + +const __dirname = new URL('.', import.meta.url).pathname; +const manifest = resolve(__dirname, '../package.json'); +let name = JSON.parse(readFileSync(manifest, { encoding: 'utf-8' })).name; + +console.log('Looking for existing owners on ' + name + ' on npm...'); + +let owners = execSync('npm owner ls') + .toString() + .split('\n') + .filter((line) => line.trim()) + .map((line) => line.split(' ')[0]); + +console.log(owners.map((o) => `✅ ${o}`).join('\n')); + +console.log('\nLooking for packages...'); + +let packages = globSync('@glimmer/*/package.json', { + cwd: __dirname + '/../dist', +}).map((pkg) => pkg.replace('/package.json', '')); + +if (!packages.length) { + console.log('No packages found. Did you do a build first?'); + // eslint-disable-next-line n/no-process-exit + process.exit(1); +} + +console.log(packages.join('\n') + '\n'); + +owners.forEach((owner) => { + packages.forEach((pkg) => { + console.log(`Adding ${owner} to ${pkg}...`); + execSync(`npm owner add "${owner}" "${pkg}"`); + }); +}); + +console.log('\nDone.'); diff --git a/glimmer-vm/bin/ts b/glimmer-vm/bin/ts new file mode 100755 index 00000000000..8638adf1ecc --- /dev/null +++ b/glimmer-vm/bin/ts @@ -0,0 +1,2 @@ +#!/usr/bin/env bash +exec node --disable-warning=ExperimentalWarning --experimental-strip-types "$@" \ No newline at end of file diff --git a/glimmer-vm/bin/update-package-json.mts b/glimmer-vm/bin/update-package-json.mts new file mode 100644 index 00000000000..de914e0c328 --- /dev/null +++ b/glimmer-vm/bin/update-package-json.mts @@ -0,0 +1,179 @@ +import { existsSync, readFileSync, writeFileSync } from 'node:fs'; +import { resolve } from 'node:path'; + +import chalk from 'chalk'; + +import type { Package } from './packages.mjs'; + +import { packages } from './packages.mjs'; + +const ROLLUP_CONFIG = [ + `import { Package } from '@glimmer-workspace/build-support'`, + `export default Package.config(import.meta)`, +] + .map((line) => `${line};\n`) + .join('\n'); + +for (const pkg of packages('@glimmer')) { + if (pkg.private) { + console.error(`Unexpected private package in @glimmer namespace`, pkg.name); + } else { + const updated = []; + const { updates, packageJSON } = update(pkg, updatePublic); + updated.push(...updates); + updated.push(...updateRollupConfig(pkg, packageJSON)); + + report(pkg, updated); + } +} + +for (const pkg of packages('@glimmer-workspace')) { + const { updates } = update(pkg, updateUniversalScripts); + report(pkg, updates); +} + +function report(pkg: Package, updates: string[]) { + if (updates.length > 0) { + const marker = updates.length > 1 ? chalk.magenta(` (${updates.length}) `) : ''; + console.log( + `${chalk.gray('-')} ${chalk.yellowBright(pkg.name)}${marker} ${chalk.gray( + updates.join(', ') + )}` + ); + } else { + console.log(`${chalk.gray('-')} ${chalk.gray(pkg.name)}`); + } +} + +interface PackageJSON extends Record { + name?: string | undefined; + main?: string | undefined; + types?: string | undefined; + scripts?: Record | undefined; + devDependencies?: Record | undefined; + config?: + | { + tsconfig?: string | undefined; + } + | undefined; +} + +function update( + pkg: Package, + updater: (packageJSON: PackageJSON) => PackageJSON +): { updates: string[]; packageJSON: PackageJSON } { + let packageJSON = JSON.parse( + readFileSync(`${pkg.path}/package.json`, { encoding: 'utf-8' }) + ) as PackageJSON; + const original = JSON.stringify(packageJSON); + + packageJSON = updater(packageJSON); + + if (original === JSON.stringify(packageJSON)) { + return { updates: [], packageJSON }; + } + writeFileSync(`${pkg.path}/package.json`, JSON.stringify(packageJSON, null, 2), { + encoding: 'utf-8', + }); + + return { updates: ['package.json'], packageJSON }; +} + +function updateRollupConfig(pkg: Package, packageJSON: PackageJSON): string[] { + if (packageJSON.main === 'index.d.ts') return []; + + const config = resolve(pkg.path, 'rollup.config.mjs'); + + if (existsSync(config)) { + const contents = readFileSync(config, { encoding: 'utf-8' }); + if (contents === ROLLUP_CONFIG) return []; + } + + writeFileSync(config, ROLLUP_CONFIG, { encoding: 'utf-8' }); + return ['rollup.config.mjs']; +} + +function updatePublic(packageJSON: PackageJSON) { + return updateExports(updatePublicDependencies(updatePublicScripts(packageJSON))); +} + +function updatePublicScripts(packageJSON: PackageJSON) { + return updateBuildScripts(updateUniversalScripts(packageJSON)); +} + +function updatePublicDependencies(packageJSON: PackageJSON) { + return { + ...packageJSON, + devDependencies: { + ...packageJSON.devDependencies, + '@glimmer-workspace/build-support': 'workspace:*', + }, + }; +} + +function updateBuildScripts(packageJSON: PackageJSON) { + if (packageJSON.main === 'index.d.ts') return packageJSON; + + return updateScripts(packageJSON, { + build: 'rollup -c rollup.config.mjs', + }); +} + +function updateExports(packageJSON: PackageJSON) { + if (packageJSON.main === 'index.js' || packageJSON.main === 'index.mjs') { + if (packageJSON.types === 'index.d.ts' || packageJSON.types === 'index.d.mts') { + return { + ...packageJSON, + exports: { + types: `./${packageJSON.types}`, + default: `./${packageJSON.main}`, + }, + }; + } + return { + ...packageJSON, + exports: { + default: './index.js', + }, + }; + } + + if (packageJSON.main === 'index.d.ts') { + return { ...packageJSON, types: 'index.d.ts', exports: { types: './index.d.ts' } }; + } + + return { + ...packageJSON, + main: 'index.ts', + types: 'index.ts', + publishConfig: { + access: 'public', + main: 'dist/index.js', + types: 'dist/index.d.ts', + exports: { + types: './dist/index.d.ts', + require: './dist/index.cjs', + default: './dist/index.js', + }, + }, + }; +} + +function updateUniversalScripts(packageJSON: PackageJSON) { + const tsconfig = packageJSON.config?.tsconfig ?? '../tsconfig.json'; + + return updateScripts(packageJSON, { + 'test:lint': 'eslint .', + 'test:types': `tsc --noEmit -p ${tsconfig}`, + }); +} + +function updateScripts(packageJSON: PackageJSON, updates: Record) { + return { + ...packageJSON, + scripts: { + ...packageJSON.scripts, + ...updates, + }, + }; +} diff --git a/glimmer-vm/eslint.config.js b/glimmer-vm/eslint.config.js new file mode 100644 index 00000000000..fe2f034973d --- /dev/null +++ b/glimmer-vm/eslint.config.js @@ -0,0 +1,116 @@ +// @ts-check +import gitignore from 'eslint-config-flat-gitignore'; + +import { + code, + compat, + jsons, + override, + tslint, + node, + config, +} from '@glimmer-workspace/eslint-plugin'; +import { WORKSPACE_ROOT } from '@glimmer-workspace/repo-metadata'; + +/** @internal */ +export default config( + gitignore(), + { + name: '@glimmer-workspace/ignores', + ignores: ['ts-dist/**/*', '.reference/**/*'], + }, + override('no-console packages', { + filter: 'env!=console', + rules: { 'no-console': 'error' }, + }), + override('console packages', { + filter: 'env=console', + rules: { 'no-console': 'off' }, + }), + code('strict packages', { + filter: 'strictness=strict', + extends: [tslint.configs.strictTypeChecked], + rules: { + '@typescript-eslint/consistent-return': 'off', + '@typescript-eslint/no-invalid-void-type': 'off', + '@typescript-eslint/no-unnecessary-type-parameters': 'off', + '@typescript-eslint/no-confusing-void-expression': [ + 'error', + { ignoreVoidOperator: true, ignoreVoidReturningFunctions: true }, + ], + '@typescript-eslint/no-unnecessary-condition': [ + 'error', + { allowConstantLoopConditions: true, checkTypePredicates: false }, + ], + }, + }), + code('loose packages', { + filter: 'strictness=loose', + extends: [tslint.configs.recommendedTypeChecked], + rules: { + '@typescript-eslint/no-explicit-any': 'off', + '@typescript-eslint/no-unsafe-argument': 'off', + '@typescript-eslint/no-unsafe-assignment': 'off', + '@typescript-eslint/no-unsafe-return': 'off', + '@typescript-eslint/no-unsafe-member-access': 'off', + '@typescript-eslint/no-unsafe-function-type': 'off', + '@typescript-eslint/no-unsafe-call': 'off', + '@typescript-eslint/restrict-template-expressions': 'off', + '@typescript-eslint/no-deprecated': 'error', + '@typescript-eslint/no-floating-promises': 'error', + }, + }), + code('test packages', { + filter: 'scope=@glimmer-test', + extends: [tslint.configs.recommendedTypeChecked, compat.extends('plugin:qunit/recommended')], + rules: { + 'qunit/require-expect': ['error', 'never-except-zero'], + // we're using assert.step instead of this sort of thing + 'qunit/no-conditional-assertions': 'off', + '@typescript-eslint/no-explicit-any': 'warn', + '@typescript-eslint/no-non-null-assertion': 'warn', + '@typescript-eslint/no-unsafe-member-access': 'warn', + '@typescript-eslint/no-unsafe-call': 'warn', + '@typescript-eslint/no-unsafe-return': 'warn', + '@typescript-eslint/restrict-template-expressions': 'warn', + '@typescript-eslint/no-unsafe-assignment': 'warn', + '@typescript-eslint/no-unsafe-argument': 'warn', + }, + }), + code('type packages', { + filter: 'scope=@types', + extensions: ['d.ts'], + extends: [tslint.configs.recommendedTypeChecked], + }), + code('node packages', { + filter: 'env=node', + plugins: { + n: node, + }, + rules: { 'n/no-process-exit': 'error' }, + }), + { + name: 'CLI scripts', + files: [ + 'bin/**/*.{js,ts,mjs,mts}', + 'repo-metadata/lib/update.ts', + 'repo-metadata/lib/package-updater.ts', + ], + languageOptions: { + parser: tslint.parser, + ecmaVersion: 'latest', + sourceType: 'module', + parserOptions: { + projectService: true, + tsconfigRootDir: WORKSPACE_ROOT, + }, + }, + plugins: { + '@typescript-eslint': tslint.plugin, + }, + rules: { + 'n/no-process-exit': 'off', + }, + }, + jsons +); diff --git a/glimmer-vm/glimmer-vm.code-workspace b/glimmer-vm/glimmer-vm.code-workspace new file mode 100644 index 00000000000..d528cb3829e --- /dev/null +++ b/glimmer-vm/glimmer-vm.code-workspace @@ -0,0 +1,185 @@ +{ + "folders": [ + { + "name": "✨ glimmer-engine", + "path": ".", + }, + { + "name": "glimmer-benchmark", + "path": "benchmark", + }, + { + "name": "@glimmer-workspace/krausest", + "path": "benchmark/benchmarks/krausest", + }, + { + "name": "@glimmer-workspace/bin", + "path": "bin", + }, + { + "name": "📦 packages", + "path": "packages", + }, + { + "name": "📦 @glimmer-workspace/benchmark-env", + "path": "packages/@glimmer-workspace/benchmark-env", + }, + { + "name": "📦 @glimmer-workspace/build-support", + "path": "packages/@glimmer-workspace/build", + }, + { + "name": "📦 @glimmer-workspace/eslint-plugin", + "path": "packages/@glimmer-workspace/eslint-plugin", + }, + { + "name": "📦 @glimmer-workspace/integration-tests", + "path": "packages/@glimmer-workspace/integration-tests", + }, + { + "name": "📦 @glimmer-workspace/test-utils", + "path": "packages/@glimmer-workspace/test-utils", + }, + { + "name": "📦 @glimmer/compiler", + "path": "packages/@glimmer/compiler", + }, + { + "name": "📦 @glimmer-test/compiler", + "path": "packages/@glimmer/compiler/test", + }, + { + "name": "📦 @glimmer/debug", + "path": "packages/@glimmer/debug", + }, + { + "name": "📦 @glimmer/destroyable", + "path": "packages/@glimmer/destroyable", + }, + { + "name": "📦 @glimmer-test/destroyable", + "path": "packages/@glimmer/destroyable/test", + }, + { + "name": "📦 @glimmer/dom-change-list", + "path": "packages/@glimmer/dom-change-list", + }, + { + "name": "📦 @glimmer-test/dom-change-list", + "path": "packages/@glimmer/dom-change-list/test", + }, + { + "name": "📦 @glimmer/encoder", + "path": "packages/@glimmer/encoder", + }, + { + "name": "📦 @glimmer/global-context", + "path": "packages/@glimmer/global-context", + }, + { + "name": "📦 @glimmer/interfaces", + "path": "packages/@glimmer/interfaces", + }, + { + "name": "📦 @glimmer/local-debug-flags", + "path": "packages/@glimmer/local-debug-flags", + }, + { + "name": "📦 @glimmer/manager", + "path": "packages/@glimmer/manager", + }, + { + "name": "📦 @glimmer-test/manager", + "path": "packages/@glimmer/manager/test", + }, + { + "name": "📦 @glimmer/node", + "path": "packages/@glimmer/node", + }, + { + "name": "📦 @glimmer/opcode-compiler", + "path": "packages/@glimmer/opcode-compiler", + }, + { + "name": "📦 @glimmer/owner", + "path": "packages/@glimmer/owner", + }, + { + "name": "📦 @glimmer-test/owner", + "path": "packages/@glimmer/owner/test", + }, + { + "name": "📦 @glimmer/program", + "path": "packages/@glimmer/program", + }, + { + "name": "📦 @glimmer-test/program", + "path": "packages/@glimmer/program/test", + }, + { + "name": "📦 @glimmer/reference", + "path": "packages/@glimmer/reference", + }, + { + "name": "📦 @glimmer-test/reference", + "path": "packages/@glimmer/reference/test", + }, + { + "name": "📦 @glimmer/runtime", + "path": "packages/@glimmer/runtime", + }, + { + "name": "📦 @glimmer/syntax", + "path": "packages/@glimmer/syntax", + }, + { + "name": "📦 @glimmer-test/syntax", + "path": "packages/@glimmer/syntax/test", + }, + { + "name": "📦 @glimmer/util", + "path": "packages/@glimmer/util", + }, + { + "name": "📦 @glimmer-test/util", + "path": "packages/@glimmer/util/test", + }, + { + "name": "📦 @glimmer/validator", + "path": "packages/@glimmer/validator", + }, + { + "name": "📦 @glimmer-test/validator", + "path": "packages/@glimmer/validator/test", + }, + { + "name": "📦 @glimmer/vm", + "path": "packages/@glimmer/vm", + }, + { + "name": "📦 @glimmer/vm-babel-plugins", + "path": "packages/@glimmer/vm-babel-plugins", + }, + { + "name": "📦 @glimmer/wire-format", + "path": "packages/@glimmer/wire-format", + }, + { + "name": "📦 @types/js-reporters", + "path": "packages/@types/js-reporters", + }, + { + "name": "📦 @types/puppeteer-chromium-resolver", + "path": "packages/@types/puppeteer-chromium-resolver", + }, + { + "name": "📦 @types/qunit", + "path": "packages/@types/qunit", + }, + ], + "settings": { + "typescript.tsc.autoDetect": "on", + "typescript.tsdk": "node_modules/typescript/lib", + "typescript.tsserver.experimental.enableProjectDiagnostics": true, + }, +} diff --git a/glimmer-vm/guides/01-introduction.md b/glimmer-vm/guides/01-introduction.md new file mode 100644 index 00000000000..272c56e03a9 --- /dev/null +++ b/glimmer-vm/guides/01-introduction.md @@ -0,0 +1,132 @@ +### Table of Contents + +1. [Introduction](./01-introduction.md) +2. [Precompiler Overview](./02-precompiler-overview.md) +3. [Runtime Overview](./03-runtime-overview.md) +4. [References](./04-references.md) +5. [Validators](./05-validators.md) +6. [~~Runtime Compiler~~](./06-runtime-compiler.md) +7. [~~Initial Render~~](./07-initial-render.md) +8. [~~Rerendering (Updating)~~](./08-rerendering-updating.md) +9. [~~The Environment~~](./09-the-environment.md) +10. [~~Optimizations~~](./10-optimizations.md) + +# Introduction + +Glimmer is a flexible, low-level rendering pipeline for building a "live" DOM +from a superset of the [Handlebars][handlebars] templating language that can +subsequently be updated cheaply when data changes. + +In addition to the basic Handlebars features such as helpers, +Glimmer also comes with built-in support for a very flexible and powerful +primitive called "Components" and a set of low-level hooks which the host +environment can use to build other high-level, user-facing features. + +This document will give you an overview of Glimmer's core architecture. While +this guide is fairly detailed, this is not intended to be an always up-to-date +API documentation or getting started guide. When code examples are given in +this document, you should generally treat them as simplified pseudo-code that +help illustrate the design rather than describing the precise implementation +details in the current codebase. + +The code examples in this document are written in [TypeScript][typescript]. + +[handlebars]: http://handlebarsjs.com +[typescript]: http://www.typescriptlang.org + +## Architecture + +The key insight of Glimmer is that templates represent a declarative programming +language for building and updating DOM. By structuring web UI around templates +as the central abstraction, we can use advanced techniques from programming +languages and compilers to significantly boost the performance of web +applications in practice. + +Because of this, Glimmer's architecture has more in common with compiler +toolchains like clang/LLVM or javac/JVM than traditional JavaScript libraries. + +At a high level, Glimmer is made up of two parts: + +1. The compiler, which turns templates into optimized binary bytecode. +2. The runtime, which evaluates that bytecode and translates its instructions into + things like creating DOM elements or instantiating JavaScript component classes. + +### Compiler + +The compiler is responsible for turning your program's templates into Glimmer +binary bytecode. + +Because Glimmer is an optimizing compiler, it must know about all of the +templates in a program in order to understand how they work together. This is in +contrast to transpilers like Babel, which can transform each file in isolation. + +As the compiler traverses your application and discovers templates, it parses +each one and creates an _intermediate representation_ (IR). The IR is similar to +the final bytecode program but contains symbolic references to external objects +(other templates, helpers, etc.) that may not have been discovered yet. + +Once all of the templates have been parsed into IR, the compiler performs a +final pass that resolves symbolic addresses and writes the final opcodes into a +shared binary buffer. In native compiler terms, you can think of this as the +"linking" step that produces the final executable. + +This binary executable is saved to disk as a `.gbx` file that can be served to a +browser and evaluated with the runtime. + +But we're not quite done yet. The bytecode program will be evaluated in the +browser where it needs to interoperate with JavaScript. For example, users +implement their template helpers as JavaScript functions. In our compiled +program, how do we know what function to call if the user types `{{formatDate +user.createdAt}}`? + +During compilation, Glimmer will assign unique numeric identifiers to each +referenced external object (like a helper or component). We call these +identifiers _handles_, and they are how we refer to "live" JavaScript objects +like functions in the binary bytecode. + +When evaluating Glimmer bytecode in the browser, instead of asking for the +`"formatDate"` helper, the runtime might ask for the object with handle `4`. + +In order to satisfy this request, the compiler also produces a data structure +called the _external module table_ that maps each handle to its associated +JavaScript object. + +For example, imagine we compile a template that invokes two helpers, `formatDate` and +`pluralize`. These helpers get assigned handles `0` and `1` respectively. In order to +allow the runtime to turn those handles into the correct function object, the compiler +might produce a map like this: + +```js +// module-table.ts +import formatDate from 'app/helpers/format-date'; +import pluralize from 'app/helpers/pluralize'; + +export default [formatDate, pluralize]; +``` + +With this data structure, we can easily implement a function that translates handles into +the appropriate live object: + +```ts +import moduleTable from './module-table'; + +function resolveHandle(handle: number): T { + return moduleTable[handle]; +} +``` + +You can think of the external module table as the bridge between Glimmer's +bytecode and the JavaScript VM. We can compactly represent references to +external objects in the bytecode using handles, and then rehydrate them later +with minimal overhead. + +Now that we have our compiled bytecode and the module table, we're ready to run +our app in the browser, or any other JavaScript environment, like Node.js. + +### Runtime + +TODO + +* * * + +[Next: Precompiler Overview »](./02-precompiler-overview.md) diff --git a/glimmer-vm/guides/02-precompiler-overview.md b/glimmer-vm/guides/02-precompiler-overview.md new file mode 100644 index 00000000000..9c614d93ec4 --- /dev/null +++ b/glimmer-vm/guides/02-precompiler-overview.md @@ -0,0 +1,74 @@ +### Table of Contents + +1. [Introduction](./01-introduction.md) +2. [Precompiler Overview](./02-precompiler-overview.md) +3. [Runtime Overview](./03-runtime-overview.md) +4. [References](./04-references.md) +5. [Validators](./05-validators.md) +6. [~~Runtime Compiler~~](./06-runtime-compiler.md) +7. [~~Initial Render~~](./07-initial-render.md) +8. [~~Rerendering (Updating)~~](./08-rerendering-updating.md) +9. [~~The Environment~~](./09-the-environment.md) +10. [~~Optimizations~~](./10-optimizations.md) + +# Precompiler Overview + +The precompilation step, which generally occurs at build time, takes a template string and turns it into an Intermediate Representation (also known as IR or WireFormat). The Intermediate Representation is a set of structured instructions that could be used directly for rendering, but is more appropriately further processed into optimized opcodes. The public interface for the precompilation is the `precompile` function from the `@glimmer/compiler` package. + +```js +import { precompile } from '@glimmer/compiler'; + +... + +const wireFormat = precompile('

This string is my template

'); + +... +``` + +## How the sausage is made +The precompilation process is relatively short and straightforward, and if you are satisfied with knowing that strings go in and Intermediate Representations come out, you can safely skip to the next guide. If you would like to know a little more about how the process works, read on. + +### Template examples +``` +Hello, Glimmer! +``` + +or + +``` +

This string looks like HTML

+``` + +or + +``` +{{#ember-component as |compy386|}}This string looks like Ember{{/ember-component}} +``` + +or + +``` +This string looks like Glimmer.js +``` + +### Parsing the string with Handlebars + +Though the examples above may _look_ like HTML, Ember templates, or Glimmer templates, at the point of precompilation they are just strings. These strings are transformed into Abstract Syntax Trees ([AST](https://en.wikipedia.org/wiki/Abstract_syntax_tree)) by the Handlebars parser. + +``` +let ast = handlebars.parse('

This string looks like HTML

'); +``` + +At this point in the process, parts of the string have meaning, but the Handlebars parser does not understand HTML syntax, so much of the template strings are still just strings. + +### Identifying HTML and angle components + +From here, Glimmer further processes the AST, teasing meaning out of the strings that remain. When this preprocessing is complete, each part of the original template string is parsed and labeled. For example, the `p` and `GlimmerComponent` from the examples above are recognized as `ElementNode`s. The AST is ready for compilation. + +### Creating the Intermediate Representation + +Glimmer's `TemplateCompiler` transforms the AST into an Intermediate Representation ([IR](https://en.wikipedia.org/wiki/Intermediate_representation)) or `WireFormat`. The Intermediate Representation contains a list of `statements` or instructions which will eventually be used to render the template, and a `symbolTable` containing the variables created in the scope of a template block. For instance, in the `ember-component` example above, `{{#ember-component as |compy386|}} ... {{/ember-component}}` is the block, and `compy386` is the variable created in the scope of the block. + +When the Intermediate Representation is ready, the precompilation step is complete. At this point, paths diverge; the final compilation steps are either completed at build time or at run time, depending on the environment in which Glimmer is running. Read on! + +[Next: Runtime Overview »](./03-runtime-overview.md) diff --git a/glimmer-vm/guides/03-runtime-overview.md b/glimmer-vm/guides/03-runtime-overview.md new file mode 100644 index 00000000000..5b73ff6e7e5 --- /dev/null +++ b/glimmer-vm/guides/03-runtime-overview.md @@ -0,0 +1,50 @@ +### Table of Contents + +1. [Introduction](./01-introduction.md) +2. [Precompiler Overview](./02-precompiler-overview.md) +3. [Runtime Overview](./03-runtime-overview.md) +4. [References](./04-references.md) +5. [Validators](./05-validators.md) +6. [~~Runtime Compiler~~](./06-runtime-compiler.md) +7. [~~Initial Render~~](./07-initial-render.md) +8. [~~Rerendering (Updating)~~](./08-rerendering-updating.md) +9. [~~The Environment~~](./09-the-environment.md) +10. [~~Optimizations~~](./10-optimizations.md) + +# Runtime Overview + +The Glimmer runtime takes the compiled bytecode discussed in the previous section and renders it in the browser. At a high level, the runtime begins by rendering a component tree, beginning with one root component and walking down through its templates. While doing this, it saves an optimized set of bytecodes which can be used later on when rerendering the application. These update codes ignore content which is purely static, such as DOM elements and helpers or components which have static inputs, and adds updating instructions for dynamic content. + +Glimmer simultaneously sets up a tree of _references_ and _validators_ for components, helpers, and values. These allow Glimmer to efficiently check if the state of a given subtree of the component hierarchy has changed, and rerender it if so. + +## Application Lifecycle + +At a high level, the runtime centers around around 3 main concepts: + +1. [Components](#component-glossary) +2. [References](#reference-guide) +3. [Validators](#validator-guide) + +**Components** as seen by Glimmer are a reusable unit of UI that encapsulates behavior and appearance. Because Glimmer VM is a highly configurable runtime, the exact meaning of "component" is determined by the host [environment](#environment) and one or more [component managers](#component-manager). + +**References** are stable objects that represents the result of a pure (side-effect-free) computation, where the result of the computation might change over time. Glimmer creates references to represent values used in templates so that they can be efficiently shared across multiple components and efficiently updated should the underlying value change. + +**Validators** are stable objects that provides certain guarantees about the freshness of a computation result. Validators can be combined, such that if any of a child validator's values have been changed, the parent will also be marked as changed. + +A Glimmer application consists of a tree of components, starting with one root component, and evaluating and rendering any references to values, helpers, and other components it may have in its template. You can think of this as the `main` component, similar to the `main` function in many programming languages. Unlike those languages however, the Glimmer VM is fairly low level and doesn't provide a convention for defining this component. This allows host environments to define their conventions and `main` component as they see fit, and render it using Glimmer's `renderMain` function. + +As it renders, Glimmer adds validators for every component and reference it creates. These validators are combined, such that the validator for a given component represents the union of the validators for any references or components it contains, resulting in a tree of validators that matches the component tree. + +Host environments can then provide different methods for invalidating state (via the validators), such as Ember's `set()` function or `@tracked` from Glimmer.js. When rerendering, Glimmer traverses the tree of components, checking each component's validator to see if it needs to be rerendered. If so, it traverses the component's subtree, but if not, the component is skipped entirely. This results in very efficient rerenders as only the portions that have changed will be rerendered by default. + +[component-glossary]: ./11-glossary.md#component +[reference-guide]: ./04-references.md +[validator-guide]: ./05-validators.md + +## The Virtual Machine + +TODO + +* * * + +[Next: References »](./04-references.md) diff --git a/glimmer-vm/guides/04-references.md b/glimmer-vm/guides/04-references.md new file mode 100644 index 00000000000..e6d7c2558ff --- /dev/null +++ b/glimmer-vm/guides/04-references.md @@ -0,0 +1,511 @@ +### Table of Contents + +1. [Introduction](./01-introduction.md) +2. [Precompiler Overview](./02-precompiler-overview.md) +3. [Runtime Overview](./03-runtime-overview.md) +4. [References](./04-references.md) +5. [Validators](./05-validators.md) +6. [~~Runtime Compiler~~](./06-runtime-compiler.md) +7. [~~Initial Render~~](./07-initial-render.md) +8. [~~Rerendering (Updating)~~](./08-rerendering-updating.md) +9. [~~The Environment~~](./09-the-environment.md) +10. [~~Optimizations~~](./10-optimizations.md) + +# References + +The core primitive of the Glimmer runtime is the `Reference` abstract data +type. + +Fundamentally, a reference is a stable object that represents the result of a +pure (side-effect-free) computation, where the result of the computation +might change over time. It has the following interface: + +```typescript +interface Reference { + value(): T; +} +``` + +If you are familiar with FRP terminologies, you might recognize this as a +discrete "signal". The key departure from other similar constructs in other +libraries (such as Ember's `Stream`s and ReactiveX's `Observable`s) is that +references is a pull-based system with no notion of "subscriptions" or +"notifications". + +As explained in the previous chapter, we find a pull-based system to be a +better fit (and ultimately more efficient) for the kind of problems we are +trying to solve. (In the next chapter, we will discuss a technique for tracking +changes without notifications.) + +In the following example, we will construct a simple reference that "captures" +the value for the `foo` variable over its lifetime: + +```typescript +let foo = 1; + +let fooReference: Reference = { + value() { + return foo; + } +}; + +fooReference.value(); // => 1 + +foo++; + +fooReference.value(); // => 2 +``` + +As you can see, calling `fooReference.value()` will always yield the current +value of the `foo` variable. + +This is a fairly basic example, but it begins to illustrate the power of the +`Reference` abstraction. While JavaScript variables always contain *values* +that could be passed around to (and held onto by) other functions, the +*variable bindings* themselves are not a first-class value. Using the reference +system, it is trivial to pass a variable *by reference* (hence the name for the +`Reference` data type). + +### Composition + +`Reference`s are inherently composable. In this example, we will model the +`foo + bar` computation using `Reference`s: + +```typescript +let foo = 1; +let bar = 2; + +let fooReference: Reference = { + value() { + return foo; + } +}; + +let barReference: Reference = { + value() { + return bar; + } +}; + +let fooPlusBarReference: Reference = { + value() { + return fooReference.value() + barReference.value(); + } +}; + +fooPlusBarReference.value(); // => 3 + +foo = 2; + +fooPlusBarReference.value(); // => 4 + +bar = 3; + +fooPlusBarReference.value(); // => 5 +``` + +As you can see, `fooPlusBarReference` *composes* `fooReference` and +`barReference` instead of accessing the variables directly. As `foo` and `bar` +change over time, the `fooPlusBarReference` stays up-to-date and returns the +correct result of `foo + bar`. + +### Combinators + +Because `Reference`s are so composable, it is also very easy to write some +higher-order combinators to model some common operations. For example, we can +generalize `fooPlusBarReference` into a reusable `AdditionReference` class: + +```typescript +class AdditionReference implements Reference { + private lhs: Reference; + private rhs: Reference; + + constructor(lhs: Reference, rhs: Reference) { + this.lhs = lhs; + this.rhs = rhs; + } + + value(): number { + return this.lhs.value() + this.rhs.value(); + } +} +``` + +Another example is the "map" operation: + +```typescript +// A `Mapper` is a function that takes a value of type `T` and returns a new +// value of type `U`. +type Mapper = (T) => U; + +function map(source: Reference, mapper: Mapper): Reference { + return new MapperReference(source, mapper); +} + +class MapperReference implements Reference { + private source: Reference; + private mapper: Mapper; + + constructor(source: Reference, mapper: Mapper) { + this.source = source; + this.mapper = mapper; + } + + value(): U { + let { source, mapper } = this; + return mapper(source.value()); + } +} + +let foo = 4919; + +let fooReference: Reference = { + value() { + return foo; + } +}; + +// Converts a number into its hexidecimal (base 16) representation +let toHexMapper: Mapper = function(num) { + return '0x' + num.toString(16).toUpperCase(); +}; + +let hexReference = map(fooReference, toHexMapper); + +hexReference.value(); // => '0x1337' + +foo = 49374; + +hexReference.value(); // => '0xC0DE' +``` + +### Lazy Evaluation + +Since references are pull-based, it is trivial to implement lazy evaluation +semantics simply by avoiding calling `.value()` until it is necessary. Consider +this naïve implementation of a reference that models the ternary conditional +expression in JavaScript (`condition ? ifTrue : ifFalse`): + +```typescript +class ConditionalExpressionReference implements Reference { + private predicate: Reference; + private consequent: Reference; + private alternative: Reference; + + constructor(predicate: Reference, consequent: Reference, alternative: Reference) { + this.predicate = predicate; + this.consequent = consequent; + this.alternative = alternative; + } + + value(): T { + let predicate = this.predicate.value(); + let consequent = this.consequent.value(); + let alternative = this.alternative.value(); + + return predicate ? consequent : alternative; + } +} + +let dayOfWeek = 'Friday'; + +let isWorkDay: Reference = { + value() { + return dayOfWeek !== 'Saturday' && dayOfWeek !== 'Sunday'; + } +}; + +let work: Reference = { + value() { + let result = []; + + result.push('Working...'); + result.push('Working...'); + result.push('Working...'); + result.push('(X_X)'); + + return result.join(' '); + } +}; + +let relax: Reference = { + value() { + return 'Relaxing... (v_v)' + } +}; + +let result = new ConditionalExpressionReference(isWorkDay, work, relax); + +result.value(); // => 'Working... Working... Working... (X_X)' + +dayOfWeek = 'Saturday'; + +result.value(); // => 'Relaxing... (v_v)' +``` + +While this implementation works, it eagerly evaluates both the "consequent" +and "alternative" references, even though only one of the two values are used. +This is not ideal, because the references might represent arbitrarily expensive +computations. + +Instead, we can change the implementation to evaluate the references lazily +(also known as "short-circuit evaluation" in this case): + +```typescript +class ConditionalExpressionReference implements Reference { + // ... + + value(): T { + let { predicate, consequent, alternative } = this; + + if (predicate.value()) { + return consequent.value(); + } else { + return alternative.value(); + } + } +} +``` + +In this improved implementation, it is guaranteed that only one of the two +clauses is evaluated, eliminating a wasteful and potentially expensive +computation. + +* * * + +## References in Glimmer + +References play a very important role in the Glimmer templating system. + +When Glimmer renders a template, each dynamic segment (such as the `{{foo}}` in +`{{foo}}`) are represented by a single reference. On initial render, +these dynamic segments are populated by pulling an initial `value()` out of +these references. + +These references also allow the templates to be re-rendered later with the +most-current data, simply by pulling the latest `value()` out of each reference +and updating the DOM nodes correspondingly (we will discuss the second part +later). + +References also help bridge the gap between the "impure" (effectful) parts +of the system from the "pure" (functional) part of the system. + +In Handlebars, a template is always rendered against a "context" (typically +known as "self" inside Glimmer), similar to JavaScript's `this` when invoking +a function. Take the following template as an example: + +```handlebars +

Welcome, {{user.name.first}}!

+ +

Message of the day: {{motd}}

+``` + +Assuming `motd` is not a helper, both of the dynamic segments are describing a +path lookup on the context (sometimes called a "self lookup" inside Glimmer). +That is, `{{user.name.first}}` is referring the value of `this.user.name.first` +where `this` is the context object. In fact, they can be rewritten as +`{{this.user.name.first}}` and `{{this.motd}}` for clarity. + +Since it is possible for the context to change from one object to a different +object between re-renders, the context itself is modeled as a reference. +Because Handlebars supports arbitrary path lookups on the context (as we saw +in the previous example), Glimmer needs a way to create additional references +from the context reference for a given path. + +Here is one possible solution: + +```typescript +// Encodes the "soft fail" path lookup semantics in Handlebars +// +// Usage: +// let obj = { foo: { bar: 'baz' } }; +// get(obj, 'foo') => { bar: 'baz' } +// get(obj, 'foo, 'bar') => 'baz' +// get(obj, 'foo, 'nope') => undefined +// get(obj, 'foo, 'bar', 'baz') => undefined +function get(object: any, ...subpaths: string[]) { + if (subpaths.length === 0) { + return object; + } + + if (object && typeof object === 'object') { + let head = subpaths[0]; + let tail = subpaths.slice(1); + + return get(object[head], ...tail); + } +} + +class PathLookupReference implements Reference { + private context: Reference; + private subpaths: string[]; + + constructor(context: Reference, path: string) { + this.context = context; + this.subpaths = path.split('.'); + } + + value(): any { + return get(this.context.value(), ...this.subpaths); + } +} + +let context = { + user: { name: { first: 'Godfrey', last: 'Chan' } }, + motd: 'Welcome back!' +} + +let contextReference: Reference = { + value() { + return context; + } +}; + +// {{user.name.first}} +let firstName = new PathLookupReference(contextReference, 'user.name.first'); + +// {{motd}} +let motd = new PathLookupReference(contextReference, 'motd'); + +firstName.value(); // => 'Godfrey' +motd.value(); // => 'Welcome back!' + +context.user.name = { first: 'Yehuda', last: 'Katz' }; + +firstName.value(); // => 'Yehuda' +``` + +While this implementation works, because it evaluates the context reference +into a value, the "parent" and "child" references are not connected in any +meaningful way. + +Occasionally, there might be extra information on the context object that you +might want to propagate to the downstream references. + +For example, the context object might be a simple primitive type like strings, +numbers, or `undefined`, in which case all the subsequent path lookups will +yield `undefined`. + +Alternatively, the context object might be an immutable data structure, in which +case all of downstream `value()`s do not need to be recomputed so long as +the context object itself did not get replaced. + +In addition to the context objects, certain advanced features in Handlebars +(and other extensions in host environments like Ember) inadvertently means that +almost any references (such as the result returned by a helper) can be used in +a path lookup position. + +For all of these reasons, Glimmer defines an extension to the base `Reference` +type called a `PathReference`: + +```typescript +interface PathReference extends Reference { + get(path: string): PathReference; +} +``` + +In addition to the `value()` method, `PathReference`s support a `get` method +that is responsible for converting these path lookups into a child reference. +This allows the parent reference to encode and propagates extra information +downwards. + +A simple example is a reference containing a primitive value (such as a string, +a number, `undefined`, etc): + +```typescript +const NULL_REFERENCE: PathReference = { + value() { + return undefined; + }, + + get(path: string) { + return NULL_REFERENCE; + } +}; + +type Primitive = string | number | boolean | void; + +class PrimitiveReference implements PathReference { + private innerValue: T; + + constructor(value: T) { + this.innerValue = value; + } + + value(): T { + return this.innerValue; + } + + get(path: string): PathReference { + return NULL_REFERENCE; + } +} +``` + +Since all subsequent path lookups on a primitive value will always yield +`undefined`, `PrimitiveReference` is able to take advantage of this information +and return a constant, specialized `PathReference` in its implementation of +`get()`. + +Another example is the `hash` helper in Ember, which takes the named arguments +and convert it into a "hash" (or "dictionary") object: + +```handlebars + + +{{#each currentUser.friends as |friend|}} + +{{/each}} +``` + +Inside the `user-profile` component, `options` can be accessed like a regular +property: + +```handlebars + +``` + +Here is a simplified implementation for the `hash` reference: + +```typescript +class HashReference implements PathReference> { + private args: Dictionary>; + + constructor(args: Dictionary>) { + this.args = args; + } + + value(): Dictionary { + let dict = new Dictionary(); + + Object.keys(this.args).forEach((name) => { + dict[name] = this.args[name].value(); + }); + + return dict; + } + + get(path: string): PathReference { + return this.args[path] || NULL_REFERENCE; + } +} +``` + +By implementing the `PathReference` interface, `HashReference` can avoid +constructing the `Dictionary` object (and evaluating all the unused references +in the process) to fulfill a simple path lookup (e.g. `{{@options.me}}` in the +example above). + +* * * + +[Next: Validators »](./05-validators.md) diff --git a/glimmer-vm/guides/05-validators.md b/glimmer-vm/guides/05-validators.md new file mode 100644 index 00000000000..5002883528d --- /dev/null +++ b/glimmer-vm/guides/05-validators.md @@ -0,0 +1,671 @@ +### Table of Contents + +1. [Introduction](./01-introduction.md) +2. [Precompiler Overview](./02-precompiler-overview.md) +3. [Runtime Overview](./03-runtime-overview.md) +4. [References](./04-references.md) +5. [Validators](./05-validators.md) +6. [~~Runtime Compiler~~](./06-runtime-compiler.md) +7. [~~Initial Render~~](./07-initial-render.md) +8. [~~Rerendering (Updating)~~](./08-rerendering-updating.md) +9. [~~The Environment~~](./09-the-environment.md) +10. [~~Optimizations~~](./10-optimizations.md) + +# Validators + +Since the computation encapsulated in a reference can be arbitrarily expensive, +it is usually a good idea to avoid recomputing its `value()` more often than +necessary. + +In particular, because references are modeling pure computations, there is no +reason to recompute the `value()` of reference if its inputs has not changed. +While it is not always possible to enumerate the inputs to a reference, it can +be done in a lot of cases. + +For example, Handlebars helpers are required to be pure functions that operate +solely on their inputs (arguments). If the inputs have not changed, the result of +the helper invocation will also remain unchanged. + +Consider this simple example: + +```handlebars +

{{uppercase (concat book.title ": " book.subtitle)}}

+``` + +The `concat` and `uppercase` helpers can be modeled as such: + +```typescript +class ConcatReference implements Reference { + private parts: Reference[]; + + constructor(...parts: Reference[]) { + this.parts = parts; + } + + value(): string { + return this.parts.map(reference => reference.value()).join(''); + } +} + +class UppercaseReference implements Reference { + private str: Reference; + + constructor(str: Reference) { + this.str = str; + } + + value(): string { + return this.str.value().toUpperCase(); + } +} + +/// + +//

{{uppercase (concat book.title ": " book.subtitle)}}

+ +let book = { + title: 'The Lord of the Rings', + subtitle: 'The Fellowship of the Ring' +}; + +let titleReference: Reference = { + value() { + return book.title; + } +}; + +let seperatorReference: Reference = { + value() { + return ': '; + } +}; + +let subtitleReference: Reference = { + value() { + return book.subtitle; + } +}; + +let result: Reference = ( + new UppercaseReference( + new ConcatReference( + titleReference, + seperatorReference, + subtitleReference + ) + ) +); + +result.value(); // => 'THE LORD OF THE RINGS: THE FELLOWSHIP OF THE RING' + +book.subtitle = 'The Two Towers'; + +result.value(); // => 'THE LORD OF THE RINGS: THE TWO TOWERS' +``` + +In this case, the inputs to both `ConcatReference` and `UppercaseReference` are +quite clear: `ConcatReference` takes an array of references as input, therefore +it only needs to be recomputed if and only if any of the input references have +"changed" (i.e. a "reduce" operation); on the other hand, `UppercaseReference` +takes a single reference as input, so it should be recomputed if and only +if the input reference has "changed" (i.e. a "map" operation). + +This presents a recursive problem – we know how to model the freshness of +a `ConcatReference` and `UppercaseReference` as long as we also have a way to +model the freshness of their input references. In other words, we need a system +that allows us describe the freshness of a computation in terms of their +inputs. + +The validators system in Glimmer is designed to solve exactly this problem. For +now, we will set aside the fundamental question of how to derive the freshness +of a computation in the first place and focus on the composition aspect of the +validators system. + +## Entity Tags + +The core primitive of the validators system is called an `EntityTag`. An entity +tag is a stable object that provides certain guarantees about the freshness of +a computation result. It has the following interface: + +```typescript +interface EntityTag { + value(): T; + validate(ticket: T): boolean; +} +``` + +Specifically, each entity tag has a `value()` method that returns an *opaque +validation ticket* which encodes the current state of the computation. + +The validation ticket can later be passed back into the `validate` method on +the same entity tag, which returns a boolean value indicating whether the +computation result might have changed since the validation was produced. + +Specifically, if `validate` returns `true` for the given validation ticket, it +is guaranteed that the computation result has *not* changed since the +validation ticket was produced. In other words, if you have cached the result +of the computation at the same time (more precisely – the same "time step" of +the discrete system) when the validation ticket was produced, it is not +necessary to rerun the same computation again since the result would be +equivalent. + +On the other hand, if `validate` returns `false`, the computation *might* have +changed since the validation ticket was produced. Any cached result can no +longer be relied on and a recomputation is necessary. + +However, a negative validation does not imply rerunning the computation would +*always* yield a different result – it merely means that the entity tag can no +longer be certain about the freshness of the computation. In other words, it +operates like a [bloom filter](https://en.wikipedia.org/wiki/Bloom_filter) in that false positives are explicitly allowed and +expected from time to time. + +Aside: if you are paying close attention, you might notice that `EntityTag` +happens to implement the `Reference` interface! While interesting, this does +not have much practical implications. However, it is helpful to remember that, +just like references, entity tags are stable, long lived objects that a can be +held on to by a consumer and queried repeatedly. + +### Entity Tags in HTTP + +The entity tag system in Glimmer is inspired by a similar system in the HTTP +protocol. Understanding its origin might be helpful for understanding some of +the operational details of the Glimmer validators system. + +In the HTTP protocol, entity tags (or ["ETags"](https://en.wikipedia.org/wiki/HTTP_ETag)) are used to handle revalidation +of cached web content. When rendering a page, an HTTP server can optionally +include an `ETag` header in the response. For example: + +``` +HTTP/1.1 200 OK +Date: Wed, 30 Mar 2016 00:00:00 GMT +Content-Type: text/plain +ETag: "0267aa812d66aafb7c4ffb790d8b5ffc" +Content-Length: 12 + +Hello world! +``` + +The `ETag` header here is an opaque validator chosen by the server that encodes +information about this response. For example, a common implementation is an MD5 +hash (or any other hash functions) of the response body. + +The browser can then cache the response alongside with the `ETag`. When the user +requests the same page again, it could send a "conditional GET" request to the +server with the cached `ETag`: + +``` +GET /motd HTTP/1.1 +If-None-Match: "0267aa812d66aafb7c4ffb790d8b5ffc" +Host: example.com +``` + +At this point, the server can do whatever it takes to determine the freshness of +the cached content. For example, the server can re-apply the same hash function +to the document and compare that against the `ETag` supplied by the client. + +After this process, if the server determined that the cached content is still +valid, it can then send an empty "Not Modified" response and avoid transmitting +the same content again: + +``` +HTTP/1.1 304 Not Modified +Date: Wed, 30 Mar 2016 00:30:00 GMT +ETag: "0267aa812d66aafb7c4ffb790d8b5ffc" +Content-Length: 0 +``` + +Since the server has confirmed that the cached content is still valid, the +browser can simply fetch the document from its local cache and display it to +the user. + +Alternatively, the server might find that a new version of the +document has been uploaded since then, meaning that the browser's cached copy +has become stale. + +In this case, the server could simply return the new content along with a +new `ETag`: + +``` +HTTP/1.1 200 OK +Date: Wed, 30 Mar 2016 00:00:00 GMT +Content-Type: text/plain +ETag: "9e3299e7c8dabfb0aca9aee52a129cca" +Content-Length: 14 + +Goodbye world! +``` + +In this case, the browser would evict the old content from its cache, cache +the new version of the document along with the new `ETag` and display the new +content to the user. + +### Entity Tags in Glimmer + +While entity tags serve a slightly different purpose in Glimmer, the idea is +similar. + +Let's define an extension to the `Reference` interface that requires each +reference to have a corresponding tag that guarantees the freshness of its +`value()` method: + +```typescript +interface Tagged { + tag: EntityTag; +} + +interface TaggedReference extends Reference, Tagged { +} +``` + +We will continue to defer the question of *how* exactly do we derive the +freshness of a reference in the first place. For now, take a leap of faith and +assume that they *do* work, and that tag revalidation is cheap relative to +recomputing the `value()` of a reference. + +With this infrastructure in place, we can finally apply this to our helper +references. + +Let's start with `UppercaseReference`. If you recall, `UppercaseReference` +needs to be recomputed if and only if its input reference has changed. +Therefore, we can simply reuse the input reference's entity tag: + +```typescript +class UppercaseReference implements TaggedReference { + public tag: EntityTag; + private str: Reference; + + constructor(str: TaggedReference) { + this.tag = str.tag; + this.str = str; + } + + value(): string { + return this.str.value().toUpperCase(); + } +} +``` + +On the other hand, `ConcatReference` needs to be computed if and only if any of +its input references has changed, so we need to combine the input tags into a +composite tag: + +```typescript +class ConcatReference implements TaggedReference { + public tag: EntityTag; + private parts: TaggedReference[]; + + constructor(...parts: TaggedReference[]) { + let tags = parts.map(reference => reference.tag); + this.tag = new CompositeTag(tags); + this.parts = parts; + } + + value(): string { + return this.parts.map(reference => reference.value()).join(''); + } +} + +class CompositeTag implements EntityTag { + private tags: EntityTag[]; + + constructor(tags: EntityTag[]) { + this.tags = tags; + } + + value(): any[] { + return this.tags.map(tag => tag.value()); + } + + validate(tickets: any[]): boolean { + return this.tags.every((tag, i) => tag.validate(tickets[i])); + } +} +``` + +Finally, we can put all of these together and write a very simple renderer that +renders a reference into a single text node and keeps it up-to-date: + +```typescript +class SimpleRenderer { + private reference: TaggedReference; + private lastTicket: any; + private textNode: Text; + + constructor(reference: TaggedReference) { + this.reference = reference; + this.lastTicket = null; + this.textNode = null; + } + + render(parentNode = document.body) { + let { reference } = this; + + this.lastTicket = reference.tag.value(); + + let text = reference.value(); + let textNode = this.textNode = document.createTextNode(text); + + parentNode.appendChild(textNode); + } + + rerender() { + let { reference, lastTicket } = this; + + if (!reference.tag.validate(lastTicket)) { + this.textNode.textContent = reference.value(); + this.lastTicket = reference.tag.value(); + } + } +} +``` + +Although very basic, this renderer is smart enough to use the entity tags on +the references to avoid unnecessary DOM updates. Fundamentally, this is very +similar to how Glimmer renders simple curlies (e.g. `{{foo}}`) into the DOM. + +## Revision Tags + +While the abstract concept of entity tags is very flexible, it leaves open the +important question of how to encode freshness information into a validation +ticket up to each individual entity tag implementation. + +Furthermore, since we cannot make any assumptions about the semantics of these +encodings, the only way to combine multiple tags is to store one validation +ticket per entity tag and later validate each of the store tickets with the +corresponding tag, e.g. the `CompositeTag` class used in the `ConcatReference` +example. + +Since combining tags from multiple input sources is a very common pattern, it +is very important that it can be implemented as efficiently as possible (both +in terms of space and time complexity). + +To address this issue, Glimmer uses a specialized variant of the entity tag +system called revision tags. This limitation might be loosened in the future in +favor of letting the host environment supply its own entity tag system. + +The revision tag system is based around the idea of a global revision counter. +The global revision counter is a monotonically increasing sequence, which is +just a fancy way of saying that it's a global number that only increases but +never decreases. + +Conceptually, a discrete system (which is what Glimmer assumes) can be modeled +as a series of state transitions. The global revision counter is incremented by +one every time the system undergoes a state transition. In other words, the +global revision counter is incremented every time a variable is changed in the +system. + +In practice, we are only concerned with a subset of all state changes that are +*observable* from the perspective of the templating system. For example, when a +variable that is not part of any template is modified, it is not particularly +important that the global revision counter is incremented. + +In addition to the global counter, each (observable) object in the system has +an internal "last modified" revision counter. Every time an object is modified, +this counter will be set to the current value of the global revision counter +(after the global revision counter has been incremented). + +The easiest way to implement this is with a collaborating object model. For +example, all observable changes in Ember are already required to go through the +`Ember.set` function. This is a perfect opportunity to increment both the +global and per-object revision counters. + +These primitives lay out the foundation for the revision tag system. If we can +assume each observable object in the system has a `lastModified` counter, then +it would be possible to construct an entity tag for each object where the +validation ticket is the current value of the `lastModified` counter. This tag +will guarantee the freshness of any first-level path lookups on that object. +In other words, all property lookups on an object will have the same result so +long as the `lastModified` remain unchanged. + +The following is a simplified implementation of the system. The only departure +from the description above is that the `lastModified` counter is tracked inside +the tag for an object instead of being a separate field on the object. (Besides +simplifying the implementation, it also avoids keeping a pointer from the tag +back to the object). + +```typescript +type Revision = number; + +type RevisionTag = EntityTag; + +let $REVISION_COUNTER: Revision = 1; + +interface TrackedObject { + tag: DirtyableTag; +} + +class DirtyableTag implements RevisionTag { + private lastRevision: Revision; + + constructor() { + this.lastRevision = $REVISION_COUNTER; + } + + value(): Revision { + return this.lastRevision; + } + + validate(ticket: Revision): boolean { + return ticket === this.lastRevision; + } + + dirty() { + this.lastRevision = ++$REVISION_COUNTER; + } +} + +function set(object: TrackedObject, property: string, value: any) { + object.tag.dirty(); + return object[property] = value; +} + +/// + +let person: TrackedObject = { + tag: new DirtyableTag(), + name: 'Godfrey Chan' +}; + +person.tag.value(); // => 1 + +set(person, 'name', 'Yehuda Katz'); + +person.tag.validate(1); // => false +person.tag.value(); // => 2 +``` + +Having a tag on each object allows references to bridge the pure and impure +parts of the system and propagate freshness information across the entire +reference chain. + +For example, this is the updated implementation of `UppercaseReference`: + +```typescript +interface VersionedReference extends Reference { + tag: RevisionTag; +} + +class UppercaseReference implements VersionedReference { + public tag: RevisionTag; + private str: Reference; + + constructor(str: VersionedReference) { + this.tag = str.tag; + this.str = str; + } + + value(): string { + return this.str.value().toUpperCase(); + } +} + +/// + +const person: TrackedObject = { + tag: new DirtyableTag(), + name: 'Godfrey Chan' +}; + +let nameReference: VersionedReference = { + tag: person.tag, + + value() { + return person.name; + } +}; + +let uppercaseReference = new UppercaseReference(nameReference); + +uppercaseReference.value(); // => 'GODFREY CHAN' +uppercaseReference.tag.value(); // => 1 +uppercaseReference.tag.validate(1); // => true + +set(person, 'name', 'Yehuda Katz'); + +uppercaseReference.tag.validate(1); // => false +uppercaseReference.value(); // => 'YEHUDA KATZ' +uppercaseReference.tag.value(); // => 2 +``` + +Since we can now assume that validation tickets are revision numbers, we can +combine them much more efficiently by just returning the largest validation +ticket. Here is the updated implementation of of `ConcatReference` (and +`CompositeTag`): + +```typescript +class ConcatReference implements VersionedReference { + public tag: RevisionTag; + private parts: VersionedReference[]; + + constructor(...parts: VersionedReference[]) { + let tags = parts.map(reference => reference.tag); + this.tag = new CompositeTag(tags); + this.parts = parts; + } + + value(): string { + return this.parts.map(reference => reference.value()).join(''); + } +} + +class CompositeTag implements RevisionTag { + private tags: RevisionTag[]; + + constructor(tags: RevisionTag[]) { + this.tags = tags; + } + + value(): Revision { + let tickets = this.tags.map(tag => tag.value()); + return Math.max(...tickets); + } + + validate(ticket: Revision): boolean { + return ticket === this.value(); + } +}; +``` + +Semantically, this is equivalent to saying a `ConcatReference` is last +modified when any of its input references was last modified, which is +equivalent to saying a `ConcatReference` needs to be recomputed if and only if +any of its input references needs to be recomputed. + +The revision tag system also has a few "special" tags. + +The constant tag has a `value()` of 0, which is smaller than the initial +revision number. This can be used to model computation and values that can +never changed, such as primitive values: + +```typescript +const CONSTANT_TAG: RevisionTag = { + value() { + return 0; + }, + + validate(ticket: Revision) { + return ticket === 0; + } +}; + +const NULL_REFERENCE: VersionedReference = { + tag: CONSTANT_TAG, + + value() { + return null; + } +}; +``` + +The volatile tag has a `value()` of `NaN`. This has two interesting properties. +First, because `Math.max(..., NaN, ...)` returns `NaN`, the `NaN` ticket will +dominate any other tickets in a composite tag. Second, because `NaN !== NaN` in +JavaScript, the tickets given out by this tag will never be valid. + +Essentially, the volatile tag is a "poison" tag that will cause the entire +reference chain to become volatile. This is very useful for modeling +computations that depend on values (or events) outside of the boundaries of the +collaborating object model (such as objects that can be mutated without going +through `Ember.set`): + +```typescript +const VOLATILE_TAG: RevisionTag = { + value() { + return NaN; + }, + + validate(ticket: Revision) { + return false; // NaN !== NaN + } +}; + +let currentTime: VersionedReference = { + tag: VOLATILE_TAG, + + value() { + return Date.now(); + } +}; + +let $input = $('input'); + +let currentInputValue: VersionedReference = { + tag: VOLATILE_TAG, + + value() { + return $('input').val(); + } +}; +``` + +The current tag has a `value()` of the current value of the global revision +counter. This is useful for tracking computations involving unspecified inputs +that are known to be within boundaries of the collaborating object model, +because the tickets will be invalidated as soon as anything inside the system +has changed: + +```typescript +const CURRENT_TAG: RevisionTag = { + value() { + return $REVISION_COUNTER; + }, + + validate(ticket: Revision) { + return ticket === $REVISION_COUNTER; + } +}; +``` + +Alternatively, without a collaborating object model, this tag can be used +in all root references that bridge the untracked objects into the system. The +revision counter can be artificially incremented once just before entering the +global render loop: this will ensure that each computation is only performed +once inside each render loop. This assumes the templates are side-effects-free. + +Together, this set of primitives allows us to implement a very efficient yet +expressive dirty-tracking system without notifications and subscriptions within +the reference chain. + +* * * + +[Next: Runtime Compiler »](./06-runtime-compiler.md) diff --git a/glimmer-vm/guides/06-runtime-compiler.md b/glimmer-vm/guides/06-runtime-compiler.md new file mode 100644 index 00000000000..658e3d5a214 --- /dev/null +++ b/glimmer-vm/guides/06-runtime-compiler.md @@ -0,0 +1,20 @@ +### Table of Contents + +1. [Introduction](./01-introduction.md) +2. [Precompiler Overview](./02-precompiler-overview.md) +3. [Runtime Overview](./03-runtime-overview.md) +4. [References](./04-references.md) +5. [Validators](./05-validators.md) +6. [~~Runtime Compiler~~](./06-runtime-compiler.md) +7. [~~Initial Render~~](./07-initial-render.md) +8. [~~Rerendering (Updating)~~](./08-rerendering-updating.md) +9. [~~The Environment~~](./09-the-environment.md) +10. [~~Optimizations~~](./10-optimizations.md) + +# Runtime Compiler + +TODO: add content here + +* * * + +[Next: Initial Render »](./07-initial-render.md) diff --git a/glimmer-vm/guides/07-initial-render.md b/glimmer-vm/guides/07-initial-render.md new file mode 100644 index 00000000000..6d5c79b5b2c --- /dev/null +++ b/glimmer-vm/guides/07-initial-render.md @@ -0,0 +1,20 @@ +### Table of Contents + +1. [Introduction](./01-introduction.md) +2. [Precompiler Overview](./02-precompiler-overview.md) +3. [Runtime Overview](./03-runtime-overview.md) +4. [References](./04-references.md) +5. [Validators](./05-validators.md) +6. [~~Runtime Compiler~~](./06-runtime-compiler.md) +7. [~~Initial Render~~](./07-initial-render.md) +8. [~~Rerendering (Updating)~~](./08-rerendering-updating.md) +9. [~~The Environment~~](./09-the-environment.md) +10. [~~Optimizations~~](./10-optimizations.md) + +# Initial Render + +TODO: add content here + +* * * + +[Next: Rerendering (Updating) »](./08-rerendering-updating.md) diff --git a/glimmer-vm/guides/08-rerendering-updating.md b/glimmer-vm/guides/08-rerendering-updating.md new file mode 100644 index 00000000000..81674893a19 --- /dev/null +++ b/glimmer-vm/guides/08-rerendering-updating.md @@ -0,0 +1,20 @@ +### Table of Contents + +1. [Introduction](./01-introduction.md) +2. [Precompiler Overview](./02-precompiler-overview.md) +3. [Runtime Overview](./03-runtime-overview.md) +4. [References](./04-references.md) +5. [Validators](./05-validators.md) +6. [~~Runtime Compiler~~](./06-runtime-compiler.md) +7. [~~Initial Render~~](./07-initial-render.md) +8. [~~Rerendering (Updating)~~](./08-rerendering-updating.md) +9. [~~The Environment~~](./09-the-environment.md) +10. [~~Optimizations~~](./10-optimizations.md) + +# Rerendering (Updating) + +TODO: add content here + +* * * + +[Next: The Environment »](./09-the-environment.md) diff --git a/glimmer-vm/guides/09-the-environment.md b/glimmer-vm/guides/09-the-environment.md new file mode 100644 index 00000000000..8968448b8e2 --- /dev/null +++ b/glimmer-vm/guides/09-the-environment.md @@ -0,0 +1,20 @@ +### Table of Contents + +1. [Introduction](./01-introduction.md) +2. [Precompiler Overview](./02-precompiler-overview.md) +3. [Runtime Overview](./03-runtime-overview.md) +4. [References](./04-references.md) +5. [Validators](./05-validators.md) +6. [~~Runtime Compiler~~](./06-runtime-compiler.md) +7. [~~Initial Render~~](./07-initial-render.md) +8. [~~Rerendering (Updating)~~](./08-rerendering-updating.md) +9. [~~The Environment~~](./09-the-environment.md) +10. [~~Optimizations~~](./10-optimizations.md) + +# The Environment + +TODO: add content here + +* * * + +[Next: Optimizations »](./10-optimizations.md) diff --git a/glimmer-vm/guides/10-optimizations.md b/glimmer-vm/guides/10-optimizations.md new file mode 100644 index 00000000000..f76a30606bb --- /dev/null +++ b/glimmer-vm/guides/10-optimizations.md @@ -0,0 +1,18 @@ +### Table of Contents + +1. [Introduction](./01-introduction.md) +2. [Precompiler Overview](./02-precompiler-overview.md) +3. [Runtime Overview](./03-runtime-overview.md) +4. [References](./04-references.md) +5. [Validators](./05-validators.md) +6. [~~Runtime Compiler~~](./06-runtime-compiler.md) +7. [~~Initial Render~~](./07-initial-render.md) +8. [~~Rerendering (Updating)~~](./08-rerendering-updating.md) +9. [~~The Environment~~](./09-the-environment.md) +10. [~~Optimizations~~](./10-optimizations.md) + +# Optimizations + +TODO: add content here + +* * * diff --git a/glimmer-vm/guides/11-glossary.md b/glimmer-vm/guides/11-glossary.md new file mode 100644 index 00000000000..ae704d6b52d --- /dev/null +++ b/glimmer-vm/guides/11-glossary.md @@ -0,0 +1,377 @@ +# Glossary + +This glossary covers terms you may come across while reading the Glimmer VM +source code or participating in its development on GitHub. + +It includes low-level implementation details in the compiler and VM that are +*not* needed to write Glimmer.js components, so don't be overwhelmed! This +document is for intermediate to advanced users who want to understand the inner +workings of Glimmer. + +## Abstract Syntax Tree + +An Abstract Syntax Tree, or AST, is a data structure that represents source code +as a tree of nodes. + +In Glimmer, the AST represents the parsed source code of Handlebars templates. +At compile time, the source for each template is read from disk and passed to +the Handlebars parser, which returns a Handlebars AST. The Glimmer compiler then +uses the AST to ultimately produce bytecode. + +## Bytecode + +Bytecode is a binary encoding of a sequence of instructions, or [opcodes](#opcode), +optimized for being evaluated with a virtual machine, or VM. + +The Glimmer compiler compiles one or more templates into a single bytecode +representation, which can be efficiently loaded and evaluated in the browser by +the VM. Each instruction is represented by a one-byte opcode followed by zero or +more operands. + +## Compiler Delegate + +The compiler delegate is an object that implements the [CompilerDelegate +interface][compiler-delegate-source] and provides information to the compiler +during the compilation process. + +For example, the compiler delegate is responsible for helping the compiler +answer whether a particular component or helper is in scope for the template it +is currently compiling. It also is responsible for providing the +[capabilities](#componentcapabilities) of a component so certain optimizations +can be performed. + +See also: [`CompilerDelegate` interface][compiler-delegate-source] + +[compiler-delegate-source]: ../packages/@glimmer/bundle-compiler/lib/delegate.ts + +## Component + +Generally speaking, a component is a reusable unit of UI that encapsulates +behavior and appearance. Because Glimmer VM is a highly configurable runtime, +the exact meaning of "component" is determined by the host +[environment](#environment) and one or more [component +managers](#component-manager). + +In the VM, the only assumption made about components is that they have an +associated template. Host environments define the JavaScript component API, if +any, so in [Glimmer.js](https://www.glimmerjs.com) you define subclasses of +`@glimmer/component`'s `Component` class, while in +[Ember.js](https://www.emberjs.com) you extend the `Ember.Component` base class. + +A component is defined once (see [`ComponentDefinition`](#componentdefinition)) +but can be instantiated and used multiple times. Each instance may receive data +from a parent component, and each instance has its own private component state. + +Components can update automatically when state changes. The exact mechanism for +change tracking is up to the host environment. + +For example, Ember.js uses key-value observing (KVO) to detect changes while +Glimmer.js uses [tracked +properties](https://glimmerjs.com/guides/tracked-properties). Using the +low-level [`Reference`](#reference) API, host environments could additionally +model Angular-style dirty checking, React-style `setState()`, and more. + +## `ComponentCapabilities` + +A `ComponentCapabilities` object describes the runtime features required for a +particular component. Glimmer uses this information to perform optimizations +that would not be possible if the capabilities were not known ahead of time. + +For example, in Ember, a component can dynamically set its `layout` property at +runtime to give itself a different template. In Glimmer.js, changing a +component's template is not allowed, so the compiler can inline the template +into the bytecode instead of having to look it up at runtime and performing +additional compilation on the client. + +See also: [`ComponentCapabilities` interface][component-capabilities-source] + +[component-capabilities-source]: ../packages/@glimmer/interfaces/lib/component-capabilities.d.ts + +## `ComponentDefinition` + +A `ComponentDefinition` is a data structure that represents a component +implementation. No matter how many instances of a particular component are +created, there is just one `ComponentDefinition`. + +A definition contains a reference to a [component manager](#component-manager) +as well as host-specific `state` that is opaque to the VM. The host environment +can include metadata in the definition, and the VM will pass that state back +to the component manager when invoking certain hooks. + +For example, the host environment can register a `ComponentDefinition` for the +`Button` component and store the associated JavaScript component class in the +state. + +When that component is invoked via ` +``` + +## Environment + +Similar to how a component manager configures the behavior of a particular component, +the environment configures how all components behave in a particular host environment. + +For example, the environment can provide alternate implementations of DOM +construction and updating operations. For server-side rendering in Node.js, the +environment is configured to use something like [Simple DOM][simple-dom] instead +of browser DOM which is not available. The environment could theoretically +provide an implementation that maps on to other UI hosts entirely, to enable +something like Glimmer Native, for example. + +[simple-dom]: https://github.com/ember-fastboot/simple-dom + +## Handle + +A handle is a unique integer identifier assigned to external objects referred +to in templates (such as helpers, other components, etc). + +The integer is encoded as operands in the compiled [bytecode](#bytecode). At run +time, the host environment is responsible for exchanging a handle for the +appropriate live JavaScript object. + +See also: [Compiler architecture overview (guide)](./01-introduction.md#compiler) + +## Helper + +A (typically pure) JavaScript function that takes input arguments and produces a +value based on those inputs. If one or more of a helper's inputs change, Glimmer +will reevaluate the helper function and update the DOM appropriately. + +Example with `dasherize` and `formatDate` helpers: + +```hbs +
+ {{formatDate @user.createdAt "MMM Do YY"}} +
+``` + +## Intermediate Representation (IR) + +An intermediate representation, or IR, is a data structure that a compiler uses +internally to represent the program it is compiling. + +An IR differs from an [AST](#abstract-syntax-tree) primarily in that it more +closely resembles the final compiled output, whereas an AST more closely +represents the source code as typed by the developer. + +In Glimmer, the compiler transforms Handlebars AST into a Glimmer IR. The IR +represents the final bytecode output, but is designed to allow additional +optimization passes. + +Once optimization has finished and all of the templates in the program have been +linked together, the final pass transforms IR into binary-encoded bytecode. + +## Iterable + +In the context of Glimmer VM, an `Iterable` is an object that helps the VM +iterate over a list of items (such as an array), detect changes to that list, +and efficiently update the DOM to reflect those changes. + +You can think of an `Iterable` as being like a [`Reference`](#reference) for +iterable objects like arrays, `Map`s, `Set`s, etc. + +## Layout + +A layout is another term for a component's template. Because components can be +invoked with additional content, "layout" helps disambiguate between the +component's template and the template for the passed block. + +For example, if a `Wrapper` component has a template like this: + +```hbs +
{{yield}}
+``` + +We call this the layout template. You might invoke the component like this: + +```hbs + + Hello World! + +``` + +When put together, they look like this: + +```hbs +
+ Hello World! +
+``` + +To avoid confusion, the layout template means the original component template +(the one that contains the `{{yield}}`). + +## Opcode + +An opcode represents an instruction the Glimmer VM should perform. Glimmer +compiles the templates in your program into a sequence of opcodes that, when +executed, create DOM, instantiate component classes, etc. + +Examples of opcodes in the Glimmer virtual machine include: + +* `0x16 Text` - append a DOM `Text` node +* `0x30 PushFrame` - push a new frame on to the stack +* `0x1F FlushElement` - flush a newly-created element to DOM (or stream in SSR case) +* `0x40 CreateComponent` - instantiate a component class and push it on to the stack + +When serialized into Glimmer bytecode, every opcode is represented as a 1-byte +integer. + +## Opcode Compiler + +The opcode compiler transforms the intermediate representation (IR) of a +template into the final sequence of opcode and operand integers. An encoder +turns this array of integers into the Glimmer bytecode file format. + +## Path Reference + +A `PathReference` is a kind of `Reference` that supports creating additional +child `References` via path lookups using the `get()` method. + +See also: [Reference](#reference), [References (guide)][path-reference-guide] + +[path-reference-guide]: ./04-references.md#references-in-glimmer + +## Constant Pool + +The constant pool is a data structure that contains arrays of JavaScript values +that can be referred to by a [handle](#handle). The constant pool is produced +during compilation, and is serialized to JavaScript so that it is available at +run time. By sharing constant values in a pool, the size of compiled templates +can be reduced even further. + +For example, imagine this simple template: + +```hbs +
+
+
+``` + +The bytecode for this template would include two `OpenElement` opcodes, which +construct a new DOM element. + +```assembly +OpenElement "div" +``` + +But this would be inefficient, because we would repeat the string `"div"` many +times in bytecode for most apps. + +Rather than repeating the string multiple times, we instead put it into the +constant pool. We then encode the `div`s in the above template as +bytecode with the same operand in both cases. + +```assembly +; Refer to "div" by handle (integer id), assuming it was assigned id 0 here +OpenElement 0x00 +``` + +In the browser, the string constant pool might look like: + +```js +const STRING_CONSTANTS = ['div']; +``` + +When the VM encounters the `OpenElement` opcode with the handle as the first operand, it will exchange it for the appropriate string value: + +```js +let handle = instruction.operand1; // 0 +let tagName = STRING_CONSTANTS[handle]; +``` + +This particular space-reduction optimization is called [string +interning](https://en.wikipedia.org/wiki/String_interning). + +## Reference + +A `Reference` is a stable object that represents the result of a pure +(side-effect-free) computation, where the result of the computation might change +over time. Glimmer creates references to represent values used in templates so +that they can be efficiently shared across multiple components and efficiently +updated should the underlying value change. + +See also: [References (guide)][path-reference-guide] + +[path-reference-guide]: ./04-references.md#references-in-glimmer + +## Runtime / Run Time + +"The runtime" is the set of Glimmer code that runs in the +user's browser, i.e., at the time the program is run. The terms "VM" and +"runtime" are often used interchangeably, although the VM is just the most +significant part of the runtime. + +It may also be used to describe events that happen after the program has started +running, e.g. "the object is instantiated at run time" or "that is a run-time +concern." + +## Template + +A template is HTML that has been augmented with additional syntax to express +dynamic content and behavior. Glimmer uses [Handlebars][handlebars] syntax for +its templates. + +Typically, every [component](#component) will have an associated template that +is rendered whenever the component is created. + +[handlebars]: http://handlebarsjs.com + +## Virtual Machine + +In the context of Glimmer, a virtual machine (or VM) is a software implementation of a +hardware (or hardware-like) architecture, designed to execute computer programs. + +For example, Java source code is compiled into Java bytecode, which is run on +the platform-independent Java virtual machine (JVM). Any program conforming to +the JVM specification can execute Java bytecode, allowing the same compiled Java +program to run on any platform with a conforming JVM implementation. + +Glimmer VM is an implementation of a compiler that turns Handlebars templates +into bytecode, and a virtual machine that executes those bytecode programs in +the browser and Node.js. + +We call Glimmer a virtual machine because its architecture is modelled on +hardware CPUs. For example, the Glimmer virtual machine is both a stack machine +and a register machine that evaluates a sequence of [opcodes](#opcode). + +In order to optimize over-the-wire size of compiled bytecode, Glimmer's +instruction set implements common tasks of component-based libraries, such as +creating new elements, setting attributes, instantiating components, and more. diff --git a/glimmer-vm/guides/compiler-internals/01-introduction.md b/glimmer-vm/guides/compiler-internals/01-introduction.md new file mode 100644 index 00000000000..9f676e05287 --- /dev/null +++ b/glimmer-vm/guides/compiler-internals/01-introduction.md @@ -0,0 +1,8 @@ +### Table of Contents + +1. [Introduction](./01-introduction.md) +2. [The Heap](./02-heap.md) +3. [Constant Pool](./03-constant-pool.md) +4. [Resolver Delegate](./04-compile-time-resolver-delegate.md) +5. [Handles](./05-handles.md) +6. [Template Compilation](./06-templates.md) diff --git a/glimmer-vm/guides/compiler-internals/02-program-compilation-context.md b/glimmer-vm/guides/compiler-internals/02-program-compilation-context.md new file mode 100644 index 00000000000..4287ca86179 --- /dev/null +++ b/glimmer-vm/guides/compiler-internals/02-program-compilation-context.md @@ -0,0 +1 @@ +# \ No newline at end of file diff --git a/glimmer-vm/guides/development/build-constraints.md b/glimmer-vm/guides/development/build-constraints.md new file mode 100644 index 00000000000..8e94bd664f6 --- /dev/null +++ b/glimmer-vm/guides/development/build-constraints.md @@ -0,0 +1,288 @@ +# Build Constraints and Transformations + +This document explains the comprehensive build constraints, transformations, and code management strategies in Glimmer VM. It serves as a reference for understanding how code is transformed from development to production and as a starting point for further analysis of the build system. + +## Overview + +Glimmer VM uses several categories of code that have different constraints on where they can appear: + +1. **Production Code** - Ships to end users in production builds +2. **Development Code** - Available in development builds for end users +3. **Local Development Code** - Only for Glimmer VM developers, never ships +4. **Build-Time Code** - Used during compilation but not at runtime + +## Code Categories and Constraints + +### 1. import.meta.env + +**What it is**: A de facto standard created by Vite for build-time environment variables. + +**Usage in Glimmer VM**: +- `import.meta.env.DEV` - `true` in development builds, `false` in production +- `import.meta.env.PROD` - `true` in production builds, `false` in development +- `import.meta.env.VM_LOCAL_DEV` - `false` in published builds, `true` in Vite dev server + +**Constraint**: These references are replaced at build time with actual values. The string `import.meta.env` never appears in published builds. + +### 2. VM_LOCAL Flag + +**What it is**: A build-time flag for code that should only run during local Glimmer VM development. + +**Purpose**: Enables expensive debugging features when working on the VM itself. These features never reach published packages (not even development builds). + +**Example Usage**: +```typescript +if (VM_LOCAL) { + // Expensive validation that helps VM developers + validateOpcodeSequence(opcodes); +} +``` + +**Constraint**: Code blocks guarded by `VM_LOCAL` are completely removed from all published builds. The condition and its contents are stripped out. + +### 3. Debug Assertion Functions + +**What they are**: Runtime type checking and validation functions from `@glimmer/debug`: + +- `check(value, checker)` - Validates a value against a type checker +- `expect(value, message)` - Asserts a condition is truthy +- `localAssert(condition, message)` - Development-only assertion +- `unwrap(value)` - Unwraps optional values, throwing if null/undefined + +**Purpose**: Catch bugs during Glimmer VM development by validating assumptions about types and state. + +**Example Usage**: +```typescript +import { check } from '@glimmer/debug'; +import { CheckReference } from './-debug-strip'; + +let definition = check(stack.pop(), CheckReference); +let capturedArgs = check(stack.pop(), CheckCapturedArguments); +``` + +**Constraint**: These function calls are stripped from ALL published builds (both development and production) using a Babel plugin during the build process. + +### 4. Type Checker Functions + +**What they are**: Functions that create runtime type validators: + +- `CheckInterface` - Validates object shape +- `CheckOr` - Union type validation +- `CheckFunction` - Function type validation +- `CheckObject` - Object/WeakMap key validation + +**Purpose**: Define the type constraints used by `check()` calls. + +**Example Usage**: +```typescript +export const CheckReference: Checker = CheckInterface({ + [REFERENCE]: CheckFunction, +}); + +export const CheckArguments = CheckOr(CheckObject, CheckFunction); +``` + +**Constraint**: These should never appear in published builds as they're only used by the stripped `check()` calls. + +### 5. Debug-Only Packages + +Three private packages contain development-only utilities: + +- **@glimmer/debug** - Type checkers, validation utilities, debugging tools +- **@glimmer/constants** - VM opcodes, DOM constants (inlined during build) +- **@glimmer/debug-util** - Debug assertions, platform-specific logging + +**Constraint**: These packages are never published to npm. Import statements for them should never appear in published builds - their contents are either inlined or stripped during compilation. + +## Build Process and Transformations + +### Debug Code Stripping + +The build process uses a Babel plugin (`@glimmer/local-debug-babel-plugin`) that: + +1. Identifies imports from `@glimmer/debug` +2. Tracks which debug functions are imported +3. Strips or transforms the function calls: + - `check(value, checker)` → `value` + - `expect(...)` → removed entirely + - `CheckInterface(...)` → `() => true` + - `recordStackSize()` → removed entirely + +### Environment Variable Replacements + +The Rollup replace plugin performs these build-time replacements: + +**Production builds:** +- `import.meta.env.MODE` → `"production"` +- `import.meta.env.DEV` → `false` +- `import.meta.env.PROD` → `true` +- `import.meta.env.VM_LOCAL_DEV` → `false` + +**Development builds:** +- `import.meta.env.MODE` → `"development"` +- `import.meta.env.DEV` → `DEBUG` (with `import { DEBUG } from '@glimmer/env'` injected) +- `import.meta.env.PROD` → `!DEBUG` +- `import.meta.env.VM_LOCAL_DEV` → `false` (becomes `true` only in Vite dev server) + +### Module Resolution and Bundling + +The build system has specific rules for what gets inlined vs treated as external: + +**Always Inlined:** +- `@glimmer/local-debug-flags` +- `@glimmer/constants` +- `@glimmer/debug` +- `@glimmer/debug-util` +- Relative imports (`.`, `/`, `#`) +- TypeScript helper library (`tslib`) + +**Always External:** +- `@handlebars/parser` +- `simple-html-tokenizer` +- `babel-plugin-debug-macros` +- Other `@glimmer/*` packages (to avoid duplication) +- `@simple-dom/*` packages +- `@babel/*` packages +- Node.js built-ins (`node:*`) + +### Build Output Structure + +Every package produces multiple build artifacts: + +1. **Development Build** (`dist/dev/`) + - Readable, formatted code + - Preserves comments + - No variable name mangling + - Includes source maps + +2. **Production Build** (`dist/prod/`) + - Minified with Terser (3 passes) + - Aggressive optimizations + - Preserves `debugger` statements (for `{{debugger}}` helper) + - Includes source maps + +3. **Type Definitions** (`dist/{dev,prod}/*.d.ts`) + - Generated from TypeScript source + - Rolled up into single files per entry point + +4. **CommonJS Build** (optional, `*.cjs`) + - Only generated if package.json includes CommonJS exports + - Follows same dev/prod split + +## TypeScript Configuration and Strictness + +Glimmer VM uses a multi-tiered TypeScript configuration system: + +### Configuration Files +- `tsconfig.base.json` - Shared base configuration +- `tsconfig.json` - Development configuration (looser for better DX) +- `tsconfig.dist.json` - Distribution configuration (stricter for published code) + +### Per-Package Strictness Levels + +Packages can declare their strictness level in `package.json`: +```json +{ + "repo-meta": { + "strictness": "strict" | "loose" + } +} +``` + +This affects which TypeScript compiler options are applied during type checking. + +### Key Compiler Constraints +- **Target**: ES2022 +- **Module Resolution**: "bundler" mode +- **Isolated Modules**: Required for build performance +- **Exact Optional Properties**: Enforced in distribution builds +- **No Unchecked Indexed Access**: Enforced in distribution builds + +## Build Orchestration + +### Turbo Pipeline + +The build system uses Turbo for orchestration with these key relationships: +- `prepack` must complete before any builds +- Type checking runs in parallel with builds +- Cache keys include TypeScript configs, source files, and lock files + +### Build Commands +- `pnpm repo:prepack` - Build all packages via Turbo (recommended) +- `pnpm repo:lint:types` - Type check all packages +- `pnpm clean` - Clean build artifacts + +### Package Publishing + +**Published Package Structure**: +- Only `dist/` directory is included in npm packages +- Conditional exports for dev/prod builds +- `publint` validates package structure before publishing + +**Export Configuration**: +```json +{ + "exports": { + ".": { + "development": "./dist/dev/index.js", + "default": "./dist/prod/index.js" + } + } +} +``` + +Note: Private packages (`@glimmer/debug`, `@glimmer/constants`, `@glimmer/debug-util`, and all `@glimmer-workspace/*`) are never published to npm. + +## Continuous Integration Constraints + +### Bundle Size Monitoring +- Automated size tracking via GitHub Actions +- Compares dev/prod sizes against main branch +- Reports size changes in PR comments +- Uses `dust` utility for accurate measurements + +### Test Environment Constraints +- **Browser Tests**: Puppeteer with specific Chrome flags +- **Smoke Tests**: 300s timeout (vs 30s for regular tests) +- **BrowserStack**: Cross-browser testing for releases +- **Floating Dependencies**: Special CI job tests against latest deps + +### Validation Steps +1. Type checking (`tsc`) +2. Linting (`eslint`) +3. Unit tests (QUnit/Vitest) +4. Smoke tests +5. Bundle size analysis +6. Package structure validation (`publint`) + +## Development Environment + +### Vite Development Server +- Transforms `import.meta.env.VM_LOCAL_DEV` → `true` for local development +- Pre-bundles test dependencies for performance +- Custom extension resolution order + +### ESLint Configuration +- Environment-aware rules (console vs non-console packages) +- Strictness based on package metadata +- Test-specific rules for QUnit +- Custom rules for Glimmer-specific patterns + +### Automated Code Fixes +Tools in `bin/fixes/`: +- `apply-eslint-suggestions.js` - Apply ESLint auto-fixes +- `apply-ts-codefixes.js` - Apply TypeScript code fixes +- `apply-suggestions.js` - Apply both types of fixes + +## Guidelines for Developers + +1. **Use debug assertions liberally** - They help catch bugs and document assumptions +2. **Don't wrap debug code in conditions** - The build process handles removal +3. **Import from the right place** - Use `@glimmer/debug` imports in VM code +4. **Trust the build process** - Write clear development code; the build makes it production-ready +5. **Respect package boundaries** - Don't import from private packages in public ones +6. **Follow strictness levels** - Adhere to the TypeScript strictness of your package + +## Summary + +The Glimmer VM build system enables developers to write defensive, well-instrumented code during development while shipping minimal, performant code to production. Through multiple layers of transformations, validations, and constraints, it ensures debug code never reaches users while maintaining a fast and helpful development experience. \ No newline at end of file diff --git a/glimmer-vm/guides/development/debug-assertions.md b/glimmer-vm/guides/development/debug-assertions.md new file mode 100644 index 00000000000..275f1eb047b --- /dev/null +++ b/glimmer-vm/guides/development/debug-assertions.md @@ -0,0 +1,62 @@ +# Debug Assertions in Glimmer VM + +## Overview + +Glimmer VM uses debug assertion functions to validate assumptions and catch errors during development. These functions are essential for maintaining code quality but must never appear in published packages. + +## Debug Functions + +The following functions from `@glimmer/debug` are for local development only: + +- `check(value, checker)` - Validates a value against a type checker (e.g., `CheckReference`, `CheckString`) +- `expect(value, message)` - Throws with message if value is falsy +- `localAssert(condition, message)` - Throws with message if condition is false +- `unwrap(value)` - Returns value if truthy, throws if null/undefined +- `recordStackSize()` - Records stack size for debugging (completely removed in builds) + +## Usage Example + +```typescript +import { check } from '@glimmer/debug'; +import { CheckReference, CheckCapturedArguments } from './-debug-strip'; + +// In your VM opcode implementation: +let definition = check(stack.pop(), CheckReference); +let capturedArgs = check(stack.pop(), CheckCapturedArguments); + +// Type checkers validate specific shapes: +// CheckReference - validates the value is a Glimmer Reference +// CheckCapturedArguments - validates captured arguments structure +``` + +## Build Process + +These debug calls are automatically stripped from all builds using a Babel plugin. The transformation works as follows: + +### Source Code (what you write): +```typescript +let value = check(stack.pop(), CheckReference); +``` + +### Published Build (what gets shipped): +```typescript +let value = stack.pop(); +``` + +## Important Notes + +1. **Write debug assertions freely** - They help catch bugs during development +2. **Don't wrap in conditions** - The build process handles removal automatically +3. **Never in published code** - Debug stripping ensures this +4. **For VM developers only** - These are not part of the public API + +## How It Works + +The build system automatically removes all debug assertions: + +1. The Babel plugin (`@glimmer/local-debug-babel-plugin`) runs during build +2. It identifies all imports from `@glimmer/debug` +3. It strips or transforms the function calls appropriately +4. Both development and production builds have debug code removed + +This ensures that while developers can use these assertions freely during development, end users never pay the cost of these checks in any published builds. \ No newline at end of file diff --git a/glimmer-vm/guides/embedding/01-introduction.md b/glimmer-vm/guides/embedding/01-introduction.md new file mode 100644 index 00000000000..3353794fbdf --- /dev/null +++ b/glimmer-vm/guides/embedding/01-introduction.md @@ -0,0 +1,8 @@ +# The Embedding API + +- AOT Embedding API +- JIT Embedding API + +Both of the Embedding APIs reduce the amount of JavaScript that the browser compiles and runs by transporting data structures over the wire and executing binary bytecode stored a typed array. + +This means that no matter how many templates an application uses, there is no additional JavaScript code for the browser to parse and compile. diff --git a/glimmer-vm/guides/embedding/02-minimum-environment.md b/glimmer-vm/guides/embedding/02-minimum-environment.md new file mode 100644 index 00000000000..485a9157cec --- /dev/null +++ b/glimmer-vm/guides/embedding/02-minimum-environment.md @@ -0,0 +1,199 @@ +# Some Context + +## Strict Mode + +The embedding guide assumes an embedding that uses Glimmer's strict mode, largely for explanatory convenience. + +## AOT Mode + +Glimmer has two compilation modes: AOT and JIT. In AOT mode, all components are compiled before any components are executed. In JIT mode, components are compiled on demand once they are encountered. + +When compiling in JIT mode, the compiler inserts extra opcodes before component or block invocation to ensure that the code is compiled. When compiling in AOT mode, the compiler knows the offset for all compiled components ahead of time, and simply stores the offsets in the opcodes directly. + +The first part of this embedding guides uses the AOT mode, which means that we'll be compiling all components that we want to use before executing them. A subsequent guide will describe how to adapt the examples for JIT mode. + +## Host Independent Example + +The basic semantics of variable bindings are host-independent. + +```hbs +{{#let "hello" "world" as |hello world|}} +

{{hello}} {{world}}

+{{/let}} +``` + +This component defines two variables: `hello` (initialized to the string `"hello"`) and `world` (initialized to the string `"world"`). + +Because this component is host-agnostic, we can compile and execute it without supplying any of the host-specified behavior. The first part of the embedding guide will use this example so we can learn how the basic machinery of the Embedding API works. + +# Let's Get Going + +## Compilation + +First, we create a minimal "compilation context" by calling `Context()`. + +```ts +import { Context } from '@glimmer/opcode-compiler'; + +let context = Context(); +``` + +The compilation context is used to compile all of the components in our entire program. Once we're done compiling components, we'll serialize the context into bytecode that we can use to execute our components. + +Next, we'll need to turn our source code into a compilable component: + +```ts +import { Component } from '@glimmer/opcode-compiler'; +import { precompile } from '@glimmer/compiler'; // Component() expects a serialized/precompiled template + +let source = ` +{{#let "hello" "world" as |hello world|}} +

{{hello}} {{world}}

+{{/let}} +`; + +let component = Compilable(source); + +function Compilable(source: string): CompilableProgram { + return Component(precompile(source)); +} +``` + +Finally, we'll compile our component using the compilation context we created. + +```ts +let handle = component.compile(context); +``` + +A "handle" is a 32-bit integer that refers to a compiled component. We'll use it later to invoke this component. + +For this minimal example, we're done compiling components, so let's serialize our context into bytecode. + +```ts +import { artifacts } from '@glimmer/program'; + +let program = artifacts(context); +``` + +A "program" is an object with two properties: + +- `heap`: the serialized binary representation of the program we compiled +- `constants`: a constant pool, used to store strings and other small, serializable values that are referred to by opcodes in the program + +Under normal circumstances, we'd serialize the program into a file and ship it over the wire to the browser. For the sake of this exercise, let's execute our program in node instead. + +# Runtime + +## The DOM + +Glimmer's internals work against a small subset of the DOM's interfaces called SimpleDOM. + +Unlike a Virtual DOM, Glimmer's DOM subset uses the exact same interface as the DOM itself: `createElement`, `setAttribute` and a few more exotic methods like `setAttributeNS` and `insertAdjacentHTML`. This subset allows Glimmer's internals to work directly against the real DOM when it's available, while clearly providing a specification of the subset to target for situations where the real DOM is not available. + +The Ember project maintains an implementation of the SimpleDOM interfaces (the `@simple-dom` npm packages), which it uses in [FastBoot][fastboot], Ember's server-side rendering solution. Unlike JSDOM, `simple-dom` is a minimal implementation of the DOM's data structures--just enough to be able to fully create and update DOM trees. This keeps the implementation compact and efficient. + +[fastboot]: https://ember-fastboot.com/ + +Since we're running in node, let's use `simple-dom` to create a document to render our component into. + +```ts +import createHTMLDocument from '@simple-dom/document'; + +let document = createHTMLDocument(); +``` + +## The Runtime Environment + +Next, we need to hydrate the compilation artifacts into a `RuntimeContext`. The `RuntimeContext` is used by the VM to execute compiled components. + +```ts +import { AotRuntime } from '@glimmer/runtime'; + +let runtime = AotRuntime(document, payload); +``` + +## Getting Ready to Execute + +Next, we'll create an element to execute our component into using our SimpleDOM document: + +```ts +let element = document.createElement('main'); +``` + +Glimmer renders components into a `Cursor`, which is an element _and_ a `nextSibling`. This is important if you want to render your component into the middle of an existing element. + +In our case, we just want to append into our new `
` element: + +```ts +let cursor = { element, nextSibling: null }; +``` + +The `Cursor` interface matches the API signature of `insertBefore`, which is the primitive SimpleDOM API that Glimmer uses to insert elements into the DOM. + +## Executing + +Finally, let's execute our compiled template. Since we're using the AOT mode, we call `renderAot` with the runtime, the handle to the component to execute, and the cursor to render into. + +```ts +import { renderAot } from '@glimmer/runtime'; + +let iterator = renderAot(runtime, handle, cursor); +``` + +## Scheduling + +In production implementations, you would want to render the component in chunks, to avoid janking the browser as rendering proceeds. Therefore, the `renderAot` method returns a JavaScript Iterator that you can use to break apart the rendering into pieces. + +For the sake of this guide, let's just run the iterator synchronously. + +```ts +let result = iterator.sync(); +``` + +In addition to exhausting the iterator, the `sync()` method invokes lifecycle hooks on objects that need them. In this simple case, there are no lifecycle hooks to run. + +# All Together Now + +```ts +import { Component, Context } from '@glimmer/opcode-compiler'; +import { artifacts } from '@glimmer/program'; +import { precompile } from '@glimmer/compiler'; +import createHTMLDocument from '@simple-dom/document'; +import { AotRuntime, renderAot } from '@glimmer/runtime'; + +let source = `{{#let "hello" "world" as |hello world|}}

{{hello}} {{world}}

{{/let}}`; + +let context = Context(); +let component = Compilable(source); +let handle = component.compile(context); + +let program = artifacts(context); + +let document = createHTMLDocument(); +let runtime = AotRuntime(document, payload); +let element = document.createElement('main'); +let cursor = { element, nextSibling: null }; +let iterator = renderAot(runtime, handle, cursor); +let result = iterator.sync(); + +function Compilable(source: string): CompilableProgram { + return Component(precompile(source)); +} +``` + +Finally, let's serialize our element into a string so we can look at it in the console. `@simple-dom/serializer` will take an object that implements SimpleDOM and turn it into a string: + +```ts +import Serializer from '@simple-dom/serializer'; +import voidMap from '@simple-dom/void-map'; + +let serialized = new Serializer(voidMap).serialize(element); + +function serialize(element: SimpleElement): string { + return new Serializer(voidMap).serialize(element); + +} +console.log(serialize(element)); + +//

hello world

+``` diff --git a/glimmer-vm/guides/embedding/03-adding-state.md b/glimmer-vm/guides/embedding/03-adding-state.md new file mode 100644 index 00000000000..44334f2a565 --- /dev/null +++ b/glimmer-vm/guides/embedding/03-adding-state.md @@ -0,0 +1,137 @@ +We now have a fully self-contained Glimmer component executing, but things get interesting when we add state to the equation. + +# Previously + +As a reminder, here's the minimal environment we used in the previous chapter: + +```ts +import { Component, Context } from '@glimmer/opcode-compiler'; +import { precompile } from '@glimmer/compiler'; +import createHTMLDocument from '@simple-dom/document'; +import { AotRuntime, renderAot } from '@glimmer/runtime'; +import Serializer from '@simple-dom/serializer'; +import voidMap from '@simple-dom/void-map'; + +let source = `{{#let "hello" "world" as |hello world|}}

{{hello}} {{world}}

{{/let}}`; + +let context = Context(); +let component = Component(precompile(source)); +let handle = component.compile(context); + +let program = artifacts(context); + +let document = createHTMLDocument(); +let runtime = AotRuntime(document, payload); +let element = document.createElement('main'); +let cursor = { element, nextSibling: null }; +let iterator = renderAot(runtime, handle, cursor); +let result = iterator.sync(); + +console.log(serialize(element)); //

hello world

+ +function serialize(element: SimpleElement): string { + return new Serializer(voidMap).serialize(element); +} + +function Compilable(source: string): CompilableProgram { + return Component(precompile(source)); +} +``` + +# Adding State + +To create state, we need a place to put it. + +The simplest way to do that is the `State` function. The `State` function takes an initial value and can be updated. + +To use our new state, we pass it as the final parameter to `renderAot`. When passed to `renderAot` in this way, it's available in the component as `this`. + +```diff +import { Component, Context } from '@glimmer/opcode-compiler'; +import { artifacts } from '@glimmer/program'; +import { precompile } from '@glimmer/compiler'; +import createHTMLDocument from '@simple-dom/document'; +import { AotRuntime, renderAot } from '@glimmer/runtime'; +import Serializer from '@simple-dom/serializer'; +import voidMap from '@simple-dom/void-map'; ++ import { State } from '@glimmer/references'; + +let source = ` + {{#let "hello" "world" as |hello world|}} +-

{{hello}} {{world}}

++

{{hello}} {{world}}{{this.prefix}}

+ {{/let}} +`; + +let context = Context(); +let component = Compilable(source)); +let handle = component.compile(context); + +let program = artifacts(context); + +let document = createHTMLDocument(); +let runtime = AotRuntime(document, payload); +let element = document.createElement('main'); ++ let state = State({ prefix: '!' }); +let cursor = { element, nextSibling: null }; +- let iterator = renderAot(runtime, handle, cursor); ++ let iterator = renderAot(runtime, handle, cursor, state); +let result = iterator.sync(); + +- console.log(serialize(element)); //

hello world

++ console.log(serialize(element)); //

hello world!

+ +function serialize(element: SimpleElement): string { + return new Serializer(voidMap).serialize(element); +} + +function Compilable(source: string): CompilableProgram { + return Component(precompile(source)); +} +``` + +To update the state, we use the `update()` method on it and then call `rerender()` on the result we got from rendering the first time. + +```diff +@@ -90,20 +90,12 @@ +let iterator = renderAot(runtime, handle, cursor, state); +let result = iterator.sync(); + +console.log(serialize(element)); //

hello world!

+ ++ state.update({ prefix: '?' }); ++ result.rerender(); ++ ++ console.log(serialize(element)); //

hello world?

+ +function serialize(element: SimpleElement): string { + return new Serializer(voidMap).serialize(element); +} +``` + +# References + +Now that we've seen some mutable state in action, it's time to learn how Glimmer interacts with external data. + +Glimmer's core primitive interface for working with external data is called `Reference`, and the easiest way to understand it is to look at the interface definition: + +```ts +export interface Reference { + value(): T; + get(key: string): Reference; + tag: Tag; +} + +export interface Tag { + value(): number; + validate(snapshot: number): boolean; +} +``` + +The `Reference`'s `value` method returns the current value that the `Reference` represents. + +The `Reference's` `get` method returns a new refrence that represents a child property in the underlying data. + +A `Tag` is used as a validator for the underlying data held by the reference. The tag's `value` method returns the current revision of the underlying data. The tag's `validate` method takes a revision that it previously returned from `value`, and returns `true` if the underlying data held by the reference is still up-to-date. + +The `State` function from the previous section has an implementation of this interface, but it's only one implementation. APIs described throughout the embedding guide will use References, and a later section will show how to implement a Reference for custom data structures like immutable.js. diff --git a/glimmer-vm/guides/embedding/04-external-helpers.md b/glimmer-vm/guides/embedding/04-external-helpers.md new file mode 100644 index 00000000000..cc32e2d7b41 --- /dev/null +++ b/glimmer-vm/guides/embedding/04-external-helpers.md @@ -0,0 +1,178 @@ +# Previously + +```ts +import { Component, Context } from '@glimmer/opcode-compiler'; +import { artifacts } from '@glimmer/program'; +import { precompile } from '@glimmer/compiler'; + +let source = ` + {{#let "hello" "world" as |hello world|}} +

{{hello}} {{world}}{{this.prefix}}

+ {{/let}} +`; + +let context = Context(); +let component = Compilable(source)); +let handle = component.compile(context); + +let program = artifacts(context); + +function Compilable(source: string): CompilableProgram { + return Component(precompile(source)); +} + +import createHTMLDocument from '@simple-dom/document'; +import { AotRuntime, renderAot } from '@glimmer/runtime'; +import Serializer from '@simple-dom/serializer'; +import voidMap from '@simple-dom/void-map'; +import { State } from '@glimmer/references'; + +let document = createHTMLDocument(); +let runtime = AotRuntime(document, program); +let main = document.createElement('main'); +let state = State({ prefix: '!' }); +let cursor = { element: main, nextSibling: null }; +let iterator = renderAot(runtime, handle, cursor, state); +let result = iterator.sync(); + +console.log(serialize(element)); +//

hello world!

+ +state.update({ prefix: '?' }); +result.rerender(); +console.log(serialize(element)); +//

hello world?

+ +function serialize(element: SimpleElement): string { + return new Serializer(voidMap).serialize(element); +} +``` + +# Computation + +We now have a component executing with some external, mutable state. But what if we want to introduce external computation into the mix? + +In Glimmer, that's the job of "helpers". Helpers are functions that take arguments as references and return a single reference. + +Let's make a global helper `increment` that takes a single number as a positional argument and increments it. + +```hbs +

{{increment 10}}

+``` + +Here's the definition of the helper: + +```ts +import { map } from '@glimmer/reference'; + +function increment(args: VMArguments): Reference { + let input = args.positional.at(0); + return map(ref, i => i + 1); +} +``` + +The Handlebars invocation syntax has both positional and named arguments. For convenience, Glimmer helpers take their arguments bundled together in a single object with `positional` and `named` properties. + +# Compile Time and Runtime Interaction + +The compiled binary represents a call to a helper as a single 64-bit number (e.g. `0x00100002`). That 64-bit number has two components: + +- `0x0010` - the opcode for `Helper` +- `0x0002` - an encoded handle to a runtime function + +The job of your `ResolverDelegate` is to convert a global helper name into a handle, and the job of your `RuntimeResolver` is to convert that handle back into a helper at runtime. + +The simplest way to support a helper in Glimmer is to hardcode the mapping between handles and their associated functions. + +Let's add `increment` to our environment by hardcoding its handle to `0`. + +```ts +const RESOLVER_DELEGATE = { + lookupHelper(name: string): Option { + if (name === 'increment') return 0; + + return null; + }, +}; +``` + +When the compiler sees a call to the `{{increment}}` helper in the program, it asks the `ResolverDelegate` for a handle, which it stores in the program. At runtime, it asks the `RuntimeResolver` to turn the handle into a helper function. + +Our `RuntimeResolver` implementation also hardcodes the mapping from `0` back to our `increment` helper. + +```ts +const RUNTIME_RESOLVER = { + resolve(handle: number) { + if (handle === 0) { + return increment; + } + }, +}; + +function increment(args: VMArguments): Reference { + let arg = args.positional.at(0); + return map(arg, i => i + 1); +} +``` + +Now let's update our program to use the `ResolverDelegate` in the compiler and the `RuntimeResolver` at runtime. + +```diff +let source = ` + {{#let "hello" "world" as |hello world|}} +

{{hello}} {{world}}{{this.prefix}}

+ {{/let}} +`; + +- let context = Context(); ++ let context = Context(RESOLVER_DELEGATE); +let component = Compilable(source); +let handle = component.compile(context); + +let program = artifacts(context); +``` + +```diff +import createHTMLDocument from '@simple-dom/document'; +import { AotRuntime, renderAot } from '@glimmer/runtime'; +import Serializer from '@simple-dom/serializer'; +import voidMap from '@simple-dom/void-map'; +import { State } from '@glimmer/references'; + +let document = createHTMLDocument(); +- let runtime = Runtime(document, payload); ++ let runtime = Runtime(document, payload, RUNTIME_RESOLVER); +let main = document.createElement('main'); +let state = State({ prefix: '!' }); +let cursor = { element: main, nextSibling: null }; +``` + +And finally, let's update our template to use the `increment` helper: + +```diff +let source = ` + {{#let "hello" "world" as |hello world|}} +-

{{hello}} {{world}}{{this.prefix}}

++

{{hello}} {{world}}{{this.prefix}} (count: {{increment this.count}})

+ {{/let}} +`; +``` + +```diff +- let state = State({ prefix: '!' }); ++ let state = State({ prefix: '!', count: 5 }); +let cursor = { element: main, nextSibling: null }; +let iterator = renderAot(runtime, handle, cursor, state); +let result = iterator.sync(); + +console.log(serialize(element)); +- //

hello world!

++ //

hello world! (count: 6)

+ +- state.update({ prefix: '?' }); ++ state.update({ prefix: '?', count: 10 }); +result.rerender(); +console.log(serialize(element)); +- //

hello world?

++ //

hello world? (count: 11)

+``` diff --git a/glimmer-vm/guides/embedding/05-components.md b/glimmer-vm/guides/embedding/05-components.md new file mode 100644 index 00000000000..b2065f69fda --- /dev/null +++ b/glimmer-vm/guides/embedding/05-components.md @@ -0,0 +1,135 @@ +# Previously + +```ts +import { Component, Context } from '@glimmer/opcode-compiler'; +import { artifacts } from '@glimmer/program'; +import { precompile } from '@glimmer/compiler'; + +/// COMPILATION + +let source = ` + {{#let "hello" "world" as |hello world|}} +

{{hello}} {{world}}{{this.prefix}} (count: {{increment this.count}})

+ {{/let}} +`; + +const RESOLVER_DELEGATE = { + lookupHelper(name: string): Option { + if (name === 'increment') return 0; + + return null; + }, +}; + +let context = Context(RESOLVER_DELEGATE); +let component = Compilable(source); +let handle = component.compile(context); + +let program = artifacts(context); + +function Compilable(source) { + return Component(precompile(source)); +} + +/// RUNTIME + +import createHTMLDocument from '@simple-dom/document'; +import { AotRuntime, renderAot } from '@glimmer/runtime'; +import Serializer from '@simple-dom/serializer'; +import voidMap from '@simple-dom/void-map'; +import { State, map } from '@glimmer/references'; + +const RUNTIME_RESOLVER = { + resolve(handle: number) { + if (handle === 0) { + return increment; + } else { + throw new Error(`Unexpected handle ${handle}`); + } + }, +}; + +function increment(args: VMArguments): Reference { + let arg = args.positional.at(0); + return map(arg, i => i + 1); +} + +let document = createHTMLDocument(); +let runtime = AotRuntime(document, payload, RUNTIME_RESOLVER); +let main = document.createElement('main'); +let state = State({ prefix: '!', count: 5 }); +let cursor = { element: main, nextSibling: null }; +let iterator = renderAot(runtime, handle, cursor, state); +let result = iterator.sync(); + +console.log(serialize(element)); +//

hello world! (count: 6)

+ +state.update({ prefix: '?', count: 10 }); +result.rerender(); +console.log(serialize(element)); +//

hello world? (count: 11)

+ +function serialize(element: SimpleElement): string { + return new Serializer(voidMap).serialize(element); +} +``` + +# Other Components + +A single component plus some helpers is nice and all, but real programs have more than one component. + +Global components work similarly to global helpers: the `ResolverDelegate` turns a component name into a handle, and the runtime takes that handle and produces the component. + +```ts +// New imports: +import { MINIMAL_CAPABILITIES } from '@glimmer/opcode-compiler'; +import { TEMPLATE_ONLY_COMPONENT } from '@glimmer/runtime'; + +// A map of helpers to runtime handles (that will be passed to the runtime resolver). +const HELPERS = { + increment: 0, +}; + +// A map of components to their source code and the runtime handle (that will be passed +// to the runtime resolver). +const COMPONENTS: Dict<{ source: string; handle: number }> = { + Second: { + source: `

{{@hello}} {{@world}}{{@suffix}} ({{increment @num}})

`, + handle: 1, + }, +}; + +// Used to make lookup by the RuntimeResolver straightforward +const TABLE = [ + increment, // 0 + TEMPLATE_ONLY_COMPONENT // 1 +]; + +const RESOLVER_DELEGATE: ResolverDelegate = { + lookupComponent(name: string): Option | void { + let component = COMPONENTS[name]; + if (component === null) return null; + + let { handle, source } = component; + + return { + handle, + compilable: Compilable(source), + capabilities: MINIMAL_CAPABILITIES, + }; + }, + + lookupHelper(name: keyof typeof HELPERS): Option | void { + if (name in HELPERS) return HELPERS[name]; + }, +}; + +const RUNTIME_RESOLVER: RuntimeResolver = { + resolve(handle:number): ResolvedValue | void { + if (handle < TABLE.length) { + return TABLE[handle]; + } + } +}; +``` diff --git a/glimmer-vm/guides/embedding/80-path-references.md b/glimmer-vm/guides/embedding/80-path-references.md new file mode 100644 index 00000000000..e69de29bb2d diff --git a/glimmer-vm/guides/embedding/90-syntax.md b/glimmer-vm/guides/embedding/90-syntax.md new file mode 100644 index 00000000000..1151556c3e0 --- /dev/null +++ b/glimmer-vm/guides/embedding/90-syntax.md @@ -0,0 +1,34 @@ +# Glimmer Syntax Basics + +Glimmer's syntax is relatively small. + +## Expressions + +**Literals**: + +- numbers, e.g. `1` and `1.5` +- strings, e.g. `'some text'` and `"some text"` +- booleans: `true` and `false` +- `null` +- `undefined` + +**VariableReference**: + +- `this` +- `Identifier` (the usual identifier characters, plus `-`, `?` and `!`) +- `"@" Identifier` + +**MemberAccess**: + +- _VariableReference_ "." _Identifier_ +- _MemberAccess_ "." _Identifier_ + +(effectively a _variable reference_ followed by "." and then N "." separated identifiers) + +**Call**: + +- "(" _VariableReference_ Expression\* NamedArg\* ")" + +**NamedArg**: + +- _Identifier_ "=" _Expression_ diff --git a/glimmer-vm/guides/embedding/91-aot.md b/glimmer-vm/guides/embedding/91-aot.md new file mode 100644 index 00000000000..dce475fe280 --- /dev/null +++ b/glimmer-vm/guides/embedding/91-aot.md @@ -0,0 +1 @@ +# The AOT Embedding API diff --git a/glimmer-vm/guides/embedding/92-jit.md b/glimmer-vm/guides/embedding/92-jit.md new file mode 100644 index 00000000000..3bac1b901ef --- /dev/null +++ b/glimmer-vm/guides/embedding/92-jit.md @@ -0,0 +1,15 @@ +# The JIT Embedding API + +This version of the API is currently used by Ember as of Ember 3.7. + +Pros: + +- Allows an application to ship a relatively compact representation of the template (the [Wire Format][wire-format]), which is useful for extremely bandwidth-constrained environments. +- Allows an application to compile templates on demand + +Cons: + +- Requires an application to ship the [Wire Format][wire-format] +- Requires the compilation of the Wire Format at runtime + +[wire-format]: ./04-wire-format.md diff --git a/glimmer-vm/guides/embedding/93-wire-format.md b/glimmer-vm/guides/embedding/93-wire-format.md new file mode 100644 index 00000000000..e69de29bb2d diff --git a/glimmer-vm/guides/reactivity/autotracked-rendering.md b/glimmer-vm/guides/reactivity/autotracked-rendering.md new file mode 100644 index 00000000000..5646bb62b5c --- /dev/null +++ b/glimmer-vm/guides/reactivity/autotracked-rendering.md @@ -0,0 +1,102 @@ +# Autotracked Rendering + +An explanation of the depths of the reactivity system we've been using and refining since Ember Octane (ember-source 3.13+). + +### Walkthrough: setting a value + +Given: +```gjs +import { tracked } from '@glimmer/tracking'; + +class ModuleState { + @tracked count = 0; + + increment() { + this.count++; + } +} + +const state = new ModuleState(); + + +``` + +And we +1. observe a render, +2. and then click the button, + - and then observe the output count update. + +How does it work? + +There are a few systems at play for autotracking: +- [tags][^vm-tags] +- [global context][^ember-global-context] +- the environment / delegate +- some [glue code][^ember-renderer] that [configures][^ember-renderer-revalidate] the [timing specifics][^ember-renderer-render-transaction] of when to [render updates][^ember-renderer-render-roots] +- the actual [call to the VM to render][^ember-root-state-render] + + +[^vm-tags]: https://github.com/glimmerjs/glimmer-vm/blob/d86274816a21c61fbc82059006fe7687ca17dc7e/packages/%40glimmer/validator/lib/validators.ts#L1 +[^ember-global-context]: https://github.com/emberjs/ember.js/blob/132b66a768a9cabd461908682ef331f35637d5e9/packages/%40ember/-internals/glimmer/lib/environment.ts#L21 +[^ember-renderer]: https://github.com/emberjs/ember.js/blob/132b66a768a9cabd461908682ef331f35637d5e9/packages/%40ember/-internals/glimmer/lib/renderer.ts#L613C1-L614C1 +[^ember-renderer-revalidate]: https://github.com/emberjs/ember.js/blob/132b66a768a9cabd461908682ef331f35637d5e9/packages/%40ember/-internals/glimmer/lib/renderer.ts#L626 +[^ember-renderer-render-transaction]: https://github.com/emberjs/ember.js/blob/132b66a768a9cabd461908682ef331f35637d5e9/packages/%40ember/-internals/glimmer/lib/renderer.ts#L573 +[^ember-renderer-render-roots]: https://github.com/emberjs/ember.js/blob/132b66a768a9cabd461908682ef331f35637d5e9/packages/%40ember/-internals/glimmer/lib/renderer.ts#L524 +[^ember-root-state-render]: https://github.com/emberjs/ember.js/blob/132b66a768a9cabd461908682ef331f35637d5e9/packages/%40ember/-internals/glimmer/lib/renderer.ts#L156 + +#### 1. leading up to observing a render + +- **render** + - call `renderMain()` from glimmer-vm + - this creates a [VM instance and a TemplateIterator](https://github.com/glimmerjs/glimmer-vm/blob/d86274816a21c61fbc82059006fe7687ca17dc7e/packages/%40glimmer/runtime/lib/render.ts#L59) + - tell the [renderer to render](https://github.com/emberjs/ember.js/blob/132b66a768a9cabd461908682ef331f35637d5e9/packages/%40ember/-internals/glimmer/lib/renderer.ts#L165-L168) + 1. [executes the VM](https://github.com/glimmerjs/glimmer-vm/blob/d86274816a21c61fbc82059006fe7687ca17dc7e/packages/%40glimmer/runtime/lib/render.ts#L32) + 2. iterates over blocks / defers to [_execute](https://github.com/glimmerjs/glimmer-vm/blob/d86274816a21c61fbc82059006fe7687ca17dc7e/packages/%40glimmer/runtime/lib/vm/append.ts#L728) + 3. [evaluate opcodes](https://github.com/glimmerjs/glimmer-vm/blob/d86274816a21c61fbc82059006fe7687ca17dc7e/packages/%40glimmer/runtime/lib/vm/append.ts#L770) + 4. this brings us to the [low-level VM](https://github.com/glimmerjs/glimmer-vm/blob/main/packages/%40glimmer/runtime/lib/vm/low-level.ts#L167) + 5. the low-level VM is the actual VirtualMachine which inteprets all our opcodes -- it iterates until there are no more opcodes + +- **read: count** + - access `count`, which `@tracked`'s getter [defers to `trackedData`](https://github.com/emberjs/ember.js/blob/132b66a768a9cabd461908682ef331f35637d5e9/packages/%40ember/-internals/metal/lib/tracked.ts#L155C28-L155C39) + - the [`trackedData`](https://github.com/emberjs/ember.js/blob/132b66a768a9cabd461908682ef331f35637d5e9/packages/%40ember/-internals/metal/lib/tracked.ts#L5) is in `@glimmer/validator` instead of using tags _directly_. + - `trackedData` calls `consumeTag` when [the value is access](https://github.com/glimmerjs/glimmer-vm/blob/main/packages/%40glimmer/validator/lib/tracked-data.ts#L15) + - `consumeTag` adds the tag to the [`CURRENT_TRACKER`](https://github.com/glimmerjs/glimmer-vm/blob/main/packages/%40glimmer/validator/lib/tracking.ts#L116) + - this is so that when any `{{ }}` regions of a template "detect" a dirty tag, they can individually re-render + + + - [valueForRef](https://github.com/glimmerjs/glimmer-vm/blob/main/packages/%40glimmer/reference/lib/reference.ts#L155) + - called by _many_ opcode handlers in the VM, in this case: [this APPEND_OPCODE](https://github.com/glimmerjs/glimmer-vm/blob/main/packages/%40glimmer/runtime/lib/compiled/opcodes/content.ts#L88) + - [track](https://github.com/glimmerjs/glimmer-vm/blob/main/packages/%40glimmer/validator/lib/tracking.ts#L232) + - calls [beginTrackFrame](https://github.com/glimmerjs/glimmer-vm/blob/d86274816a21c61fbc82059006fe7687ca17dc7e/packages/%40glimmer/validator/lib/tracking.ts#L58) and the corresponding `endTrackFrame()` + +- **render a button with modifier** + - for demonstration purposes, this phase is skipped in this explanation, as this document is more about auto-tracking, and less so about how elements and event listeners get wired up + +#### 2. click the button + +- `increment()` + - **read: count** + - reading is part of `variable++` behavior + - **set: count** + - we dirty the tag [via `@tracked`'s setter](https://github.com/emberjs/ember.js/blob/132b66a768a9cabd461908682ef331f35637d5e9/packages/%40ember/-internals/metal/lib/tracked.ts#L171) + + - `scheduleRevalidate()` is called by `dirtyTag()`, which then defers to ember to call these things and interacts with the scheduler (we go back to step 1): + - **env.begin** + - **env.rerender** + - **read: count** + - **env.commit** + +the output, `count` is rendered as `1` + + +### A minimal renderer + +[JSBin, here](https://jsbin.com/mobupuh/edit?html,output) + +> [!CAUTION] +> This is heavy in boilerplate, and mostly private API. This 300 line *minimal* example, should be considered our todo list, as having all this required to render a tiny component is _too much_. + + diff --git a/glimmer-vm/guides/reactivity/index.md b/glimmer-vm/guides/reactivity/index.md new file mode 100644 index 00000000000..1fe355f8ce9 --- /dev/null +++ b/glimmer-vm/guides/reactivity/index.md @@ -0,0 +1,37 @@ +# The Glimmer Reactivity System + +## Table of Contents + +1. [Tag Composition](./tag-composition.md): The formal composition semantics of Glimmer's tag-based + validation system. +2. [The Fundamental Laws of Reactivity](./laws.md): A definition of Glimmer's reliable and + consistent reactive programming model, and the rules that reactive abstractions must + satisfy in order to safely support this model. +3. [System Phases](./system-phases.md): A description of the phases of the Glimmer execution model: + _action_, _render_, and _idle_, and how the exeuction model supported batched _UI_ updates while + maintaining a _coherent_ data model. +4. [Reactive Abstractions](./reactive-abstractions.md): A description of the implementation of + a number of reactive abstractions, and how they satisfy the laws of reactivity. +5. [Autotracked Rendering](./autotracked-rendering.md): An overview of the + details of how rendering and autotracking interplay. + +### Pseudocode + +This directory also contains pseudocode for the foundation of a reactive system that satisfies these +requirements, and uses them to demonstrate the implementation of the reactive abstractions. + +- [`tags.ts`](./pseudocode/tags.ts): A simple implementation of the tag-based validation system, + including an interface for a runtime that supports tag consumptions and tracking frames. +- [`primitives.ts`](./pseudocode/primitives.ts): Implementation of: + - `Snapshot`, which captures a value at a specific revision with its tag validator. + - `PrimitiveCell` and `PrimitiveCache`, which implement a primitive root storage and a primitive + cached computation, both of which support law-abiding snapshots. +- [`composition.ts`](./pseudocode/composition.ts): Implementations of the higher-level reactive + constructs described in [Reactive Abstractions](./reactive-abstractions.md) in terms of the + reactive primitives. + +> [!TIP] +> +> While these are significantly simplified versions of the production primitives that ship with +> Ember and Glimmer, they serve as clear illustrations of how to implement reactive abstractions +> that satisfy the reactive laws. diff --git a/glimmer-vm/guides/reactivity/laws.md b/glimmer-vm/guides/reactivity/laws.md new file mode 100644 index 00000000000..bc0f00ecdb7 --- /dev/null +++ b/glimmer-vm/guides/reactivity/laws.md @@ -0,0 +1,81 @@ +# The Fundamental Laws of Reactivity + +## ♾ The Fundamental Axiom of Reactivity + +> ### "A reactive abstraction must provide both the current value and a means to detect invalidation without recomputation." + +From the perspective of a Glimmer user, this axiom enables writing reactive code using standard +JavaScript functions and getters that automatically reflect the current state of UI inputs. + +**Glimmer users write UI code as straightforward rendering functions**, yet the system behaves _as +if_ these functions re-execute completely whenever any reactive value changes. + +> [!IMPORTANT] +> +> When root state is mutated, all reactive abstractions reflect those changes immediately, even when +> implemented with caching. Glimmer's reactive values are _always coherent_ — changes are never +> batched in ways that would allow inconsistencies between computed values and their underlying root +> state. + +## Definitions + +- **Root Reactive State**: An atomic reactive value that can be updated directly. It is represented + by a single [value tag](./concepts.md#value-tag). You can create a single piece of root state + explicitly using the `cell` API, but containers from `tracked-builtins` and the storage created by + the `@tracked` decorator are also root reactive state. +- **Formula**: A reactive computation that depends on a number of reactive values. A formula's + revision is the most recent revision of any of the members used during the last computation (as a + [combined tag](./concepts.md#combined-tag)). A + formula will _always_ recompute its output if the revision of any of its members is advanced. +- **Snapshot**: A _snapshot_ of a reactive abstraction is its _current value_ at a specific + revision. The snapshot _invalidates_ when the abstraction's tag has a more + recent revision. _A reactive abstraction is said to _invalidate_ when any previous snapshots would + become invalid._ + +## The Fundamental Laws of Reactivity + +In order to satisfy the _Fundamental Axiom of Reactivity_, all reactive abstractions must adhere to these six laws: + +1. **Dependency Tracking**: A reactive abstraction **must** [invalidate](#invalidate) when any + reactive values used in its _last computation_ have changed. _The revision of the tag associated + with the reactive abstraction must advance to match the revision of its most recently + updated member._ + +2. **Value Coherence**: A reactive abstraction **must never** return a cached _value_ from a + revision older than its current revision. _After a root state update, any dependent reactive + abstractions must recompute their value when next snapshotted._ + +3. **Transactional Consistency**: During a single rendering transaction, a reactive abstraction + **must** return the same value and revision for all snapshots taken within that transaction. + +4. **Snapshot Immutability**: The act of snapshotting a reactive abstraction **must not** + advance the reactive timeline. _Recursive snapshotting (akin to functional composition) naturally + involves tag consumption, yet remains consistent with this requirement as immutability applies + recursively to each snapshot operation._ + +5. **Defined Granularity**: A reactive abstraction **must** define a contract specifying its + _invalidation granularity_, and **must not** invalidate more frequently than this contract + permits. When a reactive abstraction allows value mutations, it **must** specify its equivalence + comparison method. When a new value is equivalent to the previous value, the abstraction **must + not** invalidate. + +All reactive abstractions—including built-in mechanisms like `@tracked` and `createCache`, existing +libraries such as `tracked-toolbox` and `tracked-builtins`, and new primitives like `cell`—must +satisfy these six laws to maintain the Fundamental Axiom of Reactivity when these abstractions are +composed together. + +> [!TIP] +> +> In practice, the effectiveness of reactive composition is bounded by the **Defined Granularity** and **Specified Equivalence** of the underlying abstractions. +> +> For instance, if a [`cell`](#cell) implementation defines granularity at the level of JSON serialization equality, then all higher-level abstractions built upon it will inherit this same granularity constraint. +> +> The laws do not mandate comparing every value in every _computation_, nor do they require a +> uniform approach to equivalence based solely on reference equality. Each abstraction defines its +> own appropriate granularity and equivalence parameters. +> +> For developers building reactive abstractions, carefully selecting granularity and equivalence +> specifications that align with user mental models is crucial—users will experience the system +> through these decisions, expecting UI updates that accurately reflect meaningful changes in their +> application state. +> diff --git a/glimmer-vm/guides/reactivity/pseudocode/composition.ts b/glimmer-vm/guides/reactivity/pseudocode/composition.ts new file mode 100644 index 00000000000..c667a4d4053 --- /dev/null +++ b/glimmer-vm/guides/reactivity/pseudocode/composition.ts @@ -0,0 +1,123 @@ +import { PrimitiveCache, PrimitiveCell, type Status } from './primitives'; +import { runtime, MutableTag, type Tag } from './tags'; + +export class LocalCopy { + #upstream: PrimitiveCache; + #local: PrimitiveCell; + + constructor(compute: () => T) { + this.#upstream = new PrimitiveCache(compute); + this.#local = new PrimitiveCell(); + } + + /** + * Safely return the value of the upstream computation or the local cell, whichever is more + * recent. This satisfies the laws of reactivity transitively through `mostRecent`. + */ + read(): T { + return mostRecent(this.#upstream.snapshot(), this.#local.unsafeSnapshot()).value; + } + + /** + * Safely write a value to the local cell during the "action" phase. + */ + write(value: T): void { + this.#local.write(value); + } +} + +/** + * Safely returns the most recent status from the given statuses. If there are multiple status with + * the same, latest revision, the first such status in the list will be returned. + * + * This satisfies the transactionality law because we consume all tags in all cases, which means + * that: + * + * > The value of the most recent status cannot change after the `MostRecent` was computed in the + * > same rendering transaction, because a change to any of the specified statuses would trigger a + * > backtracking assertion. + * + * The granularity of `mostRecent` is: the call to `mostRecent` will invalidate when the tags of any + * of the statuses passed to it invalidate. This is as granular as possible because a change to any + * of the tags would, by definition, make it the most recent. + */ +function mostRecent, ...Status[]]>(...statuses: S): S[number] { + const [first, ...rest] = statuses; + runtime.consume(first.tag); + + return rest.reduce((latest, status) => { + runtime.consume(latest.tag); + return status.tag.revision > latest.tag.revision ? status : latest; + }, first); +} + +export function tracked( + _value: ClassAccessorDecoratorTarget, + context: ClassAccessorDecoratorContext +): ClassAccessorDecoratorResult { + // When the field is initialized, initialize a mutable tag to represent the root storage. + context.addInitializer(function (this: This) { + MutableTag.init(this, context.name); + }); + + return { + get(this: This): V { + // When the field is accessed, consume the tag to track the read, and return the underlying + // value stored in the field. + const tag = MutableTag.get(this, context.name); + tag.consume(); + return context.access.get(this); + }, + + set(this: This, value: V): void { + // When the field is written, update the tag to track the write, and update the underlying + // value stored in the field. + const tag = MutableTag.get(this, context.name); + context.access.set(this, value); + tag.update(); + }, + }; +} + +const COMPUTE = new WeakMap, () => unknown>(); + +declare const FN: unique symbol; +type FN = typeof FN; +type Cache = { + [FN]: () => T; +}; + +export function createCache(fn: () => T): Cache { + const cache = {} as Cache; + let last = undefined as { value: T; tag: Tag; revision: number } | undefined; + + COMPUTE.set(cache, () => { + if (last && last.revision >= last.tag.revision) { + runtime.consume(last.tag); + return last.value; + } + + runtime.begin(); + try { + const result = fn(); + const tag = runtime.commit(); + last = { value: result, tag, revision: runtime.current() }; + runtime.consume(tag); + return result; + } catch { + last = undefined; + } + }); + + return cache; +} + +export function getCache(cache: Cache): T { + const fn = COMPUTE.get(cache); + + if (!fn) { + throw new Error('You must only call `getCache` with the return value of `createCache`'); + } + + return fn() as T; +} diff --git a/glimmer-vm/guides/reactivity/pseudocode/primitives.ts b/glimmer-vm/guides/reactivity/pseudocode/primitives.ts new file mode 100644 index 00000000000..05c8856ec2b --- /dev/null +++ b/glimmer-vm/guides/reactivity/pseudocode/primitives.ts @@ -0,0 +1,105 @@ +import { type Tag, MutableTag, runtime } from './tags'; + +export class PrimitiveCell { + readonly #tag: MutableTag = MutableTag.init(this, 'value'); + #value: T; + + /** + * Unsafely read the value of the cell. This is unsafe because it exposes the raw value of the tag + * and the last value of the cell, but relies on the caller to ensure that the tag is consumed if + * the abstraction needs to invalidate when the cell changes. + * + * Callers of `unsafeSnapshot` must satisfy the transactionality law by consuming the tag whenever a + * change to the value would result in a change to the computed value of the abstraction. + */ + unsafeSnapshot(): Snapshot { + return Snapshot.of({ value: this.#value, tag: this.#tag }); + } + + write(value: T): void { + this.#tag.update(); + this.#value = value; + } +} +export type Status = { value: T; tag: Tag }; +type Last = { value: T; tag: Tag; revision: number }; + +export class Snapshot { + static of(status: Status): Snapshot { + return new Snapshot({ value: status.value, tag: status.tag }); + } + readonly #value: T; + readonly #tag: Tag; + readonly #revision: number; + + private constructor({ value, tag }: Status) { + this.#value = value; + this.#tag = tag; + this.#revision = tag.revision; + } + + get tag(): Tag { + return this.#tag; + } + + get value(): T { + return this.#value; + } +} + +export class PrimitiveCache { + readonly #compute: () => T; + #last: Last; + + constructor(compute: () => T) { + this.#compute = compute; + + // A `PrimitiveCache` must always be initialized with a value. If all of the primitives used + // inside of a `PrimitiveCache` are compliant with the Fundamental Laws of Reactivity, then + // initializing a cache will never change the revision counter. + this.read(); + } + + /** + * Unsafely read the status of the cache. This is unsafe because it exposes the raw value of the + * tag and the last value of the cache, but relies on the caller to ensure that the tag is + * consumed if the abstraction needs to invalidate when the cache changes. + * + * Callers of `unsafeSnapshot` must satisfy the transactionality law by consuming the tag whenever a + * change to the value would result in a change to the computed value of the abstraction. + */ + snapshot(): Snapshot { + return Snapshot.of(this.#last); + } + + /** + * Safely read the value of the cache. This satisfies the transactionality law because: + * + * 1. If the cache is valid, then it will return the last value of the cache. This is guaranteed + * to be the same value for all reads in the same rendering transaction because any mutations + * to any _members_ of the last tag will trigger a backtracking assertion. + * 2. If the cache is invalid, then the previous value of the cache is thrown away and the + * computation is run again. Any subsequent reads from the cache will return the same value + * because of (1). + */ + read(): T { + if (this.#last && this.#last.revision >= this.#last.tag.revision) { + runtime.consume(this.#last.tag); + return this.#last.value; + } + + runtime.begin(); + try { + const result = this.#compute(); + const tag = runtime.commit(); + this.#last = { value: result, tag, revision: runtime.current() }; + runtime.consume(tag); + return result; + } catch (e) { + // This is possible, but not currently modelled at all. The approach used by the error + // recovery branch that was not merged is: tags are permitted to capture errors, and + // value abstractions expose those errors in their safe read() abstractions. + throw e; + } + } +} diff --git a/glimmer-vm/guides/reactivity/pseudocode/tags.ts b/glimmer-vm/guides/reactivity/pseudocode/tags.ts new file mode 100644 index 00000000000..a6a23005225 --- /dev/null +++ b/glimmer-vm/guides/reactivity/pseudocode/tags.ts @@ -0,0 +1,81 @@ +const TAGS = new WeakMap>(); + +export interface Tag { + get revision(): number; +} + +interface Runtime { + /** + * Consumes a tag in the current tracking frame, if one is active. + */ + consume(tag: Tag): void; + + /** + * Returns the timeline's current revision. + */ + current(): number; + + /** + * Advances the revision counter, returning the new revision. + */ + advance(): number; + + /** + * Begins a new tracking frame. All `consume` operations that happen after this will be + * associated with the new frame. + */ + begin(): void; + + /** + * Ends the current tracking frame, returning a tag that contains all of the members that were + * consumed in the duration of the frame. If a previous frame exists, it will become the current + * frame, and it will consume the returned tag. + */ + commit(): Tag; +} + +export declare const runtime: Runtime; + +export class MutableTag implements Tag { + static init(obj: object, key: PropertyKey): MutableTag { + let tags = TAGS.get(obj); + if (!tags) { + tags = {}; + TAGS.set(obj, tags); + } + + const tag = new MutableTag(); + tags[key] = tag; + return tag; + } + + static get(obj: object, key: PropertyKey): MutableTag { + const tag = TAGS.get(obj)?.[key]; + assert(tag, `No tag found for object ${obj}@${String(key)}`); + return tag; + } + + #revision = runtime.current(); + + get revision(): number { + return this.#revision; + } + + consume(this: MutableTag): void { + runtime.consume(this); + } + + update(this: MutableTag): void { + this.#revision = runtime.advance(); + } +} + +/** + * Asserts an invariant. This function represents code that would be removed in user-facing code, + * because the mechanics of the implementation should enforce the invariant. + */ +function assert(condition: unknown, message: string): asserts condition { + if (!condition) { + throw new Error(message); + } +} diff --git a/glimmer-vm/guides/reactivity/reactive-abstractions.md b/glimmer-vm/guides/reactivity/reactive-abstractions.md new file mode 100644 index 00000000000..02bf4238379 --- /dev/null +++ b/glimmer-vm/guides/reactivity/reactive-abstractions.md @@ -0,0 +1,195 @@ +### `@tracked` + +The `@tracked` accessor creates a single reactive value that that is accessed and mutated through a +JavaScript property. It satisfies the reactivity laws: + +1. **Dependency Tracking**: This requirement is satisfied for root state as long as reads + of the root state consume the same tag that is updated when the root state is changed. It is + trivial to verify that the implementation of `@tracked` satisfies these requirements. + +2. **Value Coherence**: This requirement is also satisfied for root state as long as writes to the + root storage always write to the same JavaScript storage location that is accessed when the root + state is accessed. It is trivial to verify that the implementation of `@tracked` satisfies this + requirement. + +3. **Transactional Consistency**: This requirement is trivially satisfied for root state by Ember's + "backtracking rerender assertion." This assertion ensures that once a reactive value has been + _read_ during a rendering transaction, it cannot be updated again during the same transaction. + +4. **Snapshot Immutability**: In this case, the property is snapshotted when the property is read + and when the tag is consumed by the current tracking frame. It is trivial to verify that the + `get` operation does not advance the timeline. + +5. **Defined Granularity**: The `@tracked` accessor is specified to invalidate whenever the property + is set, regardless of previous or subsequent value. The new value is _never_ considered + equivalent to the previous value. + +
+Pseudo-Implementation of @tracked + +```ts +export function tracked(_value, context) { + context.addInitializer(function () { + ValueTag.init(this, context.name); + }); + + return { + get() { + const tag = ValueTag.get(this, context.name); + tag.consume(); + return context.access.get(this); + }, + + set(value) { + const tag = ValueTag.get(this, context.name); + context.access.set(this, value); + tag.update(); + }, + }; +} +``` + +
+ +### `Cell` + +The new `cell` API satisfies the reactivity laws: + +1. **Dependency Tracking**: This requirement is satisfied for root state as long as reads + of the root state consume the same tag that is updated when the root state is changed. It is + trivial to verify that the implementation of `cell` satisfies these requirements. + +2. **Value Coherence**: This requirement is also satisfied for root state as long as writes to the + root storage always write to the same JavaScript storage location that is accessed when the root + state is accessed. It is trivial to verify that the implementation of `cell` satisfies this + requirement. + +3. **Transactional Consistency**: This requirement is trivially satisfied for root state by Ember's + "backtracking rerender assertion." This assertion ensures that once a reactive value has been + _read_ during a rendering transaction, it cannot be updated again during the same transaction. + +4. **Snapshot Immutability**: In this case, the property is snapshotted when the property is read + and when the tag is consumed by the current tracking frame. It is trivial to verify that the + `get` operation does not advance the timeline. + +5. **Defined Granularity**: When the cell is set, the new value is compared to the previous value for + equivalence using the specified `equals` function. When the new value is equivalent to the + previous value, the cell's tag will _not_ invalidate. + +
+Pseudo-Implementation of the cell constructor + +```ts +export function cell(value, { equals = Object.is } = {}) { + const tag = ValueTag.init(this, 'value'); + + return { + get() { + tag.consume(); + return value; + }, + + set(newValue) { + if (!equals(value, newValue)) { + value = newValue; + tag.update(); + } + }, + }; +} +``` + +
+ +### The `createCache` Primitive API + +The `createCache` primitive API satisfies the reactivity laws: + +1. **Dependency Tracking**: The cache's computation uses `begin()` and `commit()` to automatically + track the reactive values used in the computation. Since the tag returned by `commit` produces + the maximum revision of its members, the cache will invalidate whenever any of the reactive values + used in the computation have changed. + +2. **Value Coherence**: This requirement is satisfied by the cache's implementation, which only + returns a previously cached value if its tag is still valid. When the tag is invalidated, the + cache recomputes its value before returning it, ensuring it never returns a stale value. + +3. **Transactional Consistency**: This requirement is satisfied by consuming the combined tag + during every read, regardless of whether the cache was valid or invalid. Since Ember's backtracking + rerender assertion fires whenever a tag that was previously consumed is updated during the same + rendering transaction, this requirement is enforced. + +4. **Snapshot Immutability**: In this case, snapshotting occurs when `getCache` is called. The + implementation only consumes tags during this operation and doesn't update any tags, ensuring + that reading a cache doesn't advance the timeline. This property holds recursively for the + entire computation, as each reactive value accessed during execution must also + satisfy the same immutability requirement. + +5. **Defined Granularity**: The granularity of the `createCache` API is defined transitively - + the cache invalidates whenever any of its dependencies invalidate, according to their own + granularity rules. The cache itself does not add any additional equivalence checks. + +
+Pseudo-Implementation of createCache + +```ts +const COMPUTE = new WeakMap(); + +export function createCache(fn) { + const cache = {}; + let last = undefined; + + COMPUTE.set(cache, () => { + if (last && last.revision >= last.tag.revision) { + runtime.consume(last.tag); + return last.value; + } + + runtime.begin(); + try { + const result = fn(); + const tag = runtime.commit(); + runtime.consume(tag); + last = { value: result, tag, revision: runtime.current() }; + return result; + } catch { + last = undefined; + } + }); + + return cache; +} + +export function getCache(cache) { + const fn = COMPUTE.get(cache); + + if (!fn) { + throw new Error('You must only call `getCache` with the return value of `createCache`'); + } + + return fn(); +} +``` + +
+ +### The `LocalCopy` Primitive + +> [!NOTE] +> +> This section will be written next. The crux of the matter is that `LocalCopy` satisfies the +> reactivity laws because: +> +> 1. Snapshotting a `LocalCopy` deterministically returns the value that corresponds to the latest +> the upstream computation or the local cell, whichever is more recent. +> 2. Since the backtracking rerender assertion prevents any tag from being updated once it's +> consumed, it is impossible for the choice of upstream computation or local cell to change in +> the same rendering transaction. +> 3. What's weird about `LocalCopy` is that its value is determined in part by the _revision_ of the +> members of the composition, whereas most compositions are determined entirely by the _values_ +> of the members. +> 4. By being explicit about reactivity semantics and the reactivity laws, we can see that +> `LocalCopy` is a safe abstraction despite having a dependency on the revision of the members. + +An implementation of `LocalCopy` exists in [composition.ts](./pseudocode/composition.ts) with +comments that explain how the implementation satisfies the reactivity laws. \ No newline at end of file diff --git a/glimmer-vm/guides/reactivity/system-phases.md b/glimmer-vm/guides/reactivity/system-phases.md new file mode 100644 index 00000000000..345c8bdad9d --- /dev/null +++ b/glimmer-vm/guides/reactivity/system-phases.md @@ -0,0 +1,118 @@ +# Reactive Values + +To allow developers to reason about reactive composition, developers typically interact with +[_tags_](./concepts.md#tags) through higher-level abstractions that represent _reactive values_. + +While reactive tags describe the formal _composition_ semantics of the Glimmer system, "Reactive +Values" describe the rules that higher-level abstractions must follow in order to allow developers +to safely reason about reactive composition. + +## System Phases and the Fundamental Laws + +Glimmer's reactivity system combines three key elements that work together to provide a coherent reactive programming model: + +1. **A Tag-Based Validation System**: As described in [tag-composition.md](./tag-composition.md), Glimmer uses tags to track and validate dependencies without requiring value recomputation. + +2. **The Fundamental Laws of Reactivity**: The [laws](./laws.md) define the contracts that all reactive abstractions must adhere to, ensuring predictable behavior when abstractions are composed. + +3. **System Phases**: The system operates in distinct phases that separate mutation from validation, enabling efficient tracking while preventing inconsistencies. + +These elements combine to create a system where developers can write straightforward JavaScript code while the framework maintains reactivity behind the scenes. The phases of the system, in particular, provide the framework for implementing the laws in practice. + +## System Phases: A Visual Overview + + +```mermaid +--- +config: + theme: base + themeVariables: + primaryColor: "#b9cccc" + secondaryColor: "#ffffff" + tertiaryColor: "#ff0000" + background: "#f9ffff" + lineColor: "#005f5f" + mainBkg: "#9fe9e9" + textColor: "#005f5f" +--- +stateDiagram + direction LR + state ReactiveLoop { + direction LR + Render --> Idle + Idle --> Action + Action --> Render + Render + Idle + Action + } + [*] --> Setup:App Boot + Setup --> Render:Initial Render + ReactiveLoop --> [*]:App cleanup + ReactiveLoop:Reactive Loop + Setup:Setup state + classDef transition fill:red +``` + + +- [Action Phase](#action-phase) +- [Render Phase](#render-phase) +- [Idle Phase](#idle-phase) + +### Action Phase + +The action phase allows app code to update reactive state in response to a system event (such as a +promise resolution) or a user event (such as an input event or button click). + +During this phase, app code is permitted to freely read and write reactive values as if they were +normal JavaScript values. This prepares the reactive state for the next phase, the render phase. + +- Root state can be updated freely, and each update advances the timeline. +- Reactive values can be accessed freely in order to decide how to update the root state. +- Reactive state is always fully coherent: reading from a reactive computation after updating one if + its dependencies will always return a value that is consistent with the current values of its + dependencies. + +### Render Phase + +The render phase updates the UI to reflect any changes to the reactive state. + +This phase is **transactional**, which means that reactive state is _observably frozen_ for the +duration of the render phase. Once a reactive value is accessed during a render transaction, any +subsequent accesses will produce the same value at the same revision. + +To satisfy the requirement that reactive state is _observably frozen_ during a single render phase: + +- Ember's _backtracking rerender assertion_ throws a development-mode exception if a tag that was + consumed during the render transaction is updated again during the transaction. _While this is not + enforced in production, this is a performance optimization, and the system assumes that this + prohibition is upheld._ +- Safe reactive abstractions **must** obey the **Snapshot Immutability** law, which forbids them + from updating any tags during the snapshotting operation. + +### Idle Phase + +The idle phase represents a quiescent state where the UI is fully rendered and consistent with the current reactive state. During this phase: + +- The system is waiting for the next event that will trigger state changes +- No tracking frames are active +- No updates to the reactive timeline occur + +The idle phase ends when an event occurs (user interaction, network response, timer, etc.) and the +event handler updates one or more reactive values (via the `[Update]` operation on a tag). This +transition the system into the **action phase**. + +The system also **schedules the render phase** to run asynchronously after the current JavaScript job +completes (consistent with JavaScript's run-to-completion semantics). + +### Batched Updates with a Coherent Data Model + +As a consequence of this design, all reactive updates that occur within the same JavaScript execution context are naturally batched together and processed in a single upcoming render phase. + +It's important to understand that while updates to the _rendered output_ (UI) are batched, the reactive values _inside_ the system maintain full coherence at all times: + +- There is no delay between updating root state and seeing that update reflected in a computation that depends on it +- When a computation is accessed after its dependencies have changed, it will immediately recompute based on the current values +- This internal coherence ensures that JavaScript code always sees a consistent reactive state, even though UI updates are batched + +This automatic batching ensures optimal performance by preventing cascading rerenders while allowing developers to work with reactive values as if they were normal JavaScript values. From the developer's perspective, reactive computations behave just like normal functions, giving them a familiar programming model with the added benefit of automatic UI updates. diff --git a/glimmer-vm/guides/reactivity/tag-composition.md b/glimmer-vm/guides/reactivity/tag-composition.md new file mode 100644 index 00000000000..db6b52c55bf --- /dev/null +++ b/glimmer-vm/guides/reactivity/tag-composition.md @@ -0,0 +1,47 @@ +# Tag Composition + +Glimmer's reactivity system is founded on a minimal algebraic primitive called _Tag_. Tags operate on a _monotonic revision timeline_ and compose within _tracking frames_. + +Tags intentionally exist as a separate layer from the [reactive values](./reactive-values.md) they represent, creating a clean separation between validation algebra and value semantics. + +> [!NOTE] +> +> This separation distinguishes Glimmer from most reactive systems: Glimmer can validate reactive computations without recomputing values or performing equality comparisons. While this approach doesn't provide reference-equality-based cutoffs for invalidation propagation, it enables reliable fine-grained validation and controlled root-state invalidation through equivalence rules. At scale, this architecture yields significant benefits in predictability and performance. + +## Core Algebraic Primitives + +- **Revision Timeline**: A monotonically increasing sequence where each increment represents an atomic change. The timeline advances in a discrete and monotonic manner, with each new revision strictly greater than all previous revisions. + +- **Tag**: A stateful object that represents a timestamp (revision) on the timeline when its + associated value or computation last changed. _Tags can be retained and later used to determine if + a previously snapshotted value is still valid, without recomputing that value._ + + All tags support the `[Consume]` operation, which records the tag in the current tracking frame when accessed. + +- **Value Tag**: The base tag type that tracks when a single value changes. + +- **Mutable Tag**: A tag that can be explicitly updated with: + - `[Update]`: Advances the timeline and records the new revision as the tag's current revision. + - `[Freeze]`: Marks a tag as immutable, preventing its accesses from being recorded in tracking frames. + +- **Combined Tag**: A tag that represents the join (maximum) of multiple tag revisions. This join operation maintains the algebraic property that if any constituent tag invalidates, the combined tag also invalidates. + +- **Tracking Frame**: A collector that accumulates tags consumed during a computation. The frame has + two operations: + - `[Begin]`: Creates a bounded context for tag collection. + - `[Commit]`: Closes the collection scope and produces a combined tag from the collected tags. + +- **Tracking Stack**: A nested structure of tracking frames representing the current computation hierarchy. Enables compositional reactive tracking across function boundaries. + +## Revision Timeline + +The revision timeline forms the foundation of Glimmer's validation algebra. It consists of: + +- **Initial Revision**: Timeline begins at revision `1`. +- **Constant Revision**: Special revision `0` indicates values that never change. Tags with this revision are not tracked. +- **Timeline Advancement**: Each atomic update advances the global timeline exactly once. +- **Revision Comparison**: Two tags can be compared by examining their respective revisions. + +> [!NOTE] +> +> Revision `0` (constant revision) receives special treatment in the algebra. Tags with revision `0` do not participate in tracking and a frame containing only constant tags is itself considered constant. diff --git a/glimmer-vm/guides/workspace/demos/auto-import.gif b/glimmer-vm/guides/workspace/demos/auto-import.gif new file mode 100644 index 00000000000..8eef139f9b3 --- /dev/null +++ b/glimmer-vm/guides/workspace/demos/auto-import.gif @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:48e4f21badf00542cfb61dfff160aa5941f50771eb60c8a170536ed61a4dad96 +size 3058150 diff --git a/glimmer-vm/guides/workspace/demos/dependency-links.png b/glimmer-vm/guides/workspace/demos/dependency-links.png new file mode 100644 index 00000000000..2334d2b8972 --- /dev/null +++ b/glimmer-vm/guides/workspace/demos/dependency-links.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:77fa6943d1434e86479260d76fde5e1fbc42b020316a8d2847bd892029e86768 +size 61106 diff --git a/glimmer-vm/guides/workspace/demos/dependi-outdated.png b/glimmer-vm/guides/workspace/demos/dependi-outdated.png new file mode 100644 index 00000000000..b217f07a644 --- /dev/null +++ b/glimmer-vm/guides/workspace/demos/dependi-outdated.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f78ae77e2c656483862eb6d01f1eed61cd82aa8cd2edab2dd90c75c2242adcba +size 68208 diff --git a/glimmer-vm/guides/workspace/demos/dependi-update.png b/glimmer-vm/guides/workspace/demos/dependi-update.png new file mode 100644 index 00000000000..d64f1e9d48e --- /dev/null +++ b/glimmer-vm/guides/workspace/demos/dependi-update.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:11f8dc63029058a4c4b66440992d25f10e8fa5bb6a5ef3301d5986e46386a196 +size 136594 diff --git a/glimmer-vm/guides/workspace/demos/fixme.png b/glimmer-vm/guides/workspace/demos/fixme.png new file mode 100644 index 00000000000..d24eaa282fc --- /dev/null +++ b/glimmer-vm/guides/workspace/demos/fixme.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:138d3eacd33eb26221aacdbcd62c0f02af648d0f723b04ebf31a7d2e1e22f21c +size 119864 diff --git a/glimmer-vm/guides/workspace/vscode.md b/glimmer-vm/guides/workspace/vscode.md new file mode 100644 index 00000000000..4d3842caf93 --- /dev/null +++ b/glimmer-vm/guides/workspace/vscode.md @@ -0,0 +1,92 @@ +# Recommended VSCode Workflows + +This file outlines recommendations for developing packages in this repository using Visual Studio +Code (or any other editor based on vscode). + +## Recommended Extensions + +The `.vscode/extensions.json` file lists a number of extensions that help you take the most +advantage of the repository's setup and source code. + +> [!TIP] +> +> Visual Studio Code will notify you if any of the extensions listed in the file are not +> installed. The easiest way to install these extensions is to approve the prompt. Otherwise, you +> will find the extensions listed under "Recommended" in the Extensions view. + +### Format Code Action (`rohit-gohri.format-code-action`) + +This repository is configured to use [code +actions](https://code.visualstudio.com/docs/editor/refactoring#_code-actions-quick-fixes-and-refactorings) +to autofix ESLint issues and format the source code. + +The Format Code Action extension allows us to run prettier as a code action, so we can specify the +order of formatting and lint fixing. + +> [!TIP] +> +> We intentionally don't configure ESLint to run prettier as an autofix, for [reasons described by +> the TypeScript ESLint docs](https://typescript-eslint.io/users/what-about-formatting). +> +> TL;DR The linting cycle, especially with type checking enabled, is much slower than formatting, +> and we want formatting to run instantly even if linting is slow. + +### Prettier (`esbenp.prettier-vscode`) + +This repository is configured to use Prettier as the default formatter for JavaScript, TypeScript, +JSON, Markdown and YAML files. + +Installing this extension will format the source code when you save a source file, before applying +lint fixes. + +### ESLint (`dbaeumer.vscode-eslint`) + +This repository is configured to use ESLint to lint JavaScript, TypeScript, and JSON files. + +This extension will: + +- Give you squiggly lines when you have a lint error. + +> [!NOTE] +> +> Our linting setup makes heavy use of type checking and module resolution, which allows us to +> automate quite a bit of code maintenance via autofixes. +> +> For example, autofixes will automatically sort, group and manage `import type` for you when you +> save. + +
+Autofix Demo + + ![linting](./demos/auto-import.gif) + +
+ +The linting setup will also sort your package.json files to match the consistent repository +standard, remove unnecessary type assertions and generics that match the default, and much, much more. + +### Inline Bookmarks (`tintinweb.vscode-inline-bookmarks`) + +This extension highlights standard repository annotations like `@active`, `@fixme` and `@premerge`. + +See [Standard Annotations](./workspace-management.md#standard-annotations) in `workspace-management.md` for more information. + + ![fixme](./demos/fixme.png) + +### NPM Dependency Links (`herrmannplatz.npm-dependency-links`) + +This extension will turn your dependencies and devDependencies in your `package.json` into links to +the NPM package, which will open the package in the browser. + + ![npm-dependency-links](./demos/dependency-links.png) + +### Dependi (`fill-labs.dependi`) + +This extension will show you whether dependencies are up to date in your `package.json` file. + + ![dependi](./demos/dependi-outdated.png) + +It will also allow you to see the available updated versions and click on them to update the +`package.json` file. + + ![dependi](./demos/dependi-update.png) diff --git a/glimmer-vm/guides/workspace/workspace-management.md b/glimmer-vm/guides/workspace/workspace-management.md new file mode 100644 index 00000000000..3f9b573e847 --- /dev/null +++ b/glimmer-vm/guides/workspace/workspace-management.md @@ -0,0 +1,196 @@ +The repository is organized into a number of packages, each with their own package.json. + +## Workspace Configuration + +The workspace is configured as a [pnpm workspace](https://pnpm.io/workspaces). The package locations +are specified in the `pnpm-workspace.yaml` file. + +### Turbo + +Repository workflows are managed by [Turbo](https://turbo.build). They are defined in the +`turbo.json` file. See [Turbo Workflows](#turbo-workflows) below for more details on the available +workflows. + +### Repo Metadata + +Repository metadata used by workspace tooling is cached in `repo-metadata/metadata.json`. This file +is updated by the repository's `repo:update-metadata` script. This script is a dependency of all +turbo workflows, which ensures that the metadata is up-to-date before running any scripts that +depend on them. + +## Code Packages + +Code packages are in the `packages/` directory. Packages can be authored as `.ts` or `.js` files, +but share a common directory structure. + +- `index.{ext}`: The main entry point for the package. This is the only required source file. +- `lib/**/*.{ext}`: Other source files used or exported by the entry point. +- `test/`: Optional integration tests. The `test/` directory is its own package in the scope + `@glimmer-test/*`. You can find more information about the structure of test packages + below in the [`@glimmer-test/*` Packages](#glimmer-test-packages) section below. + +### `@glimmer/*` Packages + +Packages in the `packages/@glimmer/` directory contain code that is meant to be used by consumers of the +Glimmer VM project. + +#### Published Packages + +A subset of `@glimmer/*` packages are published to NPM. In addition to the common directory +structure for all code packages, published packages have some additional requirements. + +##### Rollup Build + +A rollup-based build script in the `rollup.config.mjs` file. This file is always identical: + +```ts +import { Package } from "@glimmer-workspace/build-support"; + +export default Package.config(import.meta); +``` + +##### `package.json` + +The `package.json` for published packages has some additional requirements: + +- `publishConfig`: points the published package's exports to the `dist` directory. +- `scripts.build`: runs the rollup build: `rollup -c rollup.config.mjs`. This requires dev + dependencies on `@glimmer-workspace/build-support` and `rollup`. +- `scripts.test:publint`: runs `publint`, which verifies that the `package.json` file is prepared + correctly for publishing. This also requires a dev dependency on `publint`. +- `files`: always the `dist` directory + +> [!IMPORTANT] +> +> Packages in the `@glimmer/*` directory with `"private": true` in their `package.json` are inlined +> into _other_ published packages by the build process. The list of inlined packages is currently +> hardcoded in `packages/@glimmer-workspace/build/lib/config.js`, but this will be updated soon to +> use the [`repo-metadata`](#repo-metadata) to automatically inline packages marked private. +> +> You can determine whether a package is published by looking at the `private` field in the +> `package.json` file. + +### `@glimmer-workspace/*` Packages + +Packages in the `packages/@glimmer-workspace/` contain code that will not be published and is used when developing the workspace. + +## Test Packages + +### `@glimmer-test/*` Packages + +Packages in `@glimmer/*` or `@glimmer-workspace/\* + +## Recommended IDE Workflow + +TypeScript and ESLint are intended to automate workflow-wide development standards. + +### Pre-Merge Workspace Annotations + +These annotations are used to organize work during the lifetime of a pull request and should not be +merged to `main`. + +
+
@fixme
+
This represents a problem that should be fixed before merge.
+
@audit
+
You can use this annotation to mark instances of code that +
+ +### Workspace Annotations + +These annotations identify areas of code in a structured way. + +
+
@todo
+
This represents a problem. It should also contain a link to a GitHub issue.
+
+ +> [!NOTE] +> +> Currently, there is no enforcement of the requirements for these annotations. For now, please +> help enforce them in pull request reviews. We will add additional checks to enforce these +> requirements in the future. + +## Repo-Wide Workflows + +Workflows in this section are typically run against all packages in the repository via `turbo`. + +> [!TIP] +> +> Turbo runs commands against all packages in the workspace with the specified script in the +> `package.json` for the package. +> +> This means that commands in the sections below are run against all +> packages with the script specified in the _Runs_ column in their `package.json`. + +### `pnpm repo:prepack` + +| Runs | Depends On | +| -------------------- | -------------- | +| `prepack`, `prepare` | `repo:prepack` | + +Runs the lifecycle scripts `prepack` and `prepare` in each workspace package. This produces the same +`dist` directory as the published packages, which is perfect for verifying the results of the build +process. + +### Linting + +#### `pnpm repo:lint:files` + +| Runs | Depends On | +| -------------- | ---------- | +| `test:publint` | 🛇 Nothing | + +Verifies that all files in the repository are properly linted. + +Runs `pnpm test:lint` in each workspace package. + +#### `pnpm repo:lint:pub` + +| Runs | Depends On | +| -------------- | -------------- | +| `test:publint` | `repo:prepack` | + +Verifies that all **published** packages have the correct metadata for `npm publish`. + +#### `pnpm repo:lint:types` + +| Runs | Depends On | +| ----------------------------------- | ---------- | +| `tsc -b` (once, in workspace scope) | 🛇 Nothing | + +Verifies that all TypeScript files in the repository are properly type-checked. + +> [!NOTE] +> +> In general, `@typescript-eslint` detects many more type errors than `tsc`. However, +> `@typescript-eslint` assumes that it's being run _on top of_ `tsc`, and it's therefore necessary +> to run both `tsc` and `@typescript-eslint` to fully verify that all types are correct. +> +> Since `tsc` is run once for the entire repository, this also means that you get linting feedback +> from type-enhanced lints in the turbo output for a specific package, but all type feedback from +> `tsc` is emitted at once. +> +> When editing files in vscode, both type checking and type-aware linting are integrated seamlessly. + +#### `pnpm repo:lint:all` + +| Depends On | +| ----------------- | +| `repo:lint:files` | +| `repo:lint:pub` | + +A shortcut for running `repo:lint:files` and `repo:lint:pub`. + +#### `pnpm repo:lint:fix` + +| Runs | +| ----------------------------------------------------- | +| `repo:lint:files` (with `--fix` arg for each package) | +| `prettier -w` | + + + +> [!NOTE] +> +> `prettier -w` should really be a `turbo` task, and this should happen as follow-up work soon. diff --git a/glimmer-vm/index.html b/glimmer-vm/index.html new file mode 100644 index 00000000000..44cf6362c9d --- /dev/null +++ b/glimmer-vm/index.html @@ -0,0 +1,17 @@ + + + + + Glimmer Test Suite + + + + + + diff --git a/glimmer-vm/knip.config.js b/glimmer-vm/knip.config.js new file mode 100644 index 00000000000..5244a618aa5 --- /dev/null +++ b/glimmer-vm/knip.config.js @@ -0,0 +1,45 @@ +export default { + ignore: [ + '.reference/**', + 'smoke-tests/**', + 'benchmark/**', + 'guides/**', + // Test files are expected to be unused + '**/test/**', + // Build artifacts + '**/dist/**', + 'ts-dist/**', + ], + ignoreDependencies: [ + // Testing - these are used by test runner + 'puppeteer', + 'puppeteer-chromium-resolver', + 'vitest', + + // Scripts and CLI tools + 'auto-dist-tag', + 'dotenv-cli', + 'tracerbench', + 'zx', + + // Type packages + '@types/node', + + // Monorepo dependencies needed for hoisting + 'typescript', + 'eslint', + 'rollup', + ], + workspaces: { + bin: { + entry: ['*.mts', '*.mjs'], + }, + 'packages/*': { + entry: ['index.{ts,js,mjs}', 'lib/**/*.{ts,js,mjs}'], + ignore: ['test/**', '**/*.d.ts'], + }, + 'packages/*/test': { + entry: [], + }, + }, +}; diff --git a/glimmer-vm/package.json b/glimmer-vm/package.json new file mode 100644 index 00000000000..89c95642e0e --- /dev/null +++ b/glimmer-vm/package.json @@ -0,0 +1,156 @@ +{ + "name": "glimmer-engine", + "version": "0.92.0", + "private": true, + "license": "MIT", + "description": "Glimmer compiles Handlebars templates into document fragments rather than string buffers", + "repository": { + "type": "git", + "url": "git+https://github.com/glimmerjs/glimmer-vm.git" + }, + "author": "Tilde, Inc.", + "type": "module", + "exports": null, + "scripts": { + "benchmark:run": "./bin/ts ./bin/setup-bench.mts", + "benchmark:setup": "./bin/ts ./bin/bench-packages.mts", + "build": "turbo prepack", + "clean": "node ./bin/clean.mjs", + "dev": "vite", + "knip": "knip", + "lint": "eslint . --quiet", + "lint:all": "turbo lint:all", + "lint:check": "prettier -c .", + "lint:fix": "turbo lint -- --fix && prettier -w .", + "lint:published": "turbo test:publint", + "lint:types": "turbo //#test:types", + "postinstall": "./bin/post-install.sh", + "repo:update:conventions": "./bin/ts ./repo-metadata/lib/package-updater.ts", + "repo:update:metadata": "./bin/ts ./repo-metadata/lib/update.ts", + "smoke:setup": "./bin/ts ./smoke-tests/node/setup.ts", + "test": "node bin/run-tests.mjs", + "test:babel-plugins": "pnpm --filter @glimmer/vm-babel-plugins test", + "test:node": "turbo test:node" + }, + "devDependencies": { + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-transform-modules-commonjs": "^7.27.1", + "@babel/plugin-transform-runtime": "^7.28.0", + "@babel/preset-env": "^7.28.0", + "@babel/preset-typescript": "^7.27.1", + "@babel/runtime": "^7.27.6", + "@babel/traverse": "^7.28.0", + "@babel/types": "^7.28.0", + "@eslint-community/eslint-plugin-eslint-comments": "^4.5.0", + "@eslint/config-inspector": "^1.1.0", + "@eslint/js": "9.20.0", + "@glimmer-workspace/benchmark-env": "workspace:*", + "@glimmer-workspace/build-support": "workspace:*", + "@glimmer-workspace/eslint-plugin": "workspace:*", + "@glimmer-workspace/integration-tests": "workspace:*", + "@glimmer-workspace/repo-metadata": "workspace:*", + "@glimmer/env": "workspace:*", + "@rollup/plugin-sucrase": "^5.0.2", + "@rollup/plugin-terser": "^0.4.4", + "@tsconfig/strictest": "^2.0.5", + "@types/babel-plugin-macros": "^3.1.3", + "@types/babel__core": "^7.20.5", + "@types/babel__traverse": "^7.20.7", + "@types/eslint": "^9.6.1", + "@types/eslint-community__eslint-plugin-eslint-comments": "workspace:*", + "@types/eslint-plugin-qunit": "workspace:*", + "@types/eslint__eslintrc": "^2.1.2", + "@types/node": "^22.13.4", + "@types/preval.macro": "^3.0.2", + "@types/qunit": "^2.19.12", + "@typescript-eslint/parser": "^8.35.1", + "@typescript-eslint/utils": "^8.35.1", + "amd-name-resolver": "^1.3.1", + "auto-dist-tag": "^2.1.1", + "babel-plugin-macros": "^3.1.0", + "babel-plugin-strip-glimmer-utils": "^0.1.1", + "chalk": "^5.4.1", + "dag-map": "^2.0.2", + "dotenv-cli": "^7.4.4", + "ensure-posix-path": "^1.1.1", + "eslint": "^9.20.1", + "eslint-config-flat-gitignore": "^1.0.0", + "eslint-config-prettier": "10.0.1", + "eslint-import-resolver-typescript": "^3.8.2", + "eslint-interactive": "^11.1.0", + "eslint-plugin-import": "^2.31.0", + "eslint-plugin-import-x": "^4.6.1", + "eslint-plugin-jsonc": "^2.19.1", + "eslint-plugin-n": "17.15.1", + "eslint-plugin-qunit": "^8.1.2", + "eslint-plugin-regexp": "^2.7.0", + "eslint-plugin-simple-import-sort": "12.1.1", + "eslint-plugin-unused-imports": "4.1.4", + "execa": "^7.2.0", + "fast-glob": "^3.3.3", + "glob": "^10.4.5", + "globals": "^15.15.0", + "js-yaml": "^4.1.0", + "knip": "^5.44.4", + "loader.js": "^4.7.0", + "mkdirp": "^3.0.1", + "prettier": "^3.5.1", + "preval.macro": "^5.0.0", + "puppeteer": "24.11.2", + "puppeteer-chromium-resolver": "^24.0.1", + "qunit": "^2.24.1", + "release-plan": "^0.13.1", + "rimraf": "^5.0.10", + "rollup": "^4.34.8", + "semver": "^7.7.2", + "testem-failure-only-reporter": "^1.0.0", + "toml": "^3.0.0", + "tracerbench": "^8.0.1", + "turbo": "^2.4.2", + "typescript": "^5.7.3", + "typescript-eslint": "^8.24.1", + "vite": "^7.0.2", + "vitest": "^3.0.6", + "zx": "^8.3.2" + }, + "packageManager": "pnpm@10.6.5", + "changelog": { + "repo": "glimmerjs/glimmer-vm", + "labels": { + "breaking": ":boom: Breaking Change", + "enhancement": ":rocket: Enhancement", + "bug": ":bug: Bug Fix", + "documentation": ":memo: Documentation", + "internal": ":house: Internal" + } + }, + "engines": { + "node": ">=22.12.0" + }, + "pnpm": { + "notes": { + "override:@glimmer/syntax": "when we run prettier, we want to use our local copy of prettier, not the one it declared in its package.json. This ensures that we don't accidentally break prettier as we make changes to @glimmer/syntax" + }, + "overrides": { + "@glimmer/syntax": "workspace:*", + "@oclif/plugin-warn-if-update-available": "^3.1.42", + "@rollup/pluginutils": "^5.0.2", + "@types/node": "$@types/node", + "d3-color": "^3.1.0", + "esbuild": "^0.25.0", + "got": "^11.8.5", + "typescript": "$typescript" + }, + "peerDependencyRules": { + "allowAny": [ + "vite-plugin-babel", + "vite" + ], + "allowedVersions": { + "@rollup/pluginutils": "5", + "rollup": "^4.31.0-0", + "typescript": "5" + } + } + } +} diff --git a/glimmer-vm/packages/@types/eslint-community__eslint-plugin-eslint-comments/index.d.ts b/glimmer-vm/packages/@types/eslint-community__eslint-plugin-eslint-comments/index.d.ts new file mode 100644 index 00000000000..91a7af599ef --- /dev/null +++ b/glimmer-vm/packages/@types/eslint-community__eslint-plugin-eslint-comments/index.d.ts @@ -0,0 +1,4 @@ +import type { Linter } from 'eslint'; + +declare const DEFAULT: { configs: { recommended: Linter.Config } }; +export default DEFAULT; diff --git a/glimmer-vm/packages/@types/eslint-community__eslint-plugin-eslint-comments/package.json b/glimmer-vm/packages/@types/eslint-community__eslint-plugin-eslint-comments/package.json new file mode 100644 index 00000000000..7ad830c1d38 --- /dev/null +++ b/glimmer-vm/packages/@types/eslint-community__eslint-plugin-eslint-comments/package.json @@ -0,0 +1,10 @@ +{ + "private": true, + "name": "@types/eslint-community__eslint-plugin-eslint-comments", + "version": "0.92.0", + "exports": "./index.d.ts", + "scripts": {}, + "dependencies": { + "@types/eslint": "^9.6.1" + } +} diff --git a/glimmer-vm/packages/@types/eslint-plugin-import/index.d.ts b/glimmer-vm/packages/@types/eslint-plugin-import/index.d.ts new file mode 100644 index 00000000000..74955a5a41e --- /dev/null +++ b/glimmer-vm/packages/@types/eslint-plugin-import/index.d.ts @@ -0,0 +1,12 @@ +import type { Linter } from 'eslint'; + +interface ImportPlugin { + flatConfigs: { + recommended: Linter.Config; + typescript: Linter.Config; + }; +} + +declare const DEFAULT: ImportPlugin; + +export default DEFAULT; diff --git a/glimmer-vm/packages/@types/eslint-plugin-import/package.json b/glimmer-vm/packages/@types/eslint-plugin-import/package.json new file mode 100644 index 00000000000..00cb79fc3e5 --- /dev/null +++ b/glimmer-vm/packages/@types/eslint-plugin-import/package.json @@ -0,0 +1,11 @@ +{ + "private": true, + "name": "@types/eslint-plugin-import", + "version": "0.92.0", + "type": "module", + "exports": "./index.d.ts", + "scripts": {}, + "dependencies": { + "@types/eslint": "^9.6.1" + } +} diff --git a/glimmer-vm/packages/@types/eslint-plugin-qunit/index.d.ts b/glimmer-vm/packages/@types/eslint-plugin-qunit/index.d.ts new file mode 100644 index 00000000000..301d9144f4d --- /dev/null +++ b/glimmer-vm/packages/@types/eslint-plugin-qunit/index.d.ts @@ -0,0 +1,11 @@ +import type { ESLint } from '@types/eslint'; + +interface QUnitPlugin extends ESLint.Plugin { + configs: { + recommended: ESLint.PluginConfig; + }; +} + +declare const DEFAULT: QUnitPlugin; + +export default DEFAULT; diff --git a/glimmer-vm/packages/@types/eslint-plugin-qunit/package.json b/glimmer-vm/packages/@types/eslint-plugin-qunit/package.json new file mode 100644 index 00000000000..7f8896aec95 --- /dev/null +++ b/glimmer-vm/packages/@types/eslint-plugin-qunit/package.json @@ -0,0 +1,10 @@ +{ + "private": true, + "name": "@types/eslint-plugin-qunit", + "types": "index.d.ts", + "version": "0.92.0", + "scripts": {}, + "dependencies": { + "@types/eslint": "^9.6.1" + } +} diff --git a/glimmer-vm/packages/@types/js-reporters/index.d.ts b/glimmer-vm/packages/@types/js-reporters/index.d.ts new file mode 100644 index 00000000000..4e8ca233c47 --- /dev/null +++ b/glimmer-vm/packages/@types/js-reporters/index.d.ts @@ -0,0 +1,12 @@ +export function autoRegister(): Runner; + +// eslint-disable-next-line @typescript-eslint/no-empty-object-type +export interface Runner {} + +interface Default { + autoRegister: typeof autoRegister; +} + +declare const DEFAULT: Default; + +export default DEFAULT; diff --git a/glimmer-vm/packages/@types/js-reporters/package.json b/glimmer-vm/packages/@types/js-reporters/package.json new file mode 100644 index 00000000000..4e1419c7058 --- /dev/null +++ b/glimmer-vm/packages/@types/js-reporters/package.json @@ -0,0 +1,7 @@ +{ + "private": true, + "name": "@types/js-reporters", + "version": "0.92.0", + "exports": "./index.d.ts", + "scripts": {} +} diff --git a/glimmer-vm/packages/@types/puppeteer-chromium-resolver/index.d.ts b/glimmer-vm/packages/@types/puppeteer-chromium-resolver/index.d.ts new file mode 100644 index 00000000000..a2bd18ee689 --- /dev/null +++ b/glimmer-vm/packages/@types/puppeteer-chromium-resolver/index.d.ts @@ -0,0 +1,11 @@ +import type { launch } from 'puppeteer'; + +interface Resolved { + puppeteer: { launch: typeof launch }; + executablePath: string; +} + +// eslint-disable-next-line @typescript-eslint/no-empty-object-type +declare const pcr: (options: {}) => Promise; + +export default pcr; diff --git a/glimmer-vm/packages/@types/puppeteer-chromium-resolver/package.json b/glimmer-vm/packages/@types/puppeteer-chromium-resolver/package.json new file mode 100644 index 00000000000..66280a4cf2a --- /dev/null +++ b/glimmer-vm/packages/@types/puppeteer-chromium-resolver/package.json @@ -0,0 +1,10 @@ +{ + "private": true, + "name": "@types/puppeteer-chromium-resolver", + "version": "0.92.0", + "exports": "./index.d.ts", + "scripts": {}, + "dependencies": { + "puppeteer": "23.11.1" + } +} diff --git a/glimmer-vm/pnpm-lock.yaml b/glimmer-vm/pnpm-lock.yaml new file mode 100644 index 00000000000..4f3135eeba4 --- /dev/null +++ b/glimmer-vm/pnpm-lock.yaml @@ -0,0 +1,16984 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +overrides: + '@glimmer/syntax': workspace:* + '@rollup/pluginutils': ^5.0.2 + '@types/node': ^22.13.4 + typescript: ^5.7.3 + '@oclif/plugin-warn-if-update-available': ^3.1.42 + d3-color: ^3.1.0 + esbuild: ^0.25.0 + got: ^11.8.5 + +importers: + + .: + devDependencies: + '@babel/plugin-syntax-dynamic-import': + specifier: ^7.8.3 + version: 7.8.3(@babel/core@7.26.0) + '@babel/plugin-transform-modules-commonjs': + specifier: ^7.27.1 + version: 7.27.1(@babel/core@7.26.0) + '@babel/plugin-transform-runtime': + specifier: ^7.28.0 + version: 7.28.0(@babel/core@7.26.0) + '@babel/preset-env': + specifier: ^7.28.0 + version: 7.28.0(@babel/core@7.26.0) + '@babel/preset-typescript': + specifier: ^7.27.1 + version: 7.27.1(@babel/core@7.26.0) + '@babel/runtime': + specifier: ^7.27.6 + version: 7.27.6 + '@babel/traverse': + specifier: ^7.28.0 + version: 7.28.0 + '@babel/types': + specifier: ^7.28.0 + version: 7.28.0 + '@eslint-community/eslint-plugin-eslint-comments': + specifier: ^4.5.0 + version: 4.5.0(eslint@9.20.1(jiti@2.4.2)) + '@eslint/config-inspector': + specifier: ^1.1.0 + version: 1.1.0(eslint@9.20.1(jiti@2.4.2)) + '@eslint/js': + specifier: 9.20.0 + version: 9.20.0 + '@glimmer-workspace/benchmark-env': + specifier: workspace:* + version: link:packages/@glimmer-workspace/benchmark-env + '@glimmer-workspace/build-support': + specifier: workspace:* + version: link:packages/@glimmer-workspace/build + '@glimmer-workspace/eslint-plugin': + specifier: workspace:* + version: link:packages/@glimmer-workspace/eslint-plugin + '@glimmer-workspace/integration-tests': + specifier: workspace:* + version: link:packages/@glimmer-workspace/integration-tests + '@glimmer-workspace/repo-metadata': + specifier: workspace:* + version: link:repo-metadata + '@glimmer/env': + specifier: 0.1.7 + version: 0.1.7 + '@rollup/plugin-sucrase': + specifier: ^5.0.2 + version: 5.0.2(rollup@4.34.8) + '@rollup/plugin-terser': + specifier: ^0.4.4 + version: 0.4.4(rollup@4.34.8) + '@tsconfig/strictest': + specifier: ^2.0.5 + version: 2.0.5 + '@types/babel-plugin-macros': + specifier: ^3.1.3 + version: 3.1.3 + '@types/babel__core': + specifier: ^7.20.5 + version: 7.20.5 + '@types/babel__traverse': + specifier: ^7.20.7 + version: 7.20.7 + '@types/eslint': + specifier: ^9.6.1 + version: 9.6.1 + '@types/eslint-community__eslint-plugin-eslint-comments': + specifier: workspace:* + version: link:packages/@types/eslint-community__eslint-plugin-eslint-comments + '@types/eslint-plugin-qunit': + specifier: workspace:* + version: link:packages/@types/eslint-plugin-qunit + '@types/eslint__eslintrc': + specifier: ^2.1.2 + version: 2.1.2 + '@types/node': + specifier: ^22.13.4 + version: 22.13.4 + '@types/preval.macro': + specifier: ^3.0.2 + version: 3.0.2 + '@types/qunit': + specifier: ^2.19.12 + version: 2.19.12 + '@typescript-eslint/parser': + specifier: ^8.35.1 + version: 8.35.1(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3) + '@typescript-eslint/utils': + specifier: ^8.35.1 + version: 8.35.1(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3) + amd-name-resolver: + specifier: ^1.3.1 + version: 1.3.1 + auto-dist-tag: + specifier: ^2.1.1 + version: 2.1.1 + babel-plugin-macros: + specifier: ^3.1.0 + version: 3.1.0 + babel-plugin-strip-glimmer-utils: + specifier: ^0.1.1 + version: 0.1.1 + chalk: + specifier: ^5.4.1 + version: 5.4.1 + dag-map: + specifier: ^2.0.2 + version: 2.0.2 + dotenv-cli: + specifier: ^7.4.4 + version: 7.4.4 + ensure-posix-path: + specifier: ^1.1.1 + version: 1.1.1 + eslint: + specifier: ^9.20.1 + version: 9.20.1(jiti@2.4.2) + eslint-config-flat-gitignore: + specifier: ^1.0.0 + version: 1.0.0(eslint@9.20.1(jiti@2.4.2)) + eslint-config-prettier: + specifier: 10.0.1 + version: 10.0.1(eslint@9.20.1(jiti@2.4.2)) + eslint-import-resolver-typescript: + specifier: ^3.8.2 + version: 3.8.2(eslint-plugin-import-x@4.6.1(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3))(eslint-plugin-import@2.31.0)(eslint@9.20.1(jiti@2.4.2)) + eslint-interactive: + specifier: ^11.1.0 + version: 11.1.0(eslint@9.20.1(jiti@2.4.2)) + eslint-plugin-import: + specifier: ^2.31.0 + version: 2.31.0(@typescript-eslint/parser@8.35.1(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3))(eslint-import-resolver-typescript@3.8.2)(eslint@9.20.1(jiti@2.4.2)) + eslint-plugin-import-x: + specifier: ^4.6.1 + version: 4.6.1(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3) + eslint-plugin-jsonc: + specifier: ^2.19.1 + version: 2.19.1(eslint@9.20.1(jiti@2.4.2)) + eslint-plugin-n: + specifier: 17.15.1 + version: 17.15.1(eslint@9.20.1(jiti@2.4.2)) + eslint-plugin-qunit: + specifier: ^8.1.2 + version: 8.1.2(eslint@9.20.1(jiti@2.4.2)) + eslint-plugin-regexp: + specifier: ^2.7.0 + version: 2.7.0(eslint@9.20.1(jiti@2.4.2)) + eslint-plugin-simple-import-sort: + specifier: 12.1.1 + version: 12.1.1(eslint@9.20.1(jiti@2.4.2)) + eslint-plugin-unused-imports: + specifier: 4.1.4 + version: 4.1.4(@typescript-eslint/eslint-plugin@8.24.1(@typescript-eslint/parser@8.35.1(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3))(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3))(eslint@9.20.1(jiti@2.4.2)) + execa: + specifier: ^7.2.0 + version: 7.2.0 + fast-glob: + specifier: ^3.3.3 + version: 3.3.3 + glob: + specifier: ^10.4.5 + version: 10.4.5 + globals: + specifier: ^15.15.0 + version: 15.15.0 + js-yaml: + specifier: ^4.1.0 + version: 4.1.0 + knip: + specifier: ^5.44.4 + version: 5.44.4(@types/node@22.13.4)(typescript@5.7.3) + loader.js: + specifier: ^4.7.0 + version: 4.7.0 + mkdirp: + specifier: ^3.0.1 + version: 3.0.1 + prettier: + specifier: ^3.5.1 + version: 3.5.1 + preval.macro: + specifier: ^5.0.0 + version: 5.0.0 + puppeteer: + specifier: 24.11.2 + version: 24.11.2(typescript@5.7.3) + puppeteer-chromium-resolver: + specifier: ^24.0.1 + version: 24.0.1 + qunit: + specifier: ^2.24.1 + version: 2.24.1 + release-plan: + specifier: ^0.13.1 + version: 0.13.1 + rimraf: + specifier: ^5.0.10 + version: 5.0.10 + rollup: + specifier: ^4.34.8 + version: 4.34.8 + semver: + specifier: ^7.7.2 + version: 7.7.2 + testem-failure-only-reporter: + specifier: ^1.0.0 + version: 1.0.0(ejs@3.1.10)(handlebars@4.7.8)(underscore@1.13.7) + toml: + specifier: ^3.0.0 + version: 3.0.0 + tracerbench: + specifier: ^8.0.1 + version: 8.0.1(@swc/core@1.9.3)(@types/node@22.13.4)(typescript@5.7.3) + turbo: + specifier: ^2.4.2 + version: 2.4.2 + typescript: + specifier: ^5.7.3 + version: 5.7.3 + typescript-eslint: + specifier: ^8.24.1 + version: 8.24.1(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3) + vite: + specifier: ^7.0.2 + version: 7.0.2(@types/node@22.13.4)(jiti@2.4.2)(terser@5.43.1)(tsx@4.19.2)(yaml@2.7.0) + vitest: + specifier: ^3.0.6 + version: 3.0.6(@types/node@22.13.4)(jiti@2.4.2)(terser@5.43.1)(tsx@4.19.2)(yaml@2.7.0) + zx: + specifier: ^8.3.2 + version: 8.3.2 + + bin: + dependencies: + '@glimmer-workspace/repo-metadata': + specifier: workspace:* + version: link:../repo-metadata + '@pnpm/workspace.find-packages': + specifier: ^1000.0.10 + version: 1000.0.10(@pnpm/logger@1000.0.0) + '@types/glob': + specifier: ^8.1.0 + version: 8.1.0 + '@types/js-yaml': + specifier: ^4.0.9 + version: 4.0.9 + '@types/node': + specifier: ^22.13.4 + version: 22.13.4 + '@types/puppeteer-chromium-resolver': + specifier: workspace:* + version: link:../packages/@types/puppeteer-chromium-resolver + '@types/tar': + specifier: ^6.1.13 + version: 6.1.13 + chalk: + specifier: ^5.4.1 + version: 5.4.1 + execa: + specifier: ^7.1.1 + version: 7.1.1 + fs-extra: + specifier: ^11.3.0 + version: 11.3.0 + glob: + specifier: ^10.2.3 + version: 10.2.3 + js-yaml: + specifier: ^4.1.0 + version: 4.1.0 + mkdirp: + specifier: ^3.0.1 + version: 3.0.1 + p-map: + specifier: ^7.0.3 + version: 7.0.3 + puppeteer-chromium-resolver: + specifier: ^23.0.0 + version: 23.0.0 + rimraf: + specifier: ^6.0.1 + version: 6.0.1 + strip-ansi: + specifier: ^7.1.0 + version: 7.1.0 + tar: + specifier: ^6.2.0 + version: 6.2.1 + which: + specifier: ^5.0.0 + version: 5.0.0 + zx: + specifier: ^8.3.2 + version: 8.3.2 + devDependencies: + '@pnpm/types': + specifier: ^1000.1.1 + version: 1000.1.1 + '@types/fs-extra': + specifier: ^11.0.4 + version: 11.0.4 + eslint: + specifier: ^9.20.1 + version: 9.20.1(jiti@2.4.2) + esno: + specifier: ^0.16.3 + version: 0.16.3 + type-fest: + specifier: ^4.35.0 + version: 4.35.0 + + packages/@glimmer-workspace/benchmark-env: + dependencies: + '@glimmer/global-context': + specifier: workspace:* + version: link:../../@glimmer/global-context + '@glimmer/manager': + specifier: workspace:* + version: link:../../@glimmer/manager + '@glimmer/opcode-compiler': + specifier: workspace:* + version: link:../../@glimmer/opcode-compiler + '@glimmer/program': + specifier: workspace:* + version: link:../../@glimmer/program + '@glimmer/reference': + specifier: workspace:* + version: link:../../@glimmer/reference + '@glimmer/runtime': + specifier: workspace:* + version: link:../../@glimmer/runtime + '@glimmer/util': + specifier: workspace:* + version: link:../../@glimmer/util + '@glimmer/validator': + specifier: workspace:* + version: link:../../@glimmer/validator + devDependencies: + '@glimmer-workspace/build-support': + specifier: workspace:* + version: link:../build + '@glimmer-workspace/env': + specifier: workspace:* + version: link:../env + '@glimmer/debug-util': + specifier: workspace:* + version: link:../../@glimmer/debug-util + '@glimmer/interfaces': + specifier: workspace:* + version: link:../../@glimmer/interfaces + eslint: + specifier: ^9.20.1 + version: 9.20.1(jiti@2.4.2) + publint: + specifier: ^0.3.2 + version: 0.3.2 + rollup: + specifier: ^4.34.8 + version: 4.34.8 + typescript: + specifier: ^5.7.3 + version: 5.7.3 + + packages/@glimmer-workspace/build: + dependencies: + '@glimmer/local-debug-babel-plugin': + specifier: workspace:* + version: link:../../@glimmer/local-debug-babel-plugin + '@rollup/plugin-babel': + specifier: ^6.0.4 + version: 6.0.4(@babel/core@7.26.0)(@types/babel__core@7.20.5)(rollup@4.34.8) + '@rollup/plugin-commonjs': + specifier: ^28.0.2 + version: 28.0.2(rollup@4.34.8) + '@rollup/plugin-node-resolve': + specifier: ^16.0.0 + version: 16.0.0(rollup@4.34.8) + '@rollup/plugin-replace': + specifier: ^6.0.2 + version: 6.0.2(rollup@4.34.8) + '@rollup/plugin-swc': + specifier: ^0.4.0 + version: 0.4.0(@swc/core@1.9.3)(rollup@4.34.8) + '@rollup/plugin-terser': + specifier: ^0.4.4 + version: 0.4.4(rollup@4.34.8) + '@rollup/plugin-typescript': + specifier: ^12.1.2 + version: 12.1.2(rollup@4.34.8)(tslib@2.8.1)(typescript@5.7.3) + magic-string: + specifier: ^0.30.0 + version: 0.30.0 + postcss: + specifier: ^8.5.3 + version: 8.5.3 + rollup: + specifier: ^4.34.8 + version: 4.34.8 + rollup-plugin-dts: + specifier: ^6.1.1 + version: 6.1.1(rollup@4.34.8)(typescript@5.7.3) + rollup-plugin-insert: + specifier: ^1.3.2 + version: 1.3.2(rollup@4.34.8) + rollup-plugin-polyfill-node: + specifier: ^0.13.0 + version: 0.13.0(rollup@4.34.8) + rollup-plugin-postcss: + specifier: ^4.0.2 + version: 4.0.2(postcss@8.5.3)(ts-node@10.9.2(@swc/core@1.9.3)(@types/node@22.13.4)(typescript@5.7.3)) + tslib: + specifier: ^2.8.1 + version: 2.8.1 + unplugin-fonts: + specifier: ^1.3.1 + version: 1.3.1(vite@6.3.5(@types/node@22.13.4)(jiti@2.4.2)(terser@5.43.1)(tsx@4.19.2)(yaml@2.7.0)) + vite: + specifier: ^6.1.1 + version: 6.3.5(@types/node@22.13.4)(jiti@2.4.2)(terser@5.43.1)(tsx@4.19.2)(yaml@2.7.0) + zx: + specifier: ^8.3.2 + version: 8.3.2 + devDependencies: + '@types/node': + specifier: ^22.13.4 + version: 22.13.4 + eslint: + specifier: ^9.20.1 + version: 9.20.1(jiti@2.4.2) + typescript: + specifier: ^5.7.3 + version: 5.7.3 + + packages/@glimmer-workspace/env: {} + + packages/@glimmer-workspace/eslint-plugin: + dependencies: + '@eslint/eslintrc': + specifier: ^3.2.0 + version: 3.2.0 + '@eslint/js': + specifier: ^9.20.0 + version: 9.20.0 + '@glimmer-workspace/repo-metadata': + specifier: workspace:* + version: link:../../../repo-metadata + '@pnpm/workspace.find-packages': + specifier: ^1000.0.10 + version: 1000.0.10(@pnpm/logger@1000.0.0) + '@typescript-eslint/parser': + specifier: ^8.24.1 + version: 8.24.1(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3) + eslint-config-prettier: + specifier: 10.0.1 + version: 10.0.1(eslint@9.20.1(jiti@2.4.2)) + eslint-plugin-import-x: + specifier: ^4.6.1 + version: 4.6.1(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3) + eslint-plugin-jsonc: + specifier: ^2.19.1 + version: 2.19.1(eslint@9.20.1(jiti@2.4.2)) + eslint-plugin-n: + specifier: ^17.15.1 + version: 17.15.1(eslint@9.20.1(jiti@2.4.2)) + eslint-plugin-qunit: + specifier: ^8.1.2 + version: 8.1.2(eslint@9.20.1(jiti@2.4.2)) + eslint-plugin-regexp: + specifier: ^2.7.0 + version: 2.7.0(eslint@9.20.1(jiti@2.4.2)) + eslint-plugin-simple-import-sort: + specifier: ^12.1.1 + version: 12.1.1(eslint@9.20.1(jiti@2.4.2)) + eslint-plugin-unused-imports: + specifier: ^4.1.4 + version: 4.1.4(@typescript-eslint/eslint-plugin@8.24.1(@typescript-eslint/parser@8.24.1(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3))(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3))(eslint@9.20.1(jiti@2.4.2)) + eslint-utils: + specifier: ^3.0.0 + version: 3.0.0(eslint@9.20.1(jiti@2.4.2)) + typescript-eslint: + specifier: ^8.24.1 + version: 8.24.1(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3) + devDependencies: + '@types/eslint': + specifier: 9.6.1 + version: 9.6.1 + '@types/eslint-utils': + specifier: ^3.0.5 + version: 3.0.5 + '@types/node': + specifier: ^22.13.4 + version: 22.13.4 + eslint: + specifier: ^9.20.1 + version: 9.20.1(jiti@2.4.2) + + packages/@glimmer-workspace/integration-tests: + dependencies: + '@glimmer-workspace/test-utils': + specifier: workspace:* + version: link:../test-utils + '@glimmer/compiler': + specifier: workspace:* + version: link:../../@glimmer/compiler + '@glimmer/destroyable': + specifier: workspace:* + version: link:../../@glimmer/destroyable + '@glimmer/global-context': + specifier: workspace:* + version: link:../../@glimmer/global-context + '@glimmer/interfaces': + specifier: workspace:* + version: link:../../@glimmer/interfaces + '@glimmer/manager': + specifier: workspace:* + version: link:../../@glimmer/manager + '@glimmer/node': + specifier: workspace:* + version: link:../../@glimmer/node + '@glimmer/opcode-compiler': + specifier: workspace:* + version: link:../../@glimmer/opcode-compiler + '@glimmer/owner': + specifier: workspace:* + version: link:../../@glimmer/owner + '@glimmer/program': + specifier: workspace:* + version: link:../../@glimmer/program + '@glimmer/reference': + specifier: workspace:* + version: link:../../@glimmer/reference + '@glimmer/runtime': + specifier: workspace:* + version: link:../../@glimmer/runtime + '@glimmer/syntax': + specifier: workspace:* + version: link:../../@glimmer/syntax + '@glimmer/util': + specifier: workspace:* + version: link:../../@glimmer/util + '@glimmer/validator': + specifier: workspace:* + version: link:../../@glimmer/validator + '@glimmer/vm': + specifier: workspace:* + version: link:../../@glimmer/vm + '@glimmer/wire-format': + specifier: workspace:* + version: link:../../@glimmer/wire-format + '@simple-dom/document': + specifier: ^1.4.0 + version: 1.4.0 + '@simple-dom/serializer': + specifier: ^1.4.0 + version: 1.4.0 + '@simple-dom/void-map': + specifier: ^1.4.0 + version: 1.4.0 + js-reporters: + specifier: ^2.1.0 + version: 2.1.0 + qunit: + specifier: ^2.24.1 + version: 2.24.1 + simple-html-tokenizer: + specifier: ^0.5.11 + version: 0.5.11 + devDependencies: + '@glimmer/constants': + specifier: workspace:* + version: link:../../@glimmer/constants + '@glimmer/debug-util': + specifier: workspace:* + version: link:../../@glimmer/debug-util + '@glimmer/local-debug-flags': + specifier: workspace:* + version: link:../../@glimmer/local-debug-flags + '@types/js-reporters': + specifier: workspace:* + version: link:../../@types/js-reporters + '@types/qunit': + specifier: ^2.19.12 + version: 2.19.12 + dom-types: + specifier: ^1.1.2 + version: 1.1.2 + + packages/@glimmer-workspace/integration-tests/test: + dependencies: + '@glimmer-workspace/integration-tests': + specifier: workspace:* + version: link:.. + '@glimmer-workspace/test-utils': + specifier: workspace:* + version: link:../../test-utils + '@glimmer/compiler': + specifier: workspace:* + version: link:../../../@glimmer/compiler + '@glimmer/constants': + specifier: workspace:* + version: link:../../../@glimmer/constants + '@glimmer/debug-util': + specifier: workspace:* + version: link:../../../@glimmer/debug-util + '@glimmer/destroyable': + specifier: workspace:* + version: link:../../../@glimmer/destroyable + '@glimmer/global-context': + specifier: workspace:* + version: link:../../../@glimmer/global-context + '@glimmer/local-debug-flags': + specifier: workspace:* + version: link:../../../@glimmer/local-debug-flags + '@glimmer/manager': + specifier: workspace:* + version: link:../../../@glimmer/manager + '@glimmer/opcode-compiler': + specifier: workspace:* + version: link:../../../@glimmer/opcode-compiler + '@glimmer/owner': + specifier: workspace:* + version: link:../../../@glimmer/owner + '@glimmer/reference': + specifier: workspace:* + version: link:../../../@glimmer/reference + '@glimmer/runtime': + specifier: workspace:* + version: link:../../../@glimmer/runtime + '@glimmer/syntax': + specifier: workspace:* + version: link:../../../@glimmer/syntax + '@glimmer/util': + specifier: workspace:* + version: link:../../../@glimmer/util + '@glimmer/validator': + specifier: workspace:* + version: link:../../../@glimmer/validator + '@glimmer/wire-format': + specifier: workspace:* + version: link:../../../@glimmer/wire-format + + packages/@glimmer-workspace/test-utils: + dependencies: + '@glimmer/interfaces': + specifier: workspace:* + version: link:../../@glimmer/interfaces + '@glimmer/util': + specifier: workspace:* + version: link:../../@glimmer/util + devDependencies: + '@glimmer/debug-util': + specifier: workspace:* + version: link:../../@glimmer/debug-util + eslint: + specifier: ^9.20.1 + version: 9.20.1(jiti@2.4.2) + + packages/@glimmer/compiler: + dependencies: + '@glimmer/interfaces': + specifier: workspace:* + version: link:../interfaces + '@glimmer/syntax': + specifier: workspace:* + version: link:../syntax + '@glimmer/util': + specifier: workspace:* + version: link:../util + '@glimmer/wire-format': + specifier: workspace:* + version: link:../wire-format + devDependencies: + '@glimmer-workspace/build-support': + specifier: workspace:* + version: link:../../@glimmer-workspace/build + '@glimmer-workspace/env': + specifier: workspace:* + version: link:../../@glimmer-workspace/env + '@glimmer/constants': + specifier: workspace:* + version: link:../constants + '@glimmer/debug': + specifier: workspace:* + version: link:../debug + '@glimmer/debug-util': + specifier: workspace:* + version: link:../debug-util + '@glimmer/local-debug-flags': + specifier: workspace:* + version: link:../local-debug-flags + '@types/node': + specifier: ^22.13.4 + version: 22.13.4 + eslint: + specifier: ^9.20.1 + version: 9.20.1(jiti@2.4.2) + publint: + specifier: ^0.3.2 + version: 0.3.2 + rollup: + specifier: ^4.34.8 + version: 4.34.8 + typescript: + specifier: ^5.7.3 + version: 5.7.3 + + packages/@glimmer/compiler/test: + dependencies: + '@glimmer/compiler': + specifier: workspace:* + version: link:.. + '@glimmer/interfaces': + specifier: workspace:* + version: link:../../interfaces + '@glimmer/syntax': + specifier: workspace:* + version: link:../../syntax + '@glimmer/util': + specifier: workspace:* + version: link:../../util + devDependencies: + '@glimmer/constants': + specifier: workspace:* + version: link:../../constants + + packages/@glimmer/constants: + dependencies: + '@glimmer/interfaces': + specifier: workspace:* + version: link:../interfaces + devDependencies: + '@glimmer/debug-util': + specifier: workspace:* + version: link:../debug-util + '@glimmer/local-debug-flags': + specifier: workspace:* + version: link:../local-debug-flags + eslint: + specifier: ^9.20.1 + version: 9.20.1(jiti@2.4.2) + publint: + specifier: ^0.3.2 + version: 0.3.2 + typescript: + specifier: ^5.7.3 + version: 5.7.3 + + packages/@glimmer/constants/test: + dependencies: + '@glimmer/env': + specifier: 0.1.7 + version: 0.1.7 + '@glimmer/util': + specifier: workspace:* + version: link:../../util + devDependencies: + '@glimmer/constants': + specifier: workspace:* + version: link:.. + '@glimmer/debug-util': + specifier: workspace:* + version: link:../../debug-util + vite: + specifier: ^6.1.1 + version: 6.3.5(@types/node@22.13.4)(jiti@2.4.2)(terser@5.43.1)(tsx@4.19.2)(yaml@2.7.0) + + packages/@glimmer/debug: + dependencies: + '@glimmer/interfaces': + specifier: workspace:* + version: link:../interfaces + '@glimmer/reference': + specifier: workspace:* + version: link:../reference + '@glimmer/util': + specifier: workspace:* + version: link:../util + '@glimmer/vm': + specifier: workspace:* + version: link:../vm + devDependencies: + '@glimmer/constants': + specifier: workspace:* + version: link:../constants + '@glimmer/debug-util': + specifier: workspace:* + version: link:../debug-util + '@glimmer/local-debug-flags': + specifier: workspace:* + version: link:../local-debug-flags + eslint: + specifier: ^9.20.1 + version: 9.20.1(jiti@2.4.2) + typescript: + specifier: ^5.7.3 + version: 5.7.3 + + packages/@glimmer/debug-util: + dependencies: + '@glimmer/interfaces': + specifier: workspace:* + version: link:../interfaces + devDependencies: + '@glimmer/local-debug-flags': + specifier: workspace:* + version: link:../local-debug-flags + eslint: + specifier: ^9.20.1 + version: 9.20.1(jiti@2.4.2) + typescript: + specifier: ^5.7.3 + version: 5.7.3 + + packages/@glimmer/debug-util/test: + dependencies: + '@glimmer/env': + specifier: 0.1.7 + version: 0.1.7 + '@glimmer/util': + specifier: workspace:* + version: link:../../util + devDependencies: + '@glimmer/debug-util': + specifier: workspace:* + version: link:.. + vite: + specifier: ^6.1.1 + version: 6.3.5(@types/node@22.13.4)(jiti@2.4.2)(terser@5.43.1)(tsx@4.19.2)(yaml@2.7.0) + + packages/@glimmer/debug/test: + dependencies: + '@glimmer/debug': + specifier: workspace:* + version: link:.. + + packages/@glimmer/destroyable: + dependencies: + '@glimmer/global-context': + specifier: workspace:* + version: link:../global-context + '@glimmer/interfaces': + specifier: workspace:* + version: link:../interfaces + devDependencies: + '@glimmer-workspace/build-support': + specifier: workspace:* + version: link:../../@glimmer-workspace/build + '@glimmer-workspace/env': + specifier: workspace:* + version: link:../../@glimmer-workspace/env + '@glimmer/debug-util': + specifier: workspace:* + version: link:../debug-util + eslint: + specifier: ^9.20.1 + version: 9.20.1(jiti@2.4.2) + publint: + specifier: ^0.3.2 + version: 0.3.2 + rollup: + specifier: ^4.34.8 + version: 4.34.8 + typescript: + specifier: ^5.7.3 + version: 5.7.3 + + packages/@glimmer/destroyable/test: + dependencies: + '@glimmer/destroyable': + specifier: workspace:* + version: link:.. + '@glimmer/global-context': + specifier: workspace:* + version: link:../../global-context + '@glimmer/util': + specifier: workspace:* + version: link:../../util + devDependencies: + '@glimmer/debug-util': + specifier: workspace:* + version: link:../../debug-util + + packages/@glimmer/encoder: + dependencies: + '@glimmer/interfaces': + specifier: workspace:* + version: link:../interfaces + '@glimmer/vm': + specifier: workspace:* + version: link:../vm + devDependencies: + '@glimmer-workspace/build-support': + specifier: workspace:* + version: link:../../@glimmer-workspace/build + '@glimmer-workspace/env': + specifier: workspace:* + version: link:../../@glimmer-workspace/env + eslint: + specifier: ^9.20.1 + version: 9.20.1(jiti@2.4.2) + publint: + specifier: ^0.3.2 + version: 0.3.2 + rollup: + specifier: ^4.34.8 + version: 4.34.8 + typescript: + specifier: ^5.7.3 + version: 5.7.3 + + packages/@glimmer/global-context: + devDependencies: + '@glimmer-workspace/build-support': + specifier: workspace:* + version: link:../../@glimmer-workspace/build + '@glimmer-workspace/env': + specifier: workspace:* + version: link:../../@glimmer-workspace/env + eslint: + specifier: ^9.20.1 + version: 9.20.1(jiti@2.4.2) + publint: + specifier: ^0.3.2 + version: 0.3.2 + rollup: + specifier: ^4.34.8 + version: 4.34.8 + typescript: + specifier: ^5.7.3 + version: 5.7.3 + + packages/@glimmer/interfaces: + dependencies: + '@simple-dom/interface': + specifier: ^1.4.0 + version: 1.4.0 + type-fest: + specifier: ^4.35.0 + version: 4.35.0 + devDependencies: + eslint: + specifier: ^9.20.1 + version: 9.20.1(jiti@2.4.2) + publint: + specifier: ^0.3.2 + version: 0.3.2 + typescript: + specifier: ^5.7.3 + version: 5.7.3 + + packages/@glimmer/local-debug-babel-plugin: {} + + packages/@glimmer/local-debug-flags: + devDependencies: + eslint: + specifier: ^9.20.1 + version: 9.20.1(jiti@2.4.2) + + packages/@glimmer/manager: + dependencies: + '@glimmer/destroyable': + specifier: workspace:* + version: link:../destroyable + '@glimmer/global-context': + specifier: workspace:* + version: link:../global-context + '@glimmer/interfaces': + specifier: workspace:* + version: link:../interfaces + '@glimmer/reference': + specifier: workspace:* + version: link:../reference + '@glimmer/util': + specifier: workspace:* + version: link:../util + '@glimmer/validator': + specifier: workspace:* + version: link:../validator + '@glimmer/vm': + specifier: workspace:* + version: link:../vm + devDependencies: + '@glimmer-workspace/build-support': + specifier: workspace:* + version: link:../../@glimmer-workspace/build + '@glimmer-workspace/env': + specifier: workspace:* + version: link:../../@glimmer-workspace/env + '@glimmer/debug': + specifier: workspace:* + version: link:../debug + '@glimmer/debug-util': + specifier: workspace:* + version: link:../debug-util + eslint: + specifier: ^9.20.1 + version: 9.20.1(jiti@2.4.2) + publint: + specifier: ^0.3.2 + version: 0.3.2 + rollup: + specifier: ^4.34.8 + version: 4.34.8 + typescript: + specifier: ^5.7.3 + version: 5.7.3 + + packages/@glimmer/manager/test: + dependencies: + '@glimmer/interfaces': + specifier: workspace:* + version: link:../../interfaces + '@glimmer/manager': + specifier: workspace:* + version: link:.. + '@glimmer/reference': + specifier: workspace:* + version: link:../../reference + '@glimmer/validator': + specifier: workspace:* + version: link:../../validator + '@glimmer/vm': + specifier: workspace:* + version: link:../../vm + + packages/@glimmer/node: + dependencies: + '@glimmer/interfaces': + specifier: workspace:* + version: link:../interfaces + '@glimmer/runtime': + specifier: workspace:* + version: link:../runtime + '@glimmer/util': + specifier: workspace:* + version: link:../util + '@simple-dom/document': + specifier: ^1.4.0 + version: 1.4.0 + devDependencies: + '@glimmer-workspace/build-support': + specifier: workspace:* + version: link:../../@glimmer-workspace/build + '@glimmer-workspace/env': + specifier: workspace:* + version: link:../../@glimmer-workspace/env + '@glimmer/compiler': + specifier: workspace:* + version: link:../compiler + '@types/qunit': + specifier: ^2.19.12 + version: 2.19.12 + eslint: + specifier: ^9.20.1 + version: 9.20.1(jiti@2.4.2) + publint: + specifier: ^0.3.2 + version: 0.3.2 + rollup: + specifier: ^4.34.8 + version: 4.34.8 + typescript: + specifier: ^5.7.3 + version: 5.7.3 + + packages/@glimmer/opcode-compiler: + dependencies: + '@glimmer/encoder': + specifier: workspace:* + version: link:../encoder + '@glimmer/interfaces': + specifier: workspace:* + version: link:../interfaces + '@glimmer/manager': + specifier: workspace:* + version: link:../manager + '@glimmer/util': + specifier: workspace:* + version: link:../util + '@glimmer/vm': + specifier: workspace:* + version: link:../vm + '@glimmer/wire-format': + specifier: workspace:* + version: link:../wire-format + devDependencies: + '@glimmer-workspace/build-support': + specifier: workspace:* + version: link:../../@glimmer-workspace/build + '@glimmer-workspace/env': + specifier: workspace:* + version: link:../../@glimmer-workspace/env + '@glimmer/constants': + specifier: workspace:* + version: link:../constants + '@glimmer/debug': + specifier: workspace:* + version: link:../debug + '@glimmer/debug-util': + specifier: workspace:* + version: link:../debug-util + '@glimmer/local-debug-flags': + specifier: workspace:* + version: link:../local-debug-flags + eslint: + specifier: ^9.20.1 + version: 9.20.1(jiti@2.4.2) + publint: + specifier: ^0.3.2 + version: 0.3.2 + rollup: + specifier: ^4.34.8 + version: 4.34.8 + type-fest: + specifier: ^4.35.0 + version: 4.35.0 + typescript: + specifier: ^5.7.3 + version: 5.7.3 + + packages/@glimmer/owner: + devDependencies: + '@glimmer-workspace/build-support': + specifier: workspace:* + version: link:../../@glimmer-workspace/build + '@glimmer-workspace/env': + specifier: workspace:* + version: link:../../@glimmer-workspace/env + eslint: + specifier: ^9.20.1 + version: 9.20.1(jiti@2.4.2) + publint: + specifier: ^0.3.2 + version: 0.3.2 + rollup: + specifier: ^4.34.8 + version: 4.34.8 + typescript: + specifier: ^5.7.3 + version: 5.7.3 + + packages/@glimmer/owner/test: + dependencies: + '@glimmer/owner': + specifier: workspace:* + version: link:.. + + packages/@glimmer/program: + dependencies: + '@glimmer/interfaces': + specifier: workspace:* + version: link:../interfaces + '@glimmer/manager': + specifier: workspace:* + version: link:../manager + '@glimmer/opcode-compiler': + specifier: workspace:* + version: link:../opcode-compiler + '@glimmer/util': + specifier: workspace:* + version: link:../util + '@glimmer/vm': + specifier: workspace:* + version: link:../vm + '@glimmer/wire-format': + specifier: workspace:* + version: link:../wire-format + devDependencies: + '@glimmer-workspace/build-support': + specifier: workspace:* + version: link:../../@glimmer-workspace/build + '@glimmer-workspace/env': + specifier: workspace:* + version: link:../../@glimmer-workspace/env + '@glimmer/constants': + specifier: workspace:* + version: link:../constants + '@glimmer/debug-util': + specifier: workspace:* + version: link:../debug-util + '@glimmer/local-debug-flags': + specifier: workspace:* + version: link:../local-debug-flags + eslint: + specifier: ^9.20.1 + version: 9.20.1(jiti@2.4.2) + publint: + specifier: ^0.3.2 + version: 0.3.2 + rollup: + specifier: ^4.34.8 + version: 4.34.8 + typescript: + specifier: ^5.7.3 + version: 5.7.3 + + packages/@glimmer/program/test: + dependencies: + '@glimmer/program': + specifier: workspace:* + version: link:.. + + packages/@glimmer/reference: + dependencies: + '@glimmer/global-context': + specifier: workspace:* + version: link:../global-context + '@glimmer/interfaces': + specifier: workspace:* + version: link:../interfaces + '@glimmer/util': + specifier: workspace:* + version: link:../util + '@glimmer/validator': + specifier: workspace:* + version: link:../validator + devDependencies: + '@glimmer-workspace/build-support': + specifier: workspace:* + version: link:../../@glimmer-workspace/build + '@glimmer-workspace/env': + specifier: workspace:* + version: link:../../@glimmer-workspace/env + '@glimmer/debug-util': + specifier: workspace:* + version: link:../debug-util + eslint: + specifier: ^9.20.1 + version: 9.20.1(jiti@2.4.2) + publint: + specifier: ^0.3.2 + version: 0.3.2 + rollup: + specifier: ^4.34.8 + version: 4.34.8 + typescript: + specifier: ^5.7.3 + version: 5.7.3 + + packages/@glimmer/reference/test: + dependencies: + '@glimmer/global-context': + specifier: workspace:* + version: link:../../global-context + '@glimmer/reference': + specifier: workspace:* + version: link:.. + '@glimmer/util': + specifier: workspace:* + version: link:../../util + '@glimmer/validator': + specifier: workspace:* + version: link:../../validator + devDependencies: + '@glimmer/debug-util': + specifier: workspace:* + version: link:../../debug-util + + packages/@glimmer/runtime: + dependencies: + '@glimmer/destroyable': + specifier: workspace:* + version: link:../destroyable + '@glimmer/global-context': + specifier: workspace:* + version: link:../global-context + '@glimmer/interfaces': + specifier: workspace:* + version: link:../interfaces + '@glimmer/manager': + specifier: workspace:* + version: link:../manager + '@glimmer/owner': + specifier: workspace:* + version: link:../owner + '@glimmer/program': + specifier: workspace:* + version: link:../program + '@glimmer/reference': + specifier: workspace:* + version: link:../reference + '@glimmer/util': + specifier: workspace:* + version: link:../util + '@glimmer/validator': + specifier: workspace:* + version: link:../validator + '@glimmer/vm': + specifier: workspace:* + version: link:../vm + devDependencies: + '@glimmer-workspace/build-support': + specifier: workspace:* + version: link:../../@glimmer-workspace/build + '@glimmer-workspace/env': + specifier: workspace:* + version: link:../../@glimmer-workspace/env + '@glimmer/constants': + specifier: workspace:* + version: link:../constants + '@glimmer/debug': + specifier: workspace:* + version: link:../debug + '@glimmer/debug-util': + specifier: workspace:* + version: link:../debug-util + '@glimmer/local-debug-flags': + specifier: workspace:* + version: link:../local-debug-flags + eslint: + specifier: ^9.20.1 + version: 9.20.1(jiti@2.4.2) + publint: + specifier: ^0.3.2 + version: 0.3.2 + rollup: + specifier: ^4.34.8 + version: 4.34.8 + typescript: + specifier: ^5.7.3 + version: 5.7.3 + + packages/@glimmer/syntax: + dependencies: + '@glimmer/interfaces': + specifier: workspace:* + version: link:../interfaces + '@glimmer/util': + specifier: workspace:* + version: link:../util + '@glimmer/wire-format': + specifier: workspace:* + version: link:../wire-format + '@handlebars/parser': + specifier: ~2.2.0 + version: 2.2.0 + simple-html-tokenizer: + specifier: ^0.5.11 + version: 0.5.11 + devDependencies: + '@glimmer-workspace/build-support': + specifier: workspace:* + version: link:../../@glimmer-workspace/build + '@glimmer-workspace/env': + specifier: workspace:* + version: link:../../@glimmer-workspace/env + '@glimmer/debug-util': + specifier: workspace:* + version: link:../debug-util + '@glimmer/local-debug-flags': + specifier: workspace:* + version: link:../local-debug-flags + eslint: + specifier: ^9.20.1 + version: 9.20.1(jiti@2.4.2) + publint: + specifier: ^0.3.2 + version: 0.3.2 + rollup: + specifier: ^4.34.8 + version: 4.34.8 + typescript: + specifier: ^5.7.3 + version: 5.7.3 + + packages/@glimmer/syntax/test: + dependencies: + '@glimmer-workspace/integration-tests': + specifier: workspace:* + version: link:../../../@glimmer-workspace/integration-tests + '@glimmer-workspace/test-utils': + specifier: workspace:* + version: link:../../../@glimmer-workspace/test-utils + '@glimmer/interfaces': + specifier: workspace:* + version: link:../../interfaces + '@glimmer/syntax': + specifier: workspace:* + version: link:.. + '@glimmer/util': + specifier: workspace:* + version: link:../../util + devDependencies: + '@glimmer/debug-util': + specifier: workspace:* + version: link:../../debug-util + + packages/@glimmer/util: + dependencies: + '@glimmer/interfaces': + specifier: workspace:* + version: link:../interfaces + devDependencies: + '@glimmer-workspace/build-support': + specifier: workspace:* + version: link:../../@glimmer-workspace/build + '@glimmer-workspace/env': + specifier: workspace:* + version: link:../../@glimmer-workspace/env + '@glimmer/debug-util': + specifier: workspace:* + version: link:../debug-util + '@glimmer/local-debug-flags': + specifier: workspace:* + version: link:../local-debug-flags + '@types/qunit': + specifier: ^2.19.12 + version: 2.19.12 + eslint: + specifier: ^9.20.1 + version: 9.20.1(jiti@2.4.2) + publint: + specifier: ^0.3.2 + version: 0.3.2 + rollup: + specifier: ^4.34.8 + version: 4.34.8 + typescript: + specifier: ^5.7.3 + version: 5.7.3 + + packages/@glimmer/util/test: + dependencies: + '@glimmer/util': + specifier: workspace:* + version: link:.. + + packages/@glimmer/validator: + dependencies: + '@glimmer/global-context': + specifier: workspace:* + version: link:../global-context + '@glimmer/interfaces': + specifier: workspace:* + version: link:../interfaces + devDependencies: + '@glimmer-workspace/build-support': + specifier: workspace:* + version: link:../../@glimmer-workspace/build + '@glimmer-workspace/env': + specifier: workspace:* + version: link:../../@glimmer-workspace/env + '@glimmer/debug-util': + specifier: workspace:* + version: link:../debug-util + eslint: + specifier: ^9.20.1 + version: 9.20.1(jiti@2.4.2) + expect-type: + specifier: ^1.1.0 + version: 1.1.0 + publint: + specifier: ^0.3.2 + version: 0.3.2 + rollup: + specifier: ^4.34.8 + version: 4.34.8 + typescript: + specifier: ^5.7.3 + version: 5.7.3 + + packages/@glimmer/validator/test: + dependencies: + '@glimmer/global-context': + specifier: workspace:* + version: link:../../global-context + '@glimmer/interfaces': + specifier: workspace:* + version: link:../../interfaces + '@glimmer/validator': + specifier: workspace:* + version: link:.. + expect-type: + specifier: ^1.1.0 + version: 1.1.0 + + packages/@glimmer/vm: + dependencies: + '@glimmer/interfaces': + specifier: workspace:* + version: link:../interfaces + devDependencies: + '@glimmer-workspace/build-support': + specifier: workspace:* + version: link:../../@glimmer-workspace/build + '@glimmer-workspace/env': + specifier: workspace:* + version: link:../../@glimmer-workspace/env + eslint: + specifier: ^9.20.1 + version: 9.20.1(jiti@2.4.2) + publint: + specifier: ^0.3.2 + version: 0.3.2 + rollup: + specifier: ^4.34.8 + version: 4.34.8 + typescript: + specifier: ^5.7.3 + version: 5.7.3 + + packages/@glimmer/vm-babel-plugins: + dependencies: + babel-plugin-debug-macros: + specifier: ^0.3.4 + version: 0.3.4(@babel/core@7.26.0) + devDependencies: + '@glimmer-workspace/build-support': + specifier: workspace:* + version: link:../../@glimmer-workspace/build + '@glimmer-workspace/env': + specifier: workspace:* + version: link:../../@glimmer-workspace/env + '@types/node': + specifier: ^22.13.4 + version: 22.13.4 + babel-plugin-tester: + specifier: ^11.0.4 + version: 11.0.4(@babel/core@7.26.0) + eslint: + specifier: ^9.20.1 + version: 9.20.1(jiti@2.4.2) + mocha: + specifier: ^11.7.1 + version: 11.7.1 + publint: + specifier: ^0.3.2 + version: 0.3.2 + rollup: + specifier: ^4.34.8 + version: 4.34.8 + typescript: + specifier: ^5.7.3 + version: 5.7.3 + + packages/@glimmer/wire-format: + dependencies: + '@glimmer/interfaces': + specifier: workspace:* + version: link:../interfaces + devDependencies: + '@glimmer-workspace/build-support': + specifier: workspace:* + version: link:../../@glimmer-workspace/build + '@glimmer-workspace/env': + specifier: workspace:* + version: link:../../@glimmer-workspace/env + eslint: + specifier: ^9.20.1 + version: 9.20.1(jiti@2.4.2) + publint: + specifier: ^0.3.2 + version: 0.3.2 + rollup: + specifier: ^4.34.8 + version: 4.34.8 + typescript: + specifier: ^5.7.3 + version: 5.7.3 + + packages/@types/eslint-community__eslint-plugin-eslint-comments: + dependencies: + '@types/eslint': + specifier: ^9.6.1 + version: 9.6.1 + + packages/@types/eslint-plugin-import: + dependencies: + '@types/eslint': + specifier: ^9.6.1 + version: 9.6.1 + + packages/@types/eslint-plugin-qunit: + dependencies: + '@types/eslint': + specifier: ^9.6.1 + version: 9.6.1 + + packages/@types/js-reporters: {} + + packages/@types/puppeteer-chromium-resolver: + dependencies: + puppeteer: + specifier: 23.11.1 + version: 23.11.1(typescript@5.7.3) + + repo-metadata: + dependencies: + chalk: + specifier: ^5.4.1 + version: 5.4.1 + deepmerge: + specifier: ^4.3.1 + version: 4.3.1 + execa: + specifier: ^9.5.2 + version: 9.5.2 + globby: + specifier: ^14.1.0 + version: 14.1.0 + handlebars: + specifier: ^4.7.8 + version: 4.7.8 + read-pkg: + specifier: ^9.0.1 + version: 9.0.1 + write-pkg: + specifier: ^7.0.0 + version: 7.0.0 + yaml: + specifier: ^2.7.0 + version: 2.7.0 + devDependencies: + '@types/fs-extra': + specifier: ^11.0.4 + version: 11.0.4 + '@types/handlebars': + specifier: ^4.1.0 + version: 4.1.0 + '@types/node': + specifier: ^22.13.4 + version: 22.13.4 + pkg-entry-points: + specifier: ^1.1.1 + version: 1.1.1 + +packages: + + '@ampproject/remapping@2.3.0': + resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} + engines: {node: '>=6.0.0'} + + '@babel/code-frame@7.26.2': + resolution: {integrity: sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==} + engines: {node: '>=6.9.0'} + + '@babel/code-frame@7.27.1': + resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} + engines: {node: '>=6.9.0'} + + '@babel/compat-data@7.28.0': + resolution: {integrity: sha512-60X7qkglvrap8mn1lh2ebxXdZYtUcpd7gsmy9kLaBJ4i/WdY8PqTSdxyA8qraikqKQK5C1KRBKXqznrVapyNaw==} + engines: {node: '>=6.9.0'} + + '@babel/core@7.26.0': + resolution: {integrity: sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg==} + engines: {node: '>=6.9.0'} + + '@babel/generator@7.28.0': + resolution: {integrity: sha512-lJjzvrbEeWrhB4P3QBsH7tey117PjLZnDbLiQEKjQ/fNJTjuq4HSqgFA+UNSwZT8D7dxxbnuSBMsa1lrWzKlQg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-annotate-as-pure@7.27.3': + resolution: {integrity: sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-compilation-targets@7.27.2': + resolution: {integrity: sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==} + engines: {node: '>=6.9.0'} + + '@babel/helper-create-class-features-plugin@7.27.1': + resolution: {integrity: sha512-QwGAmuvM17btKU5VqXfb+Giw4JcN0hjuufz3DYnpeVDvZLAObloM77bhMXiqry3Iio+Ai4phVRDwl6WU10+r5A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-create-regexp-features-plugin@7.27.1': + resolution: {integrity: sha512-uVDC72XVf8UbrH5qQTc18Agb8emwjTiZrQE11Nv3CuBEZmVvTwwE9CBUEvHku06gQCAyYf8Nv6ja1IN+6LMbxQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-define-polyfill-provider@0.6.5': + resolution: {integrity: sha512-uJnGFcPsWQK8fvjgGP5LZUZZsYGIoPeRjSF5PGwrelYgq7Q15/Ft9NGFp1zglwgIv//W0uG4BevRuSJRyylZPg==} + peerDependencies: + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + + '@babel/helper-globals@7.28.0': + resolution: {integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-member-expression-to-functions@7.27.1': + resolution: {integrity: sha512-E5chM8eWjTp/aNoVpcbfM7mLxu9XGLWYise2eBKGQomAk/Mb4XoxyqXTZbuTohbsl8EKqdlMhnDI2CCLfcs9wA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-imports@7.25.9': + resolution: {integrity: sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-imports@7.27.1': + resolution: {integrity: sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-transforms@7.27.3': + resolution: {integrity: sha512-dSOvYwvyLsWBeIRyOeHXp5vPj5l1I011r52FM1+r1jCERv+aFXYk4whgQccYEGYxK2H3ZAIA8nuPkQ0HaUo3qg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-optimise-call-expression@7.27.1': + resolution: {integrity: sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-plugin-utils@7.27.1': + resolution: {integrity: sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-remap-async-to-generator@7.27.1': + resolution: {integrity: sha512-7fiA521aVw8lSPeI4ZOD3vRFkoqkJcS+z4hFo82bFSH/2tNd6eJ5qCVMS5OzDmZh/kaHQeBaeyxK6wljcPtveA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-replace-supers@7.27.1': + resolution: {integrity: sha512-7EHz6qDZc8RYS5ElPoShMheWvEgERonFCs7IAonWLLUTXW59DP14bCZt89/GKyreYn8g3S83m21FelHKbeDCKA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-skip-transparent-expression-wrappers@7.27.1': + resolution: {integrity: sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-string-parser@7.27.1': + resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-identifier@7.27.1': + resolution: {integrity: sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-option@7.27.1': + resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-wrap-function@7.27.1': + resolution: {integrity: sha512-NFJK2sHUvrjo8wAU/nQTWU890/zB2jj0qBcCbZbbf+005cAsv6tMjXz31fBign6M5ov1o0Bllu+9nbqkfsjjJQ==} + engines: {node: '>=6.9.0'} + + '@babel/helpers@7.27.6': + resolution: {integrity: sha512-muE8Tt8M22638HU31A3CgfSUciwz1fhATfoVai05aPXGor//CdWDCbnlY1yvBPo07njuVOCNGCSp/GTt12lIug==} + engines: {node: '>=6.9.0'} + + '@babel/parser@7.26.3': + resolution: {integrity: sha512-WJ/CvmY8Mea8iDXo6a7RK2wbmJITT5fN3BEkRuFlxVyNx8jOKIIhmC4fSkTcPcf8JyavbBwIe6OpiCOBXt/IcA==} + engines: {node: '>=6.0.0'} + hasBin: true + + '@babel/parser@7.28.0': + resolution: {integrity: sha512-jVZGvOxOuNSsuQuLRTh13nU0AogFlw32w/MT+LV6D3sP5WdbW61E77RnkbaO2dUvmPAYrBDJXGn5gGS6tH4j8g==} + engines: {node: '>=6.0.0'} + hasBin: true + + '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.27.1': + resolution: {integrity: sha512-QPG3C9cCVRQLxAVwmefEmwdTanECuUBMQZ/ym5kiw3XKCGA7qkuQLcjWWHcrD/GKbn/WmJwaezfuuAOcyKlRPA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-bugfix-safari-class-field-initializer-scope@7.27.1': + resolution: {integrity: sha512-qNeq3bCKnGgLkEXUuFry6dPlGfCdQNZbn7yUAPCInwAJHMU7THJfrBSozkcWq5sNM6RcF3S8XyQL2A52KNR9IA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.27.1': + resolution: {integrity: sha512-g4L7OYun04N1WyqMNjldFwlfPCLVkgB54A/YCXICZYBsvJJE3kByKv9c9+R/nAfmIfjl2rKYLNyMHboYbZaWaA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.27.1': + resolution: {integrity: sha512-oO02gcONcD5O1iTLi/6frMJBIwWEHceWGSGqrpCmEL8nogiS6J9PBlE48CaK20/Jx1LuRml9aDftLgdjXT8+Cw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.13.0 + + '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.27.1': + resolution: {integrity: sha512-6BpaYGDavZqkI6yT+KSPdpZFfpnd68UKXbcjI9pJ13pvHhPrCKWOOLp+ysvMeA+DxnhuPpgIaRpxRxo5A9t5jw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2': + resolution: {integrity: sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-dynamic-import@7.8.3': + resolution: {integrity: sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-import-assertions@7.27.1': + resolution: {integrity: sha512-UT/Jrhw57xg4ILHLFnzFpPDlMbcdEicaAtjPQpbj9wa8T4r5KVWCimHcL/460g8Ht0DMxDyjsLgiWSkVjnwPFg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-import-attributes@7.27.1': + resolution: {integrity: sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-jsx@7.27.1': + resolution: {integrity: sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-typescript@7.27.1': + resolution: {integrity: sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-unicode-sets-regex@7.18.6': + resolution: {integrity: sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-transform-arrow-functions@7.27.1': + resolution: {integrity: sha512-8Z4TGic6xW70FKThA5HYEKKyBpOOsucTOD1DjU3fZxDg+K3zBJcXMFnt/4yQiZnf5+MiOMSXQ9PaEK/Ilh1DeA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-async-generator-functions@7.28.0': + resolution: {integrity: sha512-BEOdvX4+M765icNPZeidyADIvQ1m1gmunXufXxvRESy/jNNyfovIqUyE7MVgGBjWktCoJlzvFA1To2O4ymIO3Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-async-to-generator@7.27.1': + resolution: {integrity: sha512-NREkZsZVJS4xmTr8qzE5y8AfIPqsdQfRuUiLRTEzb7Qii8iFWCyDKaUV2c0rCuh4ljDZ98ALHP/PetiBV2nddA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-block-scoped-functions@7.27.1': + resolution: {integrity: sha512-cnqkuOtZLapWYZUYM5rVIdv1nXYuFVIltZ6ZJ7nIj585QsjKM5dhL2Fu/lICXZ1OyIAFc7Qy+bvDAtTXqGrlhg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-block-scoping@7.28.0': + resolution: {integrity: sha512-gKKnwjpdx5sER/wl0WN0efUBFzF/56YZO0RJrSYP4CljXnP31ByY7fol89AzomdlLNzI36AvOTmYHsnZTCkq8Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-class-properties@7.27.1': + resolution: {integrity: sha512-D0VcalChDMtuRvJIu3U/fwWjf8ZMykz5iZsg77Nuj821vCKI3zCyRLwRdWbsuJ/uRwZhZ002QtCqIkwC/ZkvbA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-class-static-block@7.27.1': + resolution: {integrity: sha512-s734HmYU78MVzZ++joYM+NkJusItbdRcbm+AGRgJCt3iA+yux0QpD9cBVdz3tKyrjVYWRl7j0mHSmv4lhV0aoA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.12.0 + + '@babel/plugin-transform-classes@7.28.0': + resolution: {integrity: sha512-IjM1IoJNw72AZFlj33Cu8X0q2XK/6AaVC3jQu+cgQ5lThWD5ajnuUAml80dqRmOhmPkTH8uAwnpMu9Rvj0LTRA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-computed-properties@7.27.1': + resolution: {integrity: sha512-lj9PGWvMTVksbWiDT2tW68zGS/cyo4AkZ/QTp0sQT0mjPopCmrSkzxeXkznjqBxzDI6TclZhOJbBmbBLjuOZUw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-destructuring@7.28.0': + resolution: {integrity: sha512-v1nrSMBiKcodhsyJ4Gf+Z0U/yawmJDBOTpEB3mcQY52r9RIyPneGyAS/yM6seP/8I+mWI3elOMtT5dB8GJVs+A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-dotall-regex@7.27.1': + resolution: {integrity: sha512-gEbkDVGRvjj7+T1ivxrfgygpT7GUd4vmODtYpbs0gZATdkX8/iSnOtZSxiZnsgm1YjTgjI6VKBGSJJevkrclzw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-duplicate-keys@7.27.1': + resolution: {integrity: sha512-MTyJk98sHvSs+cvZ4nOauwTTG1JeonDjSGvGGUNHreGQns+Mpt6WX/dVzWBHgg+dYZhkC4X+zTDfkTU+Vy9y7Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.27.1': + resolution: {integrity: sha512-hkGcueTEzuhB30B3eJCbCYeCaaEQOmQR0AdvzpD4LoN0GXMWzzGSuRrxR2xTnCrvNbVwK9N6/jQ92GSLfiZWoQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-transform-dynamic-import@7.27.1': + resolution: {integrity: sha512-MHzkWQcEmjzzVW9j2q8LGjwGWpG2mjwaaB0BNQwst3FIjqsg8Ct/mIZlvSPJvfi9y2AC8mi/ktxbFVL9pZ1I4A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-explicit-resource-management@7.28.0': + resolution: {integrity: sha512-K8nhUcn3f6iB+P3gwCv/no7OdzOZQcKchW6N389V6PD8NUWKZHzndOd9sPDVbMoBsbmjMqlB4L9fm+fEFNVlwQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-exponentiation-operator@7.27.1': + resolution: {integrity: sha512-uspvXnhHvGKf2r4VVtBpeFnuDWsJLQ6MF6lGJLC89jBR1uoVeqM416AZtTuhTezOfgHicpJQmoD5YUakO/YmXQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-export-namespace-from@7.27.1': + resolution: {integrity: sha512-tQvHWSZ3/jH2xuq/vZDy0jNn+ZdXJeM8gHvX4lnJmsc3+50yPlWdZXIc5ay+umX+2/tJIqHqiEqcJvxlmIvRvQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-for-of@7.27.1': + resolution: {integrity: sha512-BfbWFFEJFQzLCQ5N8VocnCtA8J1CLkNTe2Ms2wocj75dd6VpiqS5Z5quTYcUoo4Yq+DN0rtikODccuv7RU81sw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-function-name@7.27.1': + resolution: {integrity: sha512-1bQeydJF9Nr1eBCMMbC+hdwmRlsv5XYOMu03YSWFwNs0HsAmtSxxF1fyuYPqemVldVyFmlCU7w8UE14LupUSZQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-json-strings@7.27.1': + resolution: {integrity: sha512-6WVLVJiTjqcQauBhn1LkICsR2H+zm62I3h9faTDKt1qP4jn2o72tSvqMwtGFKGTpojce0gJs+76eZ2uCHRZh0Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-literals@7.27.1': + resolution: {integrity: sha512-0HCFSepIpLTkLcsi86GG3mTUzxV5jpmbv97hTETW3yzrAij8aqlD36toB1D0daVFJM8NK6GvKO0gslVQmm+zZA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-logical-assignment-operators@7.27.1': + resolution: {integrity: sha512-SJvDs5dXxiae4FbSL1aBJlG4wvl594N6YEVVn9e3JGulwioy6z3oPjx/sQBO3Y4NwUu5HNix6KJ3wBZoewcdbw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-member-expression-literals@7.27.1': + resolution: {integrity: sha512-hqoBX4dcZ1I33jCSWcXrP+1Ku7kdqXf1oeah7ooKOIiAdKQ+uqftgCFNOSzA5AMS2XIHEYeGFg4cKRCdpxzVOQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-modules-amd@7.27.1': + resolution: {integrity: sha512-iCsytMg/N9/oFq6n+gFTvUYDZQOMK5kEdeYxmxt91fcJGycfxVP9CnrxoliM0oumFERba2i8ZtwRUCMhvP1LnA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-modules-commonjs@7.27.1': + resolution: {integrity: sha512-OJguuwlTYlN0gBZFRPqwOGNWssZjfIUdS7HMYtN8c1KmwpwHFBwTeFZrg9XZa+DFTitWOW5iTAG7tyCUPsCCyw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-modules-systemjs@7.27.1': + resolution: {integrity: sha512-w5N1XzsRbc0PQStASMksmUeqECuzKuTJer7kFagK8AXgpCMkeDMO5S+aaFb7A51ZYDF7XI34qsTX+fkHiIm5yA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-modules-umd@7.27.1': + resolution: {integrity: sha512-iQBE/xC5BV1OxJbp6WG7jq9IWiD+xxlZhLrdwpPkTX3ydmXdvoCpyfJN7acaIBZaOqTfr76pgzqBJflNbeRK+w==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-named-capturing-groups-regex@7.27.1': + resolution: {integrity: sha512-SstR5JYy8ddZvD6MhV0tM/j16Qds4mIpJTOd1Yu9J9pJjH93bxHECF7pgtc28XvkzTD6Pxcm/0Z73Hvk7kb3Ng==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-transform-new-target@7.27.1': + resolution: {integrity: sha512-f6PiYeqXQ05lYq3TIfIDu/MtliKUbNwkGApPUvyo6+tc7uaR4cPjPe7DFPr15Uyycg2lZU6btZ575CuQoYh7MQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-nullish-coalescing-operator@7.27.1': + resolution: {integrity: sha512-aGZh6xMo6q9vq1JGcw58lZ1Z0+i0xB2x0XaauNIUXd6O1xXc3RwoWEBlsTQrY4KQ9Jf0s5rgD6SiNkaUdJegTA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-numeric-separator@7.27.1': + resolution: {integrity: sha512-fdPKAcujuvEChxDBJ5c+0BTaS6revLV7CJL08e4m3de8qJfNIuCc2nc7XJYOjBoTMJeqSmwXJ0ypE14RCjLwaw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-object-rest-spread@7.28.0': + resolution: {integrity: sha512-9VNGikXxzu5eCiQjdE4IZn8sb9q7Xsk5EXLDBKUYg1e/Tve8/05+KJEtcxGxAgCY5t/BpKQM+JEL/yT4tvgiUA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-object-super@7.27.1': + resolution: {integrity: sha512-SFy8S9plRPbIcxlJ8A6mT/CxFdJx/c04JEctz4jf8YZaVS2px34j7NXRrlGlHkN/M2gnpL37ZpGRGVFLd3l8Ng==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-optional-catch-binding@7.27.1': + resolution: {integrity: sha512-txEAEKzYrHEX4xSZN4kJ+OfKXFVSWKB2ZxM9dpcE3wT7smwkNmXo5ORRlVzMVdJbD+Q8ILTgSD7959uj+3Dm3Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-optional-chaining@7.27.1': + resolution: {integrity: sha512-BQmKPPIuc8EkZgNKsv0X4bPmOoayeu4F1YCwx2/CfmDSXDbp7GnzlUH+/ul5VGfRg1AoFPsrIThlEBj2xb4CAg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-parameters@7.27.7': + resolution: {integrity: sha512-qBkYTYCb76RRxUM6CcZA5KRu8K4SM8ajzVeUgVdMVO9NN9uI/GaVmBg/WKJJGnNokV9SY8FxNOVWGXzqzUidBg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-private-methods@7.27.1': + resolution: {integrity: sha512-10FVt+X55AjRAYI9BrdISN9/AQWHqldOeZDUoLyif1Kn05a56xVBXb8ZouL8pZ9jem8QpXaOt8TS7RHUIS+GPA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-private-property-in-object@7.27.1': + resolution: {integrity: sha512-5J+IhqTi1XPa0DXF83jYOaARrX+41gOewWbkPyjMNRDqgOCqdffGh8L3f/Ek5utaEBZExjSAzcyjmV9SSAWObQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-property-literals@7.27.1': + resolution: {integrity: sha512-oThy3BCuCha8kDZ8ZkgOg2exvPYUlprMukKQXI1r1pJ47NCvxfkEy8vK+r/hT9nF0Aa4H1WUPZZjHTFtAhGfmQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-regenerator@7.28.0': + resolution: {integrity: sha512-LOAozRVbqxEVjSKfhGnuLoE4Kz4Oc5UJzuvFUhSsQzdCdaAQu06mG8zDv2GFSerM62nImUZ7K92vxnQcLSDlCQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-regexp-modifiers@7.27.1': + resolution: {integrity: sha512-TtEciroaiODtXvLZv4rmfMhkCv8jx3wgKpL68PuiPh2M4fvz5jhsA7697N1gMvkvr/JTF13DrFYyEbY9U7cVPA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-transform-reserved-words@7.27.1': + resolution: {integrity: sha512-V2ABPHIJX4kC7HegLkYoDpfg9PVmuWy/i6vUM5eGK22bx4YVFD3M5F0QQnWQoDs6AGsUWTVOopBiMFQgHaSkVw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-runtime@7.28.0': + resolution: {integrity: sha512-dGopk9nZrtCs2+nfIem25UuHyt5moSJamArzIoh9/vezUQPmYDOzjaHDCkAzuGJibCIkPup8rMT2+wYB6S73cA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-shorthand-properties@7.27.1': + resolution: {integrity: sha512-N/wH1vcn4oYawbJ13Y/FxcQrWk63jhfNa7jef0ih7PHSIHX2LB7GWE1rkPrOnka9kwMxb6hMl19p7lidA+EHmQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-spread@7.27.1': + resolution: {integrity: sha512-kpb3HUqaILBJcRFVhFUs6Trdd4mkrzcGXss+6/mxUd273PfbWqSDHRzMT2234gIg2QYfAjvXLSquP1xECSg09Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-sticky-regex@7.27.1': + resolution: {integrity: sha512-lhInBO5bi/Kowe2/aLdBAawijx+q1pQzicSgnkB6dUPc1+RC8QmJHKf2OjvU+NZWitguJHEaEmbV6VWEouT58g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-template-literals@7.27.1': + resolution: {integrity: sha512-fBJKiV7F2DxZUkg5EtHKXQdbsbURW3DZKQUWphDum0uRP6eHGGa/He9mc0mypL680pb+e/lDIthRohlv8NCHkg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-typeof-symbol@7.27.1': + resolution: {integrity: sha512-RiSILC+nRJM7FY5srIyc4/fGIwUhyDuuBSdWn4y6yT6gm652DpCHZjIipgn6B7MQ1ITOUnAKWixEUjQRIBIcLw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-typescript@7.28.0': + resolution: {integrity: sha512-4AEiDEBPIZvLQaWlc9liCavE0xRM0dNca41WtBeM3jgFptfUOSG9z0uteLhq6+3rq+WB6jIvUwKDTpXEHPJ2Vg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-unicode-escapes@7.27.1': + resolution: {integrity: sha512-Ysg4v6AmF26k9vpfFuTZg8HRfVWzsh1kVfowA23y9j/Gu6dOuahdUVhkLqpObp3JIv27MLSii6noRnuKN8H0Mg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-unicode-property-regex@7.27.1': + resolution: {integrity: sha512-uW20S39PnaTImxp39O5qFlHLS9LJEmANjMG7SxIhap8rCHqu0Ik+tLEPX5DKmHn6CsWQ7j3lix2tFOa5YtL12Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-unicode-regex@7.27.1': + resolution: {integrity: sha512-xvINq24TRojDuyt6JGtHmkVkrfVV3FPT16uytxImLeBZqW3/H52yN+kM1MGuyPkIQxrzKwPHs5U/MP3qKyzkGw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-unicode-sets-regex@7.27.1': + resolution: {integrity: sha512-EtkOujbc4cgvb0mlpQefi4NTPBzhSIevblFevACNLUspmrALgmEBdL/XfnyyITfd8fKBZrZys92zOWcik7j9Tw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/preset-env@7.28.0': + resolution: {integrity: sha512-VmaxeGOwuDqzLl5JUkIRM1X2Qu2uKGxHEQWh+cvvbl7JuJRgKGJSfsEF/bUaxFhJl/XAyxBe7q7qSuTbKFuCyg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/preset-modules@0.1.6-no-external-plugins': + resolution: {integrity: sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==} + peerDependencies: + '@babel/core': ^7.0.0-0 || ^8.0.0-0 <8.0.0 + + '@babel/preset-typescript@7.27.1': + resolution: {integrity: sha512-l7WfQfX0WK4M0v2RudjuQK4u99BS6yLHYEmdtVPP7lKV013zr9DygFuWNlnbvQ9LR+LS0Egz/XAvGx5U9MX0fQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/runtime@7.27.6': + resolution: {integrity: sha512-vbavdySgbTTrmFE+EsiqUTzlOr5bzlnJtUv9PynGCAKvfQqjIXbvFdumPM/GxMDfyuGMJaJAU6TO4zc1Jf1i8Q==} + engines: {node: '>=6.9.0'} + + '@babel/template@7.27.2': + resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==} + engines: {node: '>=6.9.0'} + + '@babel/traverse@7.28.0': + resolution: {integrity: sha512-mGe7UK5wWyh0bKRfupsUchrQGqvDbZDbKJw+kcRGSmdHVYrv+ltd0pnpDTVpiTqnaBru9iEvA8pz8W46v0Amwg==} + engines: {node: '>=6.9.0'} + + '@babel/types@7.28.0': + resolution: {integrity: sha512-jYnje+JyZG5YThjHiF28oT4SIZLnYOcSBb6+SDaFIyzDVSkXQmQQYclJ2R+YxcdmK0AX6x1E5OQNtuh3jHDrUg==} + engines: {node: '>=6.9.0'} + + '@colors/colors@1.5.0': + resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==} + engines: {node: '>=0.1.90'} + + '@cspotcode/source-map-support@0.8.1': + resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} + engines: {node: '>=12'} + + '@esbuild/aix-ppc64@0.25.5': + resolution: {integrity: sha512-9o3TMmpmftaCMepOdA5k/yDw8SfInyzWWTjYTFCX3kPSDJMROQTb8jg+h9Cnwnmm1vOzvxN7gIfB5V2ewpjtGA==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.25.5': + resolution: {integrity: sha512-VGzGhj4lJO+TVGV1v8ntCZWJktV7SGCs3Pn1GRWI1SBFtRALoomm8k5E9Pmwg3HOAal2VDc2F9+PM/rEY6oIDg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.25.5': + resolution: {integrity: sha512-AdJKSPeEHgi7/ZhuIPtcQKr5RQdo6OO2IL87JkianiMYMPbCtot9fxPbrMiBADOWWm3T2si9stAiVsGbTQFkbA==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.25.5': + resolution: {integrity: sha512-D2GyJT1kjvO//drbRT3Hib9XPwQeWd9vZoBJn+bu/lVsOZ13cqNdDeqIF/xQ5/VmWvMduP6AmXvylO/PIc2isw==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + + '@esbuild/darwin-arm64@0.25.5': + resolution: {integrity: sha512-GtaBgammVvdF7aPIgH2jxMDdivezgFu6iKpmT+48+F8Hhg5J/sfnDieg0aeG/jfSvkYQU2/pceFPDKlqZzwnfQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.25.5': + resolution: {integrity: sha512-1iT4FVL0dJ76/q1wd7XDsXrSW+oLoquptvh4CLR4kITDtqi2e/xwXwdCVH8hVHU43wgJdsq7Gxuzcs6Iq/7bxQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.25.5': + resolution: {integrity: sha512-nk4tGP3JThz4La38Uy/gzyXtpkPW8zSAmoUhK9xKKXdBCzKODMc2adkB2+8om9BDYugz+uGV7sLmpTYzvmz6Sw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.25.5': + resolution: {integrity: sha512-PrikaNjiXdR2laW6OIjlbeuCPrPaAl0IwPIaRv+SMV8CiM8i2LqVUHFC1+8eORgWyY7yhQY+2U2fA55mBzReaw==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.25.5': + resolution: {integrity: sha512-Z9kfb1v6ZlGbWj8EJk9T6czVEjjq2ntSYLY2cw6pAZl4oKtfgQuS4HOq41M/BcoLPzrUbNd+R4BXFyH//nHxVg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.25.5': + resolution: {integrity: sha512-cPzojwW2okgh7ZlRpcBEtsX7WBuqbLrNXqLU89GxWbNt6uIg78ET82qifUy3W6OVww6ZWobWub5oqZOVtwolfw==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-ia32@0.25.5': + resolution: {integrity: sha512-sQ7l00M8bSv36GLV95BVAdhJ2QsIbCuCjh/uYrWiMQSUuV+LpXwIqhgJDcvMTj+VsQmqAHL2yYaasENvJ7CDKA==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-loong64@0.25.5': + resolution: {integrity: sha512-0ur7ae16hDUC4OL5iEnDb0tZHDxYmuQyhKhsPBV8f99f6Z9KQM02g33f93rNH5A30agMS46u2HP6qTdEt6Q1kg==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-mips64el@0.25.5': + resolution: {integrity: sha512-kB/66P1OsHO5zLz0i6X0RxlQ+3cu0mkxS3TKFvkb5lin6uwZ/ttOkP3Z8lfR9mJOBk14ZwZ9182SIIWFGNmqmg==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-ppc64@0.25.5': + resolution: {integrity: sha512-UZCmJ7r9X2fe2D6jBmkLBMQetXPXIsZjQJCjgwpVDz+YMcS6oFR27alkgGv3Oqkv07bxdvw7fyB71/olceJhkQ==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-riscv64@0.25.5': + resolution: {integrity: sha512-kTxwu4mLyeOlsVIFPfQo+fQJAV9mh24xL+y+Bm6ej067sYANjyEw1dNHmvoqxJUCMnkBdKpvOn0Ahql6+4VyeA==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-s390x@0.25.5': + resolution: {integrity: sha512-K2dSKTKfmdh78uJ3NcWFiqyRrimfdinS5ErLSn3vluHNeHVnBAFWC8a4X5N+7FgVE1EjXS1QDZbpqZBjfrqMTQ==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-x64@0.25.5': + resolution: {integrity: sha512-uhj8N2obKTE6pSZ+aMUbqq+1nXxNjZIIjCjGLfsWvVpy7gKCOL6rsY1MhRh9zLtUtAI7vpgLMK6DxjO8Qm9lJw==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-arm64@0.25.5': + resolution: {integrity: sha512-pwHtMP9viAy1oHPvgxtOv+OkduK5ugofNTVDilIzBLpoWAM16r7b/mxBvfpuQDpRQFMfuVr5aLcn4yveGvBZvw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.25.5': + resolution: {integrity: sha512-WOb5fKrvVTRMfWFNCroYWWklbnXH0Q5rZppjq0vQIdlsQKuw6mdSihwSo4RV/YdQ5UCKKvBy7/0ZZYLBZKIbwQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-arm64@0.25.5': + resolution: {integrity: sha512-7A208+uQKgTxHd0G0uqZO8UjK2R0DDb4fDmERtARjSHWxqMTye4Erz4zZafx7Di9Cv+lNHYuncAkiGFySoD+Mw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.25.5': + resolution: {integrity: sha512-G4hE405ErTWraiZ8UiSoesH8DaCsMm0Cay4fsFWOOUcz8b8rC6uCvnagr+gnioEjWn0wC+o1/TAHt+It+MpIMg==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + + '@esbuild/sunos-x64@0.25.5': + resolution: {integrity: sha512-l+azKShMy7FxzY0Rj4RCt5VD/q8mG/e+mDivgspo+yL8zW7qEwctQ6YqKX34DTEleFAvCIUviCFX1SDZRSyMQA==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.25.5': + resolution: {integrity: sha512-O2S7SNZzdcFG7eFKgvwUEZ2VG9D/sn/eIiz8XRZ1Q/DO5a3s76Xv0mdBzVM5j5R639lXQmPmSo0iRpHqUUrsxw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.25.5': + resolution: {integrity: sha512-onOJ02pqs9h1iMJ1PQphR+VZv8qBMQ77Klcsqv9CNW2w6yLqoURLcgERAIurY6QE63bbLuqgP9ATqajFLK5AMQ==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-x64@0.25.5': + resolution: {integrity: sha512-TXv6YnJ8ZMVdX+SXWVBo/0p8LTcrUYngpWjvm91TMjjBQii7Oz11Lw5lbDV5Y0TzuhSJHwiH4hEtC1I42mMS0g==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + + '@eslint-community/eslint-plugin-eslint-comments@4.5.0': + resolution: {integrity: sha512-MAhuTKlr4y/CE3WYX26raZjy+I/kS2PLKSzvfmDCGrBLTFHOYwqROZdr4XwPgXwX3K9rjzMr4pSmUWGnzsUyMg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0 + + '@eslint-community/eslint-utils@4.4.1': + resolution: {integrity: sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + + '@eslint-community/eslint-utils@4.7.0': + resolution: {integrity: sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + + '@eslint-community/regexpp@4.12.1': + resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + + '@eslint/compat@1.2.5': + resolution: {integrity: sha512-5iuG/StT+7OfvhoBHPlmxkPA9om6aDUFgmD4+mWKAGsYt4vCe8rypneG03AuseyRHBmcCLXQtIH5S26tIoggLg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^9.10.0 + peerDependenciesMeta: + eslint: + optional: true + + '@eslint/config-array@0.19.1': + resolution: {integrity: sha512-fo6Mtm5mWyKjA/Chy1BYTdn5mGJoDNjC7C64ug20ADsRDGrA85bN3uK3MaKbeRkRuuIEAR5N33Jr1pbm411/PA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/config-inspector@1.1.0': + resolution: {integrity: sha512-DQGzRGV6jKujyxxCPlhwwyzq3HTW/NbFX9A4npPjW0+0A3KemxYJWZdwqJn4rauPsRUpJ8yuh5uOyMCChrnFsg==} + hasBin: true + peerDependencies: + eslint: ^8.50.0 || ^9.0.0 + + '@eslint/core@0.10.0': + resolution: {integrity: sha512-gFHJ+xBOo4G3WRlR1e/3G8A6/KZAH6zcE/hkLRCZTi/B9avAG365QhFA8uOGzTMqgTghpn7/fSnscW++dpMSAw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/core@0.11.0': + resolution: {integrity: sha512-DWUB2pksgNEb6Bz2fggIy1wh6fGgZP4Xyy/Mt0QZPiloKKXerbqq9D3SBQTlCRYOrcRPu4vuz+CGjwdfqxnoWA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/eslintrc@3.2.0': + resolution: {integrity: sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/js@9.20.0': + resolution: {integrity: sha512-iZA07H9io9Wn836aVTytRaNqh00Sad+EamwOVJT12GTLw1VGMFV/4JaME+JjLtr9fiGaoWgYnS54wrfWsSs4oQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/object-schema@2.1.5': + resolution: {integrity: sha512-o0bhxnL89h5Bae5T318nFoFzGy+YE5i/gGkoPAgkmTVdRKTiv3p8JHevPiPaMwoloKfEiiaHlawCqaZMqRm+XQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/plugin-kit@0.2.5': + resolution: {integrity: sha512-lB05FkqEdUg2AA0xEbUz0SnkXT1LcCTa438W4IWTUh4hdOnVbQyOJ81OrDXsJk/LSiJHubgGEFoR5EHq1NsH1A==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@gar/promisify@1.1.3': + resolution: {integrity: sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==} + + '@glimmer/env@0.1.7': + resolution: {integrity: sha512-JKF/a9I9jw6fGoz8kA7LEQslrwJ5jms5CXhu/aqkBWk+PmZ6pTl8mlb/eJ/5ujBGTiQzBhy5AIWF712iA+4/mw==} + + '@gwhitney/detect-indent@7.0.1': + resolution: {integrity: sha512-7bQW+gkKa2kKZPeJf6+c6gFK9ARxQfn+FKy9ScTBppyKRWH2KzsmweXUoklqeEiHiNVWaeP5csIdsNq6w7QhzA==} + engines: {node: '>=12.20'} + + '@handlebars/parser@2.2.0': + resolution: {integrity: sha512-NiZQQrc4rZ+JxiF+fds1t2bFTyJT+0el2hPsCPHXa5zVA+6tWlO/C01MZLYE0LmxfLopeONoxQr31lXKBLsEww==} + engines: {node: ^20.18.0} + + '@humanfs/core@0.19.1': + resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} + engines: {node: '>=18.18.0'} + + '@humanfs/node@0.16.6': + resolution: {integrity: sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==} + engines: {node: '>=18.18.0'} + + '@humanwhocodes/module-importer@1.0.1': + resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} + engines: {node: '>=12.22'} + + '@humanwhocodes/retry@0.3.1': + resolution: {integrity: sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==} + engines: {node: '>=18.18'} + + '@humanwhocodes/retry@0.4.1': + resolution: {integrity: sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==} + engines: {node: '>=18.18'} + + '@isaacs/cliui@8.0.2': + resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} + engines: {node: '>=12'} + + '@jridgewell/gen-mapping@0.3.12': + resolution: {integrity: sha512-OuLGC46TjB5BbN1dH8JULVVZY4WTdkF7tV9Ys6wLL1rubZnCMstOhNHueU5bLCrnRuDhKPDM4g6sw4Bel5Gzqg==} + + '@jridgewell/gen-mapping@0.3.8': + resolution: {integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==} + engines: {node: '>=6.0.0'} + + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} + + '@jridgewell/set-array@1.2.1': + resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} + engines: {node: '>=6.0.0'} + + '@jridgewell/source-map@0.3.10': + resolution: {integrity: sha512-0pPkgz9dY+bijgistcTTJ5mR+ocqRXLuhXHYdzoMmmoJ2C9S46RCm2GMUbatPEUK9Yjy26IrAy8D/M00lLkv+Q==} + + '@jridgewell/source-map@0.3.6': + resolution: {integrity: sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==} + + '@jridgewell/sourcemap-codec@1.5.0': + resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} + + '@jridgewell/sourcemap-codec@1.5.4': + resolution: {integrity: sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw==} + + '@jridgewell/trace-mapping@0.3.25': + resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} + + '@jridgewell/trace-mapping@0.3.29': + resolution: {integrity: sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ==} + + '@jridgewell/trace-mapping@0.3.9': + resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} + + '@manypkg/find-root@2.2.3': + resolution: {integrity: sha512-jtEZKczWTueJYHjGpxU3KJQ08Gsrf4r6Q2GjmPp/RGk5leeYAA1eyDADSAF+KVCsQ6EwZd/FMcOFCoMhtqdCtQ==} + engines: {node: '>=14.18.0'} + + '@manypkg/get-packages@2.2.2': + resolution: {integrity: sha512-3+Zd8kLZmsyJFmWTBtY0MAuCErI7yKB2cjMBlujvSVKZ2R/BMXi0kjCXu2dtRlSq/ML86t1FkumT0yreQ3n8OQ==} + engines: {node: '>=14.18.0'} + + '@manypkg/tools@1.1.2': + resolution: {integrity: sha512-3lBouSuF7CqlseLB+FKES0K4FQ02JrbEoRtJhxnsyB1s5v4AP03gsoohN8jp7DcOImhaR9scYdztq3/sLfk/qQ==} + engines: {node: '>=14.18.0'} + + '@nodelib/fs.scandir@2.1.5': + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + + '@nodelib/fs.scandir@4.0.1': + resolution: {integrity: sha512-vAkI715yhnmiPupY+dq+xenu5Tdf2TBQ66jLvBIcCddtz+5Q8LbMKaf9CIJJreez8fQ8fgaY+RaywQx8RJIWpw==} + engines: {node: '>=18.18.0'} + + '@nodelib/fs.stat@2.0.5': + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + + '@nodelib/fs.stat@4.0.0': + resolution: {integrity: sha512-ctr6bByzksKRCV0bavi8WoQevU6plSp2IkllIsEqaiKe2mwNNnaluhnRhcsgGZHrrHk57B3lf95MkLMO3STYcg==} + engines: {node: '>=18.18.0'} + + '@nodelib/fs.walk@1.2.8': + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + + '@nodelib/fs.walk@3.0.1': + resolution: {integrity: sha512-nIh/M6Kh3ZtOmlY00DaUYB4xeeV6F3/ts1l29iwl3/cfyY/OuCfUx+v08zgx8TKPTifXRcjjqVQ4KB2zOYSbyw==} + engines: {node: '>=18.18.0'} + + '@nolyfill/is-core-module@1.0.39': + resolution: {integrity: sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==} + engines: {node: '>=12.4.0'} + + '@npmcli/fs@1.1.1': + resolution: {integrity: sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==} + + '@npmcli/git@6.0.3': + resolution: {integrity: sha512-GUYESQlxZRAdhs3UhbB6pVRNUELQOHXwK9ruDkwmCv2aZ5y0SApQzUJCg02p3A7Ue2J5hxvlk1YI53c00NmRyQ==} + engines: {node: ^18.17.0 || >=20.5.0} + + '@npmcli/move-file@1.1.2': + resolution: {integrity: sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==} + engines: {node: '>=10'} + deprecated: This functionality has been moved to @npmcli/fs + + '@npmcli/package-json@6.1.1': + resolution: {integrity: sha512-d5qimadRAUCO4A/Txw71VM7UrRZzV+NPclxz/dc+M6B2oYwjWTjqh8HA/sGQgs9VZuJ6I/P7XIAlJvgrl27ZOw==} + engines: {node: ^18.17.0 || >=20.5.0} + + '@npmcli/promise-spawn@8.0.2': + resolution: {integrity: sha512-/bNJhjc+o6qL+Dwz/bqfTQClkEO5nTQ1ZEcdCkAQjhkZMHIh22LPG7fNh1enJP1NKWDqYiiABnjFCY7E0zHYtQ==} + engines: {node: ^18.17.0 || >=20.5.0} + + '@oclif/command@1.8.36': + resolution: {integrity: sha512-/zACSgaYGtAQRzc7HjzrlIs14FuEYAZrMOEwicRoUnZVyRunG4+t5iSEeQu0Xy2bgbCD0U1SP/EdeNZSTXRwjQ==} + engines: {node: '>=12.0.0'} + deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info. + peerDependencies: + '@oclif/config': ^1 + + '@oclif/config@1.18.16': + resolution: {integrity: sha512-VskIxVcN22qJzxRUq+raalq6Q3HUde7sokB7/xk5TqRZGEKRVbFeqdQBxDWwQeudiJEgcNiMvIFbMQ43dY37FA==} + engines: {node: '>=8.0.0'} + deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info. + + '@oclif/config@1.18.17': + resolution: {integrity: sha512-k77qyeUvjU8qAJ3XK3fr/QVAqsZO8QOBuESnfeM5HHtPNLSyfVcwiMM2zveSW5xRdLSG3MfV8QnLVkuyCL2ENg==} + engines: {node: '>=8.0.0'} + deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info. + + '@oclif/core@2.16.0': + resolution: {integrity: sha512-dL6atBH0zCZl1A1IXCKJgLPrM/wR7K+Wi401E/IvqsK8m2iCHW+0TEOGrans/cuN3oTW+uxIyJFHJ8Im0k4qBw==} + engines: {node: '>=14.0.0'} + + '@oclif/core@4.4.1': + resolution: {integrity: sha512-RYonV4IJZcGAoi3pdo5CPl5hVH1YdtQMEX77TLdgTPVrMmIjbiB0Borfguj/mdDF2TjLXp+Z+RbmLUejuhSYTA==} + engines: {node: '>=18.0.0'} + + '@oclif/errors@1.3.6': + resolution: {integrity: sha512-fYaU4aDceETd89KXP+3cLyg9EHZsLD3RxF2IU9yxahhBpspWjkWi3Dy3bTgcwZ3V47BgxQaGapzJWDM33XIVDQ==} + engines: {node: '>=8.0.0'} + deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info. + + '@oclif/help@1.0.15': + resolution: {integrity: sha512-Yt8UHoetk/XqohYX76DfdrUYLsPKMc5pgkzsZVHDyBSkLiGRzujVaGZdjr32ckVZU9q3a47IjhWxhip7Dz5W/g==} + engines: {node: '>=8.0.0'} + deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info. + + '@oclif/linewrap@1.0.0': + resolution: {integrity: sha512-Ups2dShK52xXa8w6iBWLgcjPJWjais6KPJQq3gQ/88AY6BXoTX+MIGFPrWQO1KLMiQfoTpcLnUwloN4brrVUHw==} + + '@oclif/parser@3.8.17': + resolution: {integrity: sha512-l04iSd0xoh/16TGVpXb81Gg3z7tlQGrEup16BrVLsZBK6SEYpYHRJZnM32BwZrHI97ZSFfuSwVlzoo6HdsaK8A==} + engines: {node: '>=8.0.0'} + deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info. + + '@oclif/plugin-help@5.2.20': + resolution: {integrity: sha512-u+GXX/KAGL9S10LxAwNUaWdzbEBARJ92ogmM7g3gDVud2HioCmvWQCDohNRVZ9GYV9oKwZ/M8xwd6a1d95rEKQ==} + engines: {node: '>=12.0.0'} + + '@oclif/plugin-warn-if-update-available@3.1.42': + resolution: {integrity: sha512-bcBfON81gYCx6x50HjrcL7gRiz7bEuLdQNifMsMcBtBq3IpOifyS8/l5R3REEy9kHJ1qdcSYehtopMvS4ov9lA==} + engines: {node: '>=18.0.0'} + + '@octokit/auth-token@5.1.2': + resolution: {integrity: sha512-JcQDsBdg49Yky2w2ld20IHAlwr8d/d8N6NiOXbtuoPCqzbsiJgF633mVUw3x4mo0H5ypataQIX7SFu3yy44Mpw==} + engines: {node: '>= 18'} + + '@octokit/core@6.1.4': + resolution: {integrity: sha512-lAS9k7d6I0MPN+gb9bKDt7X8SdxknYqAMh44S5L+lNqIN2NuV8nvv3g8rPp7MuRxcOpxpUIATWprO0C34a8Qmg==} + engines: {node: '>= 18'} + + '@octokit/endpoint@10.1.3': + resolution: {integrity: sha512-nBRBMpKPhQUxCsQQeW+rCJ/OPSMcj3g0nfHn01zGYZXuNDvvXudF/TYY6APj5THlurerpFN4a/dQAIAaM6BYhA==} + engines: {node: '>= 18'} + + '@octokit/graphql@8.2.1': + resolution: {integrity: sha512-n57hXtOoHrhwTWdvhVkdJHdhTv0JstjDbDRhJfwIRNfFqmSo1DaK/mD2syoNUoLCyqSjBpGAKOG0BuwF392slw==} + engines: {node: '>= 18'} + + '@octokit/openapi-types@23.0.1': + resolution: {integrity: sha512-izFjMJ1sir0jn0ldEKhZ7xegCTj/ObmEDlEfpFrx4k/JyZSMRHbO3/rBwgE7f3m2DHt+RrNGIVw4wSmwnm3t/g==} + + '@octokit/plugin-paginate-rest@11.4.3': + resolution: {integrity: sha512-tBXaAbXkqVJlRoA/zQVe9mUdb8rScmivqtpv3ovsC5xhje/a+NOCivs7eUhWBwCApJVsR4G5HMeaLbq7PxqZGA==} + engines: {node: '>= 18'} + peerDependencies: + '@octokit/core': '>=6' + + '@octokit/plugin-request-log@5.3.1': + resolution: {integrity: sha512-n/lNeCtq+9ofhC15xzmJCNKP2BWTv8Ih2TTy+jatNCCq/gQP/V7rK3fjIfuz0pDWDALO/o/4QY4hyOF6TQQFUw==} + engines: {node: '>= 18'} + peerDependencies: + '@octokit/core': '>=6' + + '@octokit/plugin-rest-endpoint-methods@13.3.1': + resolution: {integrity: sha512-o8uOBdsyR+WR8MK9Cco8dCgvG13H1RlM1nWnK/W7TEACQBFux/vPREgKucxUfuDQ5yi1T3hGf4C5ZmZXAERgwQ==} + engines: {node: '>= 18'} + peerDependencies: + '@octokit/core': '>=6' + + '@octokit/request-error@6.1.7': + resolution: {integrity: sha512-69NIppAwaauwZv6aOzb+VVLwt+0havz9GT5YplkeJv7fG7a40qpLt/yZKyiDxAhgz0EtgNdNcb96Z0u+Zyuy2g==} + engines: {node: '>= 18'} + + '@octokit/request@9.2.2': + resolution: {integrity: sha512-dZl0ZHx6gOQGcffgm1/Sf6JfEpmh34v3Af2Uci02vzUYz6qEN6zepoRtmybWXIGXFIK8K9ylE3b+duCWqhArtg==} + engines: {node: '>= 18'} + + '@octokit/rest@21.1.1': + resolution: {integrity: sha512-sTQV7va0IUVZcntzy1q3QqPm/r8rWtDCqpRAmb8eXXnKkjoQEtFe3Nt5GTVsHft+R6jJoHeSiVLcgcvhtue/rg==} + engines: {node: '>= 18'} + + '@octokit/types@13.8.0': + resolution: {integrity: sha512-x7DjTIbEpEWXK99DMd01QfWy0hd5h4EN+Q7shkdKds3otGQP+oWE/y0A76i1OvH9fygo4ddvNf7ZvF0t78P98A==} + + '@pkgjs/parseargs@0.11.0': + resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} + engines: {node: '>=14'} + + '@pnpm/catalogs.config@1000.0.2': + resolution: {integrity: sha512-2GCYZwxmgw6w0bpB71VbbXapgIcSSFOF9vnS+YLyTdy8JaIYoag2XkhXP1cMu24THPRXeo/zKTyziEsqgr1u8w==} + engines: {node: '>=18.12'} + + '@pnpm/catalogs.protocol-parser@1000.0.0': + resolution: {integrity: sha512-8eC25RAiu8BTaEseQmbo5xemlSwl06pMsUVORiYGX7JZEDb0UQVXOnbqFFJMPe/dyO8uwGXnDb350nauMzaraA==} + engines: {node: '>=18.12'} + + '@pnpm/catalogs.resolver@1000.0.2': + resolution: {integrity: sha512-5xp3InFRgl6YzovSYoKs0NTalcVKRj4KkD/d0zIBsKp2cae0G/t2ZZVq3J5rS1Ytf4qkv4oe5SZWpd1oV7Hkew==} + engines: {node: '>=18.12'} + + '@pnpm/catalogs.types@1000.0.0': + resolution: {integrity: sha512-xRf72lk7xHNvbenA4sp4Of/90QDdRW0CRYT+V+EbqpUXu1xsXtedHai34cTU6VGe7C1hUukxxE9eYTtIpYrx5g==} + engines: {node: '>=18.12'} + + '@pnpm/cli-meta@1000.0.2': + resolution: {integrity: sha512-zNLog8D3vG9O0waUH5Rkzo3xow/LBPoD2VW7uZ+JLauEE4oVIS59EonrR08+GVt/lAVJ3y1F8wBxKw1c/pcU5A==} + engines: {node: '>=18.12'} + + '@pnpm/cli-utils@1000.0.10': + resolution: {integrity: sha512-iCcn7eGlKk6/oJPr1yatF5HBdrR16cdXOodrNUVWoZ8G43Y6gDR0wOw8kHs4+y3K8sxAMo4rFW5EDcMbixVO/A==} + engines: {node: '>=18.12'} + peerDependencies: + '@pnpm/logger': '>=5.1.0 <1001.0.0' + + '@pnpm/config.env-replace@1.1.0': + resolution: {integrity: sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w==} + engines: {node: '>=12.22.0'} + + '@pnpm/config.env-replace@3.0.0': + resolution: {integrity: sha512-tV71wOtu8ULW4Fv5c7MWph3Sfle1wkT2q83qF2Cx/0J5E2dpUsClO9evAouL4fbdmPonkXJbRYL5cGHKuqxr4w==} + engines: {node: '>=18.12'} + + '@pnpm/config@1002.3.1': + resolution: {integrity: sha512-eFu2+c91XW8+ql7yFfx9Xr7w2Z+uDdKpYpdGpP8kAA3NdZnZ1l18HLwrAdD3GoY1TWyoxI7b9uVcXEASy3r6/A==} + engines: {node: '>=18.12'} + + '@pnpm/constants@1001.1.0': + resolution: {integrity: sha512-xb9dfSGi1qfUKY3r4Zy9JdC9+ZeaDxwfE7HrrGIEsBVY1hvIn6ntbR7A97z3nk44yX7vwbINNf9sizTp0WEtEw==} + engines: {node: '>=18.12'} + + '@pnpm/core-loggers@1000.1.2': + resolution: {integrity: sha512-jOxjLqoC8mSX+vAj9JragTeqbZBWKswb/KX2MKKv+v1hKhyNqDPtNwJFBA1xnmNnuJnJ0fuFYUDV6tivktCFxA==} + engines: {node: '>=18.12'} + peerDependencies: + '@pnpm/logger': '>=5.1.0 <1001.0.0' + + '@pnpm/crypto.hash@1000.0.0': + resolution: {integrity: sha512-itIFxA9NUD27VSHob9bjqOH9ixfJaJJi5txqK+2GSQK2L+6I+zus0x/DxK6ezV7wWbPopBu2IM6vGV56fCTb/w==} + engines: {node: '>=18.12'} + + '@pnpm/crypto.polyfill@1000.0.0': + resolution: {integrity: sha512-viLJ4o3syjKiF1HVgZSnwVZlImAwQubNzdH/Ccm6lS0PZzwh94diLniSC/vBqaPgRmFkr6kspm/2vPfXA4vLsQ==} + engines: {node: '>=18.12'} + + '@pnpm/dedupe.issues-renderer@1000.0.1': + resolution: {integrity: sha512-zrCfk0HUQM8WhxCi3C0waGDKO0/gB4r3LgAUOQB4YTHPNr+m+iubznY0I5G776OqJfsPeLi4bByg4Y1wK29xlg==} + engines: {node: '>=18.12'} + + '@pnpm/dedupe.types@1000.0.0': + resolution: {integrity: sha512-+d8Q576BxRZgt03O+JZXK3C1xVJeAr4Hs35Y8SCl01KpQ0Z7xzfJWahpee7iFc5jELiwjCQg2sISTwtZZQFltA==} + engines: {node: '>=18.12'} + + '@pnpm/default-reporter@1001.3.1': + resolution: {integrity: sha512-4Zmm8QgY5vM0D2oZ1cEnYMf7VTwS4IX6Ei9ozYC9vx8k8QLHsKtUuErLzY+3Az9dQYJV++rzTpnHldGkGZQmlQ==} + engines: {node: '>=18.12'} + peerDependencies: + '@pnpm/logger': '>=5.1.0 <1001.0.0' + + '@pnpm/env.system-node-version@1000.0.2': + resolution: {integrity: sha512-648LcCKAV46yJjO74Em0HoOb5IVcXnVIgMC7EOiN5+kSKP855h1v+pg0dDuLO+W4xOV9/BmL6CJ/pscniTNWgw==} + engines: {node: '>=18.12'} + + '@pnpm/error@1000.0.2': + resolution: {integrity: sha512-2SfE4FFL73rE1WVIoESbqlj4sLy5nWW4M/RVdHvCRJPjlQHa9MH7m7CVJM204lz6I+eHoB+E7rL3zmpJR5wYnQ==} + engines: {node: '>=18.12'} + + '@pnpm/fetcher-base@1000.0.3': + resolution: {integrity: sha512-jnv/FP1K7k1QF4ralk5TwHALOA5DRP8LWSYJRc7qk5O8so48E9I0H46/AXQz4ZSd36TGY5xObt1UmoNIqdTOAA==} + engines: {node: '>=18.12'} + + '@pnpm/fs.find-packages@1000.0.5': + resolution: {integrity: sha512-+OGmy5jFZsaZlG6fKYrtutGl4Wa28et/djVMzCn9o6vXRuIczYMWx3niWaaEECuBkf7AleOrR5/revSWKrfteQ==} + engines: {node: '>=18.12'} + + '@pnpm/git-utils@1000.0.0': + resolution: {integrity: sha512-W6isNTNgB26n6dZUgwCw6wly+uHQ2Zh5QiRKY1HHMbLAlsnZOxsSNGnuS9euKWHxDftvPfU7uR8XB5x95T5zPQ==} + engines: {node: '>=18.12'} + + '@pnpm/graceful-fs@1000.0.0': + resolution: {integrity: sha512-RvMEliAmcfd/4UoaYQ93DLQcFeqit78jhYmeJJVPxqFGmj0jEcb9Tu0eAOXr7tGP3eJHpgvPbTU4o6pZ1bJhxg==} + engines: {node: '>=18.12'} + + '@pnpm/hooks.types@1001.0.2': + resolution: {integrity: sha512-mbpq/K4xWNWdGmvCWBBOwYWj1yuZIpF28Y4TfX6rFrCK2RoMrhTaO92OPp1ap7QyCSNOrRHEeDwafPBj5l0/fw==} + engines: {node: '>=18.12'} + + '@pnpm/lockfile.types@1001.0.2': + resolution: {integrity: sha512-drx2TRYPWriUQDvFHygJ/MuacQ7BRvGvptENNX2QXAsnHx8G5ZYnF21XDc6fCkPG6f83Rw1PcHOaUHObLZbEeA==} + engines: {node: '>=18.12'} + + '@pnpm/logger@1000.0.0': + resolution: {integrity: sha512-v5WO9L4pT7ZjZpf7a/a3H3Xj59JPHNMFJwRS7m/01VMWrKjs89CdVIE5e/N6DwuzP750j0iKozTw6UrCVEfQjA==} + engines: {node: '>=18.12'} + + '@pnpm/manifest-utils@1000.0.4': + resolution: {integrity: sha512-rD6dcpSD1V7oQX9DGRG2tmfrWUuYN8FJb5ckqjFmebs3eR9whihA9/SGXZEhYotDeweuay2j4esdkGFGhoAx5A==} + engines: {node: '>=18.12'} + + '@pnpm/matcher@1000.0.0': + resolution: {integrity: sha512-MKulLUYdMFvZ3UOFsqpqn7nrA3OnHs210jYmI8Wxyczh1nG7icY49sUtlpYsEEbBA1arJpAXDGyU4hx58dk9Lg==} + engines: {node: '>=18.12'} + + '@pnpm/network.ca-file@1.0.2': + resolution: {integrity: sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA==} + engines: {node: '>=12.22.0'} + + '@pnpm/npm-conf@2.3.1': + resolution: {integrity: sha512-c83qWb22rNRuB0UaVCI0uRPNRr8Z0FWnEIvT47jiHAmOIUHbBOg5XvV7pM5x+rKn9HRpjxquDbXYSXr3fAKFcw==} + engines: {node: '>=12'} + + '@pnpm/npm-conf@3.0.0': + resolution: {integrity: sha512-LdFkv/+4ONkQ9ZyE8ihC2L2RcPjvNcOTQq6pvvvZp8KeDYATCJeJX7gpHZF3Bx1XvUSU35dyF9Q9dS+JShtOFA==} + engines: {node: '>=12'} + + '@pnpm/package-is-installable@1000.0.4': + resolution: {integrity: sha512-QC59IaRiZwnGLEWR55LswJlJRWuT4TXK9v4l4ayK1SuODlIqpDz1pORGegFyNUKfyUff5JhYoEx2S5PApY7b/g==} + engines: {node: '>=18.12'} + peerDependencies: + '@pnpm/logger': '>=5.1.0 <1001.0.0' + + '@pnpm/parse-overrides@1000.0.2': + resolution: {integrity: sha512-NII/zHEDIqtSNkDS39TD0r6ukKdZaQPwn6EjDEHYFacgbHN2d3i261paQvm0Pm0oX4svV+5x5YWHUTIbQJItDg==} + engines: {node: '>=18.12'} + + '@pnpm/parse-wanted-dependency@1000.0.0': + resolution: {integrity: sha512-SKK9m7leIQ0u6S+/LXREF0wTrFnyKiirLza6Dt0l7CL9pZdZtuI3mMvz6gNBFnIjTKJPwacdqRywT3bfK8W+FQ==} + engines: {node: '>=18.12'} + + '@pnpm/patching.types@1000.0.0': + resolution: {integrity: sha512-IzNrirYIcquD0tRGKkzj8q5eKh0zOVDL6rOu/sQSrlF6qWTu8YaWCI5LQoZPa1B5IGQTCJwhcoZlnGBHZyEXAg==} + engines: {node: '>=18.12'} + + '@pnpm/pnpmfile@1001.0.4': + resolution: {integrity: sha512-WDIsjZdM9Ol8XKtWbnl7nzS9+CFnf0HAz/2xxE/ksJ1fPG2VN2hbqHTsC9Szso11axVB6NU7JdEKy49jxBepVQ==} + engines: {node: '>=18.12'} + peerDependencies: + '@pnpm/logger': '>=5.1.0 <1001.0.0' + + '@pnpm/ramda@0.28.1': + resolution: {integrity: sha512-zcAG+lvU0fMziNeGXpPyCyCJYp5ZVrPElEE4t14jAmViaihohocZ+dDkcRIyAomox8pQsuZnv1EyHR+pOhmUWw==} + + '@pnpm/read-project-manifest@1000.0.5': + resolution: {integrity: sha512-DSnPRfQ2PjcICaGbmUWoC7W28x9pssVHkQIGafd62ljF4AMWhfWyZqlnZQOmiUBHoFDtYYkEXyC6drZ2Pko6lw==} + engines: {node: '>=18.12'} + + '@pnpm/render-peer-issues@1000.0.4': + resolution: {integrity: sha512-4TpIH4KRwi/tTkJQaU3/2A8/um50hdkHGjPzukdKjU837H/ZfZ0ARQQOPYR0axcuCHUov4l5gqQJ6q3Kmb26gQ==} + engines: {node: '>=18.12'} + + '@pnpm/resolver-base@1000.1.2': + resolution: {integrity: sha512-kU8vG7Tt18nIwzIpu0oWejdzg5uFPKSh6mPN/wvVNQZO1T3zcQtgILs28fY8u7ONZPHKV4lcbbEFI/KDiGewFg==} + engines: {node: '>=18.12'} + + '@pnpm/store-controller-types@1001.0.1': + resolution: {integrity: sha512-J0RGzZKgabxTcEQigs3lTiC4qtsJ6wM7Vtcr4l5hqWfMkDuHNoWI4n3bB/VtzMQ33WPldFpWnYFNJGLNJjOHbA==} + engines: {node: '>=18.12'} + + '@pnpm/text.comments-parser@1000.0.0': + resolution: {integrity: sha512-ivv/esrETOq9uMiKOC0ddVZ1BktEGsfsMQ9RWmrDpwPiqFSqWsIspnquxTBmm5GflC5N06fbqjGOpulZVYo3vQ==} + engines: {node: '>=18.12'} + + '@pnpm/types@1000.1.1': + resolution: {integrity: sha512-5zrv7B+4mW/6iiYS/BrFZWbMqLHjKmaBrMcw+F8LcuMQ7p4SQX4ANoycpr1VIQpn4+xQ0ckyuadfxBttpzicbg==} + engines: {node: '>=18.12'} + + '@pnpm/util.lex-comparator@3.0.0': + resolution: {integrity: sha512-ead+l3IiuVXwKDf/QJPX6G93cwhXki3yOVEA/VdAO7AhZ5vUuSBxHe6gQKEbB0QacJ4H5VsYxeM1xUgwjjOO/Q==} + engines: {node: '>=18.12'} + + '@pnpm/which@3.0.1': + resolution: {integrity: sha512-4ivtS12Oni9axgGefaq+gTPD+7N0VPCFdxFH8izCaWfnxLQblX3iVxba+25ZoagStlzUs8sQg8OMKlCVhyGWTw==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + hasBin: true + + '@pnpm/workspace.find-packages@1000.0.10': + resolution: {integrity: sha512-hwCaWOpDGau7xTGBFcIiyH3tX5Ysu8qJpaA8Kx9VBCmZwUqgmkn6IjLFIGjdjVr6jpAvYqrNlV8xRcvodkfQTA==} + engines: {node: '>=18.12'} + peerDependencies: + '@pnpm/logger': '>=5.1.0 <1001.0.0' + + '@pnpm/workspace.read-manifest@1000.0.2': + resolution: {integrity: sha512-MKWL07/ZHmvOZG8UzbIBMib4EiYi8+rXpk49a8ditR2E/RsIj3p0ICKG9S2nFfIjeJCEOtxO6HDXXQIn4iYyiw==} + engines: {node: '>=18.12'} + + '@pnpm/write-project-manifest@1000.0.2': + resolution: {integrity: sha512-vIwllRvCfSlaIlbE7GJwDStiwigisYI4IstouP5a1Th8nP+QutJZeqPRNCQWjaWn4XTCs0kcPWBg2sOA2D8+Mw==} + engines: {node: '>=18.12'} + + '@publint/pack@0.1.1': + resolution: {integrity: sha512-TvCl79Y8v18ZhFGd5mjO1kYPovSBq3+4LVCi5Nfl1JI8fS8i8kXbgQFGwBJRXczim8GlW8c2LMBKTtExYXOy/A==} + engines: {node: '>=18'} + + '@puppeteer/browsers@2.10.5': + resolution: {integrity: sha512-eifa0o+i8dERnngJwKrfp3dEq7ia5XFyoqB17S4gK8GhsQE4/P8nxOfQSE0zQHxzzLo/cmF+7+ywEQ7wK7Fb+w==} + engines: {node: '>=18'} + hasBin: true + + '@puppeteer/browsers@2.6.1': + resolution: {integrity: sha512-aBSREisdsGH890S2rQqK82qmQYU3uFpSH8wcZWHgHzl3LfzsxAKbLNiAG9mO8v1Y0UICBeClICxPJvyr0rcuxg==} + engines: {node: '>=18'} + hasBin: true + + '@rollup/plugin-babel@6.0.4': + resolution: {integrity: sha512-YF7Y52kFdFT/xVSuVdjkV5ZdX/3YtmX0QulG+x0taQOtJdHYzVU61aSSkAgVJ7NOv6qPkIYiJSgSWWN/DM5sGw==} + engines: {node: '>=14.0.0'} + peerDependencies: + '@babel/core': ^7.0.0 + '@types/babel__core': ^7.1.9 + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + '@types/babel__core': + optional: true + rollup: + optional: true + + '@rollup/plugin-commonjs@28.0.2': + resolution: {integrity: sha512-BEFI2EDqzl+vA1rl97IDRZ61AIwGH093d9nz8+dThxJNH8oSoB7MjWvPCX3dkaK1/RCJ/1v/R1XB15FuSs0fQw==} + engines: {node: '>=16.0.0 || 14 >= 14.17'} + peerDependencies: + rollup: ^2.68.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + + '@rollup/plugin-inject@5.0.5': + resolution: {integrity: sha512-2+DEJbNBoPROPkgTDNe8/1YXWcqxbN5DTjASVIOx8HS+pITXushyNiBV56RB08zuptzz8gT3YfkqriTBVycepg==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + + '@rollup/plugin-node-resolve@16.0.0': + resolution: {integrity: sha512-0FPvAeVUT/zdWoO0jnb/V5BlBsUSNfkIOtFHzMO4H9MOklrmQFY6FduVHKucNb/aTFxvnGhj4MNj/T1oNdDfNg==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^2.78.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + + '@rollup/plugin-replace@6.0.2': + resolution: {integrity: sha512-7QaYCf8bqF04dOy7w/eHmJeNExxTYwvKAmlSAH/EaWWUzbT0h5sbF6bktFoX/0F/0qwng5/dWFMyf3gzaM8DsQ==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + + '@rollup/plugin-sucrase@5.0.2': + resolution: {integrity: sha512-4MhIVH9Dy2Hwose1/x5QMs0XF7yn9jDd/yozHqzdIrMWIolgFpGnrnVhQkqTaK1RALY/fpyrEKmwH/04vr1THA==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^2.53.1||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + + '@rollup/plugin-swc@0.4.0': + resolution: {integrity: sha512-oAtqXa8rOl7BOK1Rz3rRxI+LIL53S9SqO2KSq2UUUzWgOgXg6492Jh5mL2mv/f9cpit8zFWdwILuVeozZ0C8mg==} + engines: {node: '>=14.0.0'} + peerDependencies: + '@swc/core': ^1.3.0 + rollup: ^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + + '@rollup/plugin-terser@0.4.4': + resolution: {integrity: sha512-XHeJC5Bgvs8LfukDwWZp7yeqin6ns8RTl2B9avbejt6tZqsqvVoWI7ZTQrcNsfKEDWBTnTxM8nMDkO2IFFbd0A==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + + '@rollup/plugin-typescript@12.1.2': + resolution: {integrity: sha512-cdtSp154H5sv637uMr1a8OTWB0L1SWDSm1rDGiyfcGcvQ6cuTs4MDk2BVEBGysUWago4OJN4EQZqOTl/QY3Jgg==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^2.14.0||^3.0.0||^4.0.0 + tslib: '*' + typescript: ^5.7.3 + peerDependenciesMeta: + rollup: + optional: true + tslib: + optional: true + + '@rollup/pluginutils@5.1.4': + resolution: {integrity: sha512-USm05zrsFxYLPdWWq+K3STlWiT/3ELn3RcV5hJMghpeAIhxfsUIg6mt12CBJBInWMV4VneoV7SfGv8xIwo2qNQ==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + + '@rollup/rollup-android-arm-eabi@4.34.8': + resolution: {integrity: sha512-q217OSE8DTp8AFHuNHXo0Y86e1wtlfVrXiAlwkIvGRQv9zbc6mE3sjIVfwI8sYUyNxwOg0j/Vm1RKM04JcWLJw==} + cpu: [arm] + os: [android] + + '@rollup/rollup-android-arm-eabi@4.44.1': + resolution: {integrity: sha512-JAcBr1+fgqx20m7Fwe1DxPUl/hPkee6jA6Pl7n1v2EFiktAHenTaXl5aIFjUIEsfn9w3HE4gK1lEgNGMzBDs1w==} + cpu: [arm] + os: [android] + + '@rollup/rollup-android-arm64@4.34.8': + resolution: {integrity: sha512-Gigjz7mNWaOL9wCggvoK3jEIUUbGul656opstjaUSGC3eT0BM7PofdAJaBfPFWWkXNVAXbaQtC99OCg4sJv70Q==} + cpu: [arm64] + os: [android] + + '@rollup/rollup-android-arm64@4.44.1': + resolution: {integrity: sha512-RurZetXqTu4p+G0ChbnkwBuAtwAbIwJkycw1n6GvlGlBuS4u5qlr5opix8cBAYFJgaY05TWtM+LaoFggUmbZEQ==} + cpu: [arm64] + os: [android] + + '@rollup/rollup-darwin-arm64@4.34.8': + resolution: {integrity: sha512-02rVdZ5tgdUNRxIUrFdcMBZQoaPMrxtwSb+/hOfBdqkatYHR3lZ2A2EGyHq2sGOd0Owk80oV3snlDASC24He3Q==} + cpu: [arm64] + os: [darwin] + + '@rollup/rollup-darwin-arm64@4.44.1': + resolution: {integrity: sha512-fM/xPesi7g2M7chk37LOnmnSTHLG/v2ggWqKj3CCA1rMA4mm5KVBT1fNoswbo1JhPuNNZrVwpTvlCVggv8A2zg==} + cpu: [arm64] + os: [darwin] + + '@rollup/rollup-darwin-x64@4.34.8': + resolution: {integrity: sha512-qIP/elwR/tq/dYRx3lgwK31jkZvMiD6qUtOycLhTzCvrjbZ3LjQnEM9rNhSGpbLXVJYQ3rq39A6Re0h9tU2ynw==} + cpu: [x64] + os: [darwin] + + '@rollup/rollup-darwin-x64@4.44.1': + resolution: {integrity: sha512-gDnWk57urJrkrHQ2WVx9TSVTH7lSlU7E3AFqiko+bgjlh78aJ88/3nycMax52VIVjIm3ObXnDL2H00e/xzoipw==} + cpu: [x64] + os: [darwin] + + '@rollup/rollup-freebsd-arm64@4.34.8': + resolution: {integrity: sha512-IQNVXL9iY6NniYbTaOKdrlVP3XIqazBgJOVkddzJlqnCpRi/yAeSOa8PLcECFSQochzqApIOE1GHNu3pCz+BDA==} + cpu: [arm64] + os: [freebsd] + + '@rollup/rollup-freebsd-arm64@4.44.1': + resolution: {integrity: sha512-wnFQmJ/zPThM5zEGcnDcCJeYJgtSLjh1d//WuHzhf6zT3Md1BvvhJnWoy+HECKu2bMxaIcfWiu3bJgx6z4g2XA==} + cpu: [arm64] + os: [freebsd] + + '@rollup/rollup-freebsd-x64@4.34.8': + resolution: {integrity: sha512-TYXcHghgnCqYFiE3FT5QwXtOZqDj5GmaFNTNt3jNC+vh22dc/ukG2cG+pi75QO4kACohZzidsq7yKTKwq/Jq7Q==} + cpu: [x64] + os: [freebsd] + + '@rollup/rollup-freebsd-x64@4.44.1': + resolution: {integrity: sha512-uBmIxoJ4493YATvU2c0upGz87f99e3wop7TJgOA/bXMFd2SvKCI7xkxY/5k50bv7J6dw1SXT4MQBQSLn8Bb/Uw==} + cpu: [x64] + os: [freebsd] + + '@rollup/rollup-linux-arm-gnueabihf@4.34.8': + resolution: {integrity: sha512-A4iphFGNkWRd+5m3VIGuqHnG3MVnqKe7Al57u9mwgbyZ2/xF9Jio72MaY7xxh+Y87VAHmGQr73qoKL9HPbXj1g==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm-gnueabihf@4.44.1': + resolution: {integrity: sha512-n0edDmSHlXFhrlmTK7XBuwKlG5MbS7yleS1cQ9nn4kIeW+dJH+ExqNgQ0RrFRew8Y+0V/x6C5IjsHrJmiHtkxQ==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm-musleabihf@4.34.8': + resolution: {integrity: sha512-S0lqKLfTm5u+QTxlFiAnb2J/2dgQqRy/XvziPtDd1rKZFXHTyYLoVL58M/XFwDI01AQCDIevGLbQrMAtdyanpA==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm-musleabihf@4.44.1': + resolution: {integrity: sha512-8WVUPy3FtAsKSpyk21kV52HCxB+me6YkbkFHATzC2Yd3yuqHwy2lbFL4alJOLXKljoRw08Zk8/xEj89cLQ/4Nw==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm64-gnu@4.34.8': + resolution: {integrity: sha512-jpz9YOuPiSkL4G4pqKrus0pn9aYwpImGkosRKwNi+sJSkz+WU3anZe6hi73StLOQdfXYXC7hUfsQlTnjMd3s1A==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-arm64-gnu@4.44.1': + resolution: {integrity: sha512-yuktAOaeOgorWDeFJggjuCkMGeITfqvPgkIXhDqsfKX8J3jGyxdDZgBV/2kj/2DyPaLiX6bPdjJDTu9RB8lUPQ==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-arm64-musl@4.34.8': + resolution: {integrity: sha512-KdSfaROOUJXgTVxJNAZ3KwkRc5nggDk+06P6lgi1HLv1hskgvxHUKZ4xtwHkVYJ1Rep4GNo+uEfycCRRxht7+Q==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-arm64-musl@4.44.1': + resolution: {integrity: sha512-W+GBM4ifET1Plw8pdVaecwUgxmiH23CfAUj32u8knq0JPFyK4weRy6H7ooxYFD19YxBulL0Ktsflg5XS7+7u9g==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-loongarch64-gnu@4.34.8': + resolution: {integrity: sha512-NyF4gcxwkMFRjgXBM6g2lkT58OWztZvw5KkV2K0qqSnUEqCVcqdh2jN4gQrTn/YUpAcNKyFHfoOZEer9nwo6uQ==} + cpu: [loong64] + os: [linux] + + '@rollup/rollup-linux-loongarch64-gnu@4.44.1': + resolution: {integrity: sha512-1zqnUEMWp9WrGVuVak6jWTl4fEtrVKfZY7CvcBmUUpxAJ7WcSowPSAWIKa/0o5mBL/Ij50SIf9tuirGx63Ovew==} + cpu: [loong64] + os: [linux] + + '@rollup/rollup-linux-powerpc64le-gnu@4.34.8': + resolution: {integrity: sha512-LMJc999GkhGvktHU85zNTDImZVUCJ1z/MbAJTnviiWmmjyckP5aQsHtcujMjpNdMZPT2rQEDBlJfubhs3jsMfw==} + cpu: [ppc64] + os: [linux] + + '@rollup/rollup-linux-powerpc64le-gnu@4.44.1': + resolution: {integrity: sha512-Rl3JKaRu0LHIx7ExBAAnf0JcOQetQffaw34T8vLlg9b1IhzcBgaIdnvEbbsZq9uZp3uAH+JkHd20Nwn0h9zPjA==} + cpu: [ppc64] + os: [linux] + + '@rollup/rollup-linux-riscv64-gnu@4.34.8': + resolution: {integrity: sha512-xAQCAHPj8nJq1PI3z8CIZzXuXCstquz7cIOL73HHdXiRcKk8Ywwqtx2wrIy23EcTn4aZ2fLJNBB8d0tQENPCmw==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-riscv64-gnu@4.44.1': + resolution: {integrity: sha512-j5akelU3snyL6K3N/iX7otLBIl347fGwmd95U5gS/7z6T4ftK288jKq3A5lcFKcx7wwzb5rgNvAg3ZbV4BqUSw==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-riscv64-musl@4.44.1': + resolution: {integrity: sha512-ppn5llVGgrZw7yxbIm8TTvtj1EoPgYUAbfw0uDjIOzzoqlZlZrLJ/KuiE7uf5EpTpCTrNt1EdtzF0naMm0wGYg==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-s390x-gnu@4.34.8': + resolution: {integrity: sha512-DdePVk1NDEuc3fOe3dPPTb+rjMtuFw89gw6gVWxQFAuEqqSdDKnrwzZHrUYdac7A7dXl9Q2Vflxpme15gUWQFA==} + cpu: [s390x] + os: [linux] + + '@rollup/rollup-linux-s390x-gnu@4.44.1': + resolution: {integrity: sha512-Hu6hEdix0oxtUma99jSP7xbvjkUM/ycke/AQQ4EC5g7jNRLLIwjcNwaUy95ZKBJJwg1ZowsclNnjYqzN4zwkAw==} + cpu: [s390x] + os: [linux] + + '@rollup/rollup-linux-x64-gnu@4.34.8': + resolution: {integrity: sha512-8y7ED8gjxITUltTUEJLQdgpbPh1sUQ0kMTmufRF/Ns5tI9TNMNlhWtmPKKHCU0SilX+3MJkZ0zERYYGIVBYHIA==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-linux-x64-gnu@4.44.1': + resolution: {integrity: sha512-EtnsrmZGomz9WxK1bR5079zee3+7a+AdFlghyd6VbAjgRJDbTANJ9dcPIPAi76uG05micpEL+gPGmAKYTschQw==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-linux-x64-musl@4.34.8': + resolution: {integrity: sha512-SCXcP0ZpGFIe7Ge+McxY5zKxiEI5ra+GT3QRxL0pMMtxPfpyLAKleZODi1zdRHkz5/BhueUrYtYVgubqe9JBNQ==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-linux-x64-musl@4.44.1': + resolution: {integrity: sha512-iAS4p+J1az6Usn0f8xhgL4PaU878KEtutP4hqw52I4IO6AGoyOkHCxcc4bqufv1tQLdDWFx8lR9YlwxKuv3/3g==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-win32-arm64-msvc@4.34.8': + resolution: {integrity: sha512-YHYsgzZgFJzTRbth4h7Or0m5O74Yda+hLin0irAIobkLQFRQd1qWmnoVfwmKm9TXIZVAD0nZ+GEb2ICicLyCnQ==} + cpu: [arm64] + os: [win32] + + '@rollup/rollup-win32-arm64-msvc@4.44.1': + resolution: {integrity: sha512-NtSJVKcXwcqozOl+FwI41OH3OApDyLk3kqTJgx8+gp6On9ZEt5mYhIsKNPGuaZr3p9T6NWPKGU/03Vw4CNU9qg==} + cpu: [arm64] + os: [win32] + + '@rollup/rollup-win32-ia32-msvc@4.34.8': + resolution: {integrity: sha512-r3NRQrXkHr4uWy5TOjTpTYojR9XmF0j/RYgKCef+Ag46FWUTltm5ziticv8LdNsDMehjJ543x/+TJAek/xBA2w==} + cpu: [ia32] + os: [win32] + + '@rollup/rollup-win32-ia32-msvc@4.44.1': + resolution: {integrity: sha512-JYA3qvCOLXSsnTR3oiyGws1Dm0YTuxAAeaYGVlGpUsHqloPcFjPg+X0Fj2qODGLNwQOAcCiQmHub/V007kiH5A==} + cpu: [ia32] + os: [win32] + + '@rollup/rollup-win32-x64-msvc@4.34.8': + resolution: {integrity: sha512-U0FaE5O1BCpZSeE6gBl3c5ObhePQSfk9vDRToMmTkbhCOgW4jqvtS5LGyQ76L1fH8sM0keRp4uDTsbjiUyjk0g==} + cpu: [x64] + os: [win32] + + '@rollup/rollup-win32-x64-msvc@4.44.1': + resolution: {integrity: sha512-J8o22LuF0kTe7m+8PvW9wk3/bRq5+mRo5Dqo6+vXb7otCm3TPhYOJqOaQtGU9YMWQSL3krMnoOxMr0+9E6F3Ug==} + cpu: [x64] + os: [win32] + + '@rtsao/scc@1.1.0': + resolution: {integrity: sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==} + + '@samverschueren/stream-to-observable@0.3.1': + resolution: {integrity: sha512-c/qwwcHyafOQuVQJj0IlBjf5yYgBI7YPJ77k4fOJYesb41jio65eaJODRUmfYKhTOFBrIZ66kgvGPlNbjuoRdQ==} + engines: {node: '>=6'} + peerDependencies: + rxjs: '*' + zen-observable: '*' + peerDependenciesMeta: + rxjs: + optional: true + zen-observable: + optional: true + + '@sec-ant/readable-stream@0.4.1': + resolution: {integrity: sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==} + + '@simple-dom/document@1.4.0': + resolution: {integrity: sha512-/RUeVH4kuD3rzo5/91+h4Z1meLSLP66eXqpVAw/4aZmYozkeqUkMprq0znL4psX/adEed5cBgiNJcfMz/eKZLg==} + + '@simple-dom/interface@1.4.0': + resolution: {integrity: sha512-l5qumKFWU0S+4ZzMaLXFU8tQZsicHEMEyAxI5kDFGhJsRqDwe0a7/iPA/GdxlGyDKseQQAgIz5kzU7eXTrlSpA==} + + '@simple-dom/serializer@1.4.0': + resolution: {integrity: sha512-mI1yRahsVs8atXLiQksineDsFEFqeG7RHwnnBTDOK6inbzl4tZQgjR+Z7edjgIJq5j5RhZvwPI6EuCji9B3eQw==} + + '@simple-dom/void-map@1.4.0': + resolution: {integrity: sha512-VDhLEyVCbuhOBBgHol9ShzIv9O8UCzdXeH4FoXu2DOcu/nnvTjLTck+BgXsCLv5ynDiUdoqsREEVFnoyPpFKVw==} + + '@sindresorhus/is@4.6.0': + resolution: {integrity: sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==} + engines: {node: '>=10'} + + '@sindresorhus/merge-streams@2.3.0': + resolution: {integrity: sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==} + engines: {node: '>=18'} + + '@sindresorhus/merge-streams@4.0.0': + resolution: {integrity: sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==} + engines: {node: '>=18'} + + '@snyk/github-codeowners@1.1.0': + resolution: {integrity: sha512-lGFf08pbkEac0NYgVf4hdANpAgApRjNByLXB+WBip3qj1iendOIyAwP2GKkKbQMNVy2r1xxDf0ssfWscoiC+Vw==} + engines: {node: '>=8.10'} + hasBin: true + + '@socket.io/component-emitter@3.1.2': + resolution: {integrity: sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==} + + '@swc/core-darwin-arm64@1.9.3': + resolution: {integrity: sha512-hGfl/KTic/QY4tB9DkTbNuxy5cV4IeejpPD4zo+Lzt4iLlDWIeANL4Fkg67FiVceNJboqg48CUX+APhDHO5G1w==} + engines: {node: '>=10'} + cpu: [arm64] + os: [darwin] + + '@swc/core-darwin-x64@1.9.3': + resolution: {integrity: sha512-IaRq05ZLdtgF5h9CzlcgaNHyg4VXuiStnOFpfNEMuI5fm5afP2S0FHq8WdakUz5WppsbddTdplL+vpeApt/WCQ==} + engines: {node: '>=10'} + cpu: [x64] + os: [darwin] + + '@swc/core-linux-arm-gnueabihf@1.9.3': + resolution: {integrity: sha512-Pbwe7xYprj/nEnZrNBvZfjnTxlBIcfApAGdz2EROhjpPj+FBqBa3wOogqbsuGGBdCphf8S+KPprL1z+oDWkmSQ==} + engines: {node: '>=10'} + cpu: [arm] + os: [linux] + + '@swc/core-linux-arm64-gnu@1.9.3': + resolution: {integrity: sha512-AQ5JZiwNGVV/2K2TVulg0mw/3LYfqpjZO6jDPtR2evNbk9Yt57YsVzS+3vHSlUBQDRV9/jqMuZYVU3P13xrk+g==} + engines: {node: '>=10'} + cpu: [arm64] + os: [linux] + + '@swc/core-linux-arm64-musl@1.9.3': + resolution: {integrity: sha512-tzVH480RY6RbMl/QRgh5HK3zn1ZTFsThuxDGo6Iuk1MdwIbdFYUY034heWUTI4u3Db97ArKh0hNL0xhO3+PZdg==} + engines: {node: '>=10'} + cpu: [arm64] + os: [linux] + + '@swc/core-linux-x64-gnu@1.9.3': + resolution: {integrity: sha512-ivXXBRDXDc9k4cdv10R21ccBmGebVOwKXT/UdH1PhxUn9m/h8erAWjz5pcELwjiMf27WokqPgaWVfaclDbgE+w==} + engines: {node: '>=10'} + cpu: [x64] + os: [linux] + + '@swc/core-linux-x64-musl@1.9.3': + resolution: {integrity: sha512-ILsGMgfnOz1HwdDz+ZgEuomIwkP1PHT6maigZxaCIuC6OPEhKE8uYna22uU63XvYcLQvZYDzpR3ms47WQPuNEg==} + engines: {node: '>=10'} + cpu: [x64] + os: [linux] + + '@swc/core-win32-arm64-msvc@1.9.3': + resolution: {integrity: sha512-e+XmltDVIHieUnNJHtspn6B+PCcFOMYXNJB1GqoCcyinkEIQNwC8KtWgMqUucUbEWJkPc35NHy9k8aCXRmw9Kg==} + engines: {node: '>=10'} + cpu: [arm64] + os: [win32] + + '@swc/core-win32-ia32-msvc@1.9.3': + resolution: {integrity: sha512-rqpzNfpAooSL4UfQnHhkW8aL+oyjqJniDP0qwZfGnjDoJSbtPysHg2LpcOBEdSnEH+uIZq6J96qf0ZFD8AGfXA==} + engines: {node: '>=10'} + cpu: [ia32] + os: [win32] + + '@swc/core-win32-x64-msvc@1.9.3': + resolution: {integrity: sha512-3YJJLQ5suIEHEKc1GHtqVq475guiyqisKSoUnoaRtxkDaW5g1yvPt9IoSLOe2mRs7+FFhGGU693RsBUSwOXSdQ==} + engines: {node: '>=10'} + cpu: [x64] + os: [win32] + + '@swc/core@1.9.3': + resolution: {integrity: sha512-oRj0AFePUhtatX+BscVhnzaAmWjpfAeySpM1TCbxA1rtBDeH/JDhi5yYzAKneDYtVtBvA7ApfeuzhMC9ye4xSg==} + engines: {node: '>=10'} + peerDependencies: + '@swc/helpers': '*' + peerDependenciesMeta: + '@swc/helpers': + optional: true + + '@swc/counter@0.1.3': + resolution: {integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==} + + '@swc/types@0.1.23': + resolution: {integrity: sha512-u1iIVZV9Q0jxY+yM2vw/hZGDNudsN85bBpTqzAQ9rzkxW9D+e3aEM4Han+ow518gSewkXgjmEK0BD79ZcNVgPw==} + + '@szmarczak/http-timer@4.0.6': + resolution: {integrity: sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==} + engines: {node: '>=10'} + + '@tootallnate/once@1.1.2': + resolution: {integrity: sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==} + engines: {node: '>= 6'} + + '@tootallnate/quickjs-emscripten@0.23.0': + resolution: {integrity: sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==} + + '@tracerbench/core@8.0.1': + resolution: {integrity: sha512-xS+mOLDd0uqI6dBGgnl3HRFUTtmqjEqe53JncoINzuSk1za8hkND60GoqyMjhpq7tyXo1QHhcXXTkZ9YX39gVQ==} + hasBin: true + + '@tracerbench/find-chrome@2.0.0': + resolution: {integrity: sha512-tqx3LNo7vLkEVdI0ou0kCTKbG4blgb9th4e/YIEBpDzBNHokB5X/owBII/M4AYkOLnfX3WnTAEE8F7WmenVMkQ==} + + '@tracerbench/har@8.0.0': + resolution: {integrity: sha512-FyzUGft8uN3h3Qar9Lf5qjIwxFgNx6oH7ohZfdLhaT0mVoGLKYWJhKNq0sIBKY9ilK+gw0QAOf38tKw7zuVL8Q==} + + '@tracerbench/message-transport@2.0.0': + resolution: {integrity: sha512-PtgWnELGF9j3CSlqJX3vVw3s46eMlt4OnwQUh1yAvqAcdzjfXyJeCrRa/YSbt4tyvLfHKGPVmcuHBuBO1/rrtQ==} + + '@tracerbench/protocol-connection@2.0.0': + resolution: {integrity: sha512-S43URQlQ8L1ZkvHGpqglRv8f1fal92JASoKvT7t7VQElFYb/juV/CM69lp10f2gGPY4A/iIu7c2BwK0v1FwSdw==} + peerDependencies: + devtools-protocol: '*' + + '@tracerbench/protocol-transport@2.0.0': + resolution: {integrity: sha512-Z62tfmARhQ/lpl4Q1ZDGnNqQyyNlme1YLJa9Egak7joOEDmyxrJpmeTszW/XhaAYuaZQihB6nTXzLzjRwfyqWw==} + + '@tracerbench/spawn-chrome@2.0.0': + resolution: {integrity: sha512-B2PFea2zMuZHVf312lH/fyePmDu9BNOWap0RFXmJW9Rw8jwnDLo3L5oR6Vj17dkUF958HAmHiwL3eUpbqPcgng==} + + '@tracerbench/spawn@2.0.0': + resolution: {integrity: sha512-Bj8w1Tx51BkA4ES5MI9UE7nX9rJDXwL5MeDTHOowyFM/OSqUblVc+I9Lb5+9Nllw8oFBV37ue9JquIE9iOti7w==} + + '@tracerbench/stats@8.0.1': + resolution: {integrity: sha512-VyP2UzvIiTEn5a2YhEFR/09keCX7Gv3WaUd8vTIQjjiNKHdMsmY7wba3ttsScFF0FMoDGPxV5NcnZAfgjJjtqw==} + + '@tracerbench/trace-event@8.0.0': + resolution: {integrity: sha512-V71xTeg0zpn8dQOIU5vxrhhn7a18WtGQiFV+K8wpvx5kom/CKTJKWxr92S6GEmmLb5C2AHo3OQ4ZxlOn4sst4Q==} + + '@tracerbench/trace-model@8.0.0': + resolution: {integrity: sha512-jIpHFWffjtnQ2h4vg0ZGjVvjL1U19sjdgOzisSGNgrzpNgmbn10kCbVvfhsM2w5gr1HBAJX2ZsnNO1ZKXNdzkA==} + + '@tracerbench/websocket-message-transport@2.0.0': + resolution: {integrity: sha512-fw4i7RNc/6Ps/h0yXq93yDav8BGX1HcjTdaXxFqLDl5ijK2JngAswPaOn/Dof41+jG0s90Yy3pA2lCAJzcL58Q==} + + '@trysound/sax@0.2.0': + resolution: {integrity: sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==} + engines: {node: '>=10.13.0'} + + '@tsconfig/node10@1.0.11': + resolution: {integrity: sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==} + + '@tsconfig/node12@1.0.11': + resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==} + + '@tsconfig/node14@1.0.3': + resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==} + + '@tsconfig/node16@1.0.4': + resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==} + + '@tsconfig/strictest@2.0.5': + resolution: {integrity: sha512-ec4tjL2Rr0pkZ5hww65c+EEPYwxOi4Ryv+0MtjeaSQRJyq322Q27eOQiFbuNgw2hpL4hB1/W/HBGk3VKS43osg==} + + '@types/babel-plugin-macros@3.1.3': + resolution: {integrity: sha512-JU+MgpsHK3taY18mBETy5XlwY6LVngte7QXYzUuXEaaX0CN8dBqbjXtADe+gJmkSQE1FJHufzPj++OWZlhRmGw==} + + '@types/babel__core@7.20.5': + resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} + + '@types/babel__generator@7.6.8': + resolution: {integrity: sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==} + + '@types/babel__template@7.4.4': + resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==} + + '@types/babel__traverse@7.20.7': + resolution: {integrity: sha512-dkO5fhS7+/oos4ciWxyEyjWe48zmG6wbCheo/G2ZnHx4fs3EU6YC6UM8rk56gAjNJ9P3MTH2jo5jb92/K6wbng==} + + '@types/cacheable-request@6.0.3': + resolution: {integrity: sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==} + + '@types/cli-progress@3.11.6': + resolution: {integrity: sha512-cE3+jb9WRlu+uOSAugewNpITJDt1VF8dHOopPO4IABFc3SXYL5WE/+PTz/FCdZRRfIujiWW3n3aMbv1eIGVRWA==} + + '@types/cookie@0.4.1': + resolution: {integrity: sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==} + + '@types/cors@2.8.17': + resolution: {integrity: sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==} + + '@types/d3-hierarchy@3.1.7': + resolution: {integrity: sha512-tJFtNoYBtRtkNysX1Xq4sxtjK8YgoWUNpIiUee0/jHGRwqvzYxkq0hGVbbOGSz+JgFxxRu4K8nb3YpG3CMARtg==} + + '@types/doctrine@0.0.9': + resolution: {integrity: sha512-eOIHzCUSH7SMfonMG1LsC2f8vxBFtho6NGBznK41R84YzPuvSBzrhEps33IsQiOW9+VL6NQ9DbjQJznk/S4uRA==} + + '@types/eslint-utils@3.0.5': + resolution: {integrity: sha512-dGOLJqHXpjomkPgZiC7vnVSJtFIOM1Y6L01EyUhzPuD0y0wfIGiqxiGs3buUBfzxLIQHrCvZsIMDaCZ8R5IIoA==} + + '@types/eslint@9.6.1': + resolution: {integrity: sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==} + + '@types/eslint__eslintrc@2.1.2': + resolution: {integrity: sha512-qXvzPFY7Rz05xD8ZApXJ3S8xStQD2Ibzu3EFIF0UMNOAfLY5xUu3H61q0JrHo2OXD6rcFG75yUxNQbkKtFKBSw==} + + '@types/estree@1.0.6': + resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} + + '@types/estree@1.0.8': + resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} + + '@types/fs-extra@11.0.4': + resolution: {integrity: sha512-yTbItCNreRooED33qjunPthRcSjERP1r4MqCZc7wv0u2sUkzTFp45tgUfS5+r7FrZPdmCCNflLhVSP/o+SemsQ==} + + '@types/glob@8.1.0': + resolution: {integrity: sha512-IO+MJPVhoqz+28h1qLAcBEH2+xHMK6MTyHJc7MTnnYb6wsoLR29POVGJ7LycmVXIqyy/4/2ShP5sUwTXuOwb/w==} + + '@types/handlebars@4.1.0': + resolution: {integrity: sha512-gq9YweFKNNB1uFK71eRqsd4niVkXrxHugqWFQkeLRJvGjnxsLr16bYtcsG4tOFwmYi0Bax+wCkbf1reUfdl4kA==} + deprecated: This is a stub types definition. handlebars provides its own type definitions, so you do not need this installed. + + '@types/http-cache-semantics@4.0.4': + resolution: {integrity: sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==} + + '@types/js-yaml@4.0.9': + resolution: {integrity: sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==} + + '@types/json-schema@7.0.15': + resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + + '@types/json5@0.0.29': + resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} + + '@types/jsonfile@6.1.4': + resolution: {integrity: sha512-D5qGUYwjvnNNextdU59/+fI+spnwtTFmyQP0h+PfIOSkNfpU6AOICUOkm4i0OnSk+NyjdPJrxCDro0sJsWlRpQ==} + + '@types/keyv@3.1.4': + resolution: {integrity: sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==} + + '@types/minimatch@5.1.2': + resolution: {integrity: sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==} + + '@types/minimist@1.2.5': + resolution: {integrity: sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==} + + '@types/node@22.13.4': + resolution: {integrity: sha512-ywP2X0DYtX3y08eFVx5fNIw7/uIv8hYUKgXoK8oayJlLnKcRfEYCxWMVE1XagUdVtCJlZT1AU4LXEABW+L1Peg==} + + '@types/normalize-package-data@2.4.4': + resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} + + '@types/parse-json@4.0.2': + resolution: {integrity: sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==} + + '@types/preval.macro@3.0.2': + resolution: {integrity: sha512-WGi6THl5HXdXq5RishLkAUPxk4XjYWbmLhEC14hpE92ER3AtZUUUu8SSIy1ntCtYamW8KaEpBlhJ6H6jubjDug==} + + '@types/qunit@2.19.12': + resolution: {integrity: sha512-II+C1wgzUia0g+tGAH+PBb4XiTm8/C/i6sN23r21NNskBYOYrv+qnW0tFQ/IxZzKVwrK4CTglf8YO3poJUclQA==} + + '@types/resolve@1.20.2': + resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==} + + '@types/responselike@1.0.3': + resolution: {integrity: sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==} + + '@types/ssri@7.1.5': + resolution: {integrity: sha512-odD/56S3B51liILSk5aXJlnYt99S6Rt9EFDDqGtJM26rKHApHcwyU/UoYHrzKkdkHMAIquGWCuHtQTbes+FRQw==} + + '@types/tar@6.1.13': + resolution: {integrity: sha512-IznnlmU5f4WcGTh2ltRu/Ijpmk8wiWXfF0VA4s+HPjHZgvFggk1YaIkbo5krX/zUCzWF8N/l4+W/LNxnvAJ8nw==} + + '@types/yauzl@2.10.3': + resolution: {integrity: sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==} + + '@typescript-eslint/eslint-plugin@8.24.1': + resolution: {integrity: sha512-ll1StnKtBigWIGqvYDVuDmXJHVH4zLVot1yQ4fJtLpL7qacwkxJc1T0bptqw+miBQ/QfUbhl1TcQ4accW5KUyA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + '@typescript-eslint/parser': ^8.0.0 || ^8.0.0-alpha.0 + eslint: ^8.57.0 || ^9.0.0 + typescript: ^5.7.3 + + '@typescript-eslint/parser@8.24.1': + resolution: {integrity: sha512-Tqoa05bu+t5s8CTZFaGpCH2ub3QeT9YDkXbPd3uQ4SfsLoh1/vv2GEYAioPoxCWJJNsenXlC88tRjwoHNts1oQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: ^5.7.3 + + '@typescript-eslint/parser@8.35.1': + resolution: {integrity: sha512-3MyiDfrfLeK06bi/g9DqJxP5pV74LNv4rFTyvGDmT3x2p1yp1lOd+qYZfiRPIOf/oON+WRZR5wxxuF85qOar+w==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: ^5.7.3 + + '@typescript-eslint/project-service@8.35.1': + resolution: {integrity: sha512-VYxn/5LOpVxADAuP3NrnxxHYfzVtQzLKeldIhDhzC8UHaiQvYlXvKuVho1qLduFbJjjy5U5bkGwa3rUGUb1Q6Q==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: ^5.7.3 + + '@typescript-eslint/scope-manager@8.19.0': + resolution: {integrity: sha512-hkoJiKQS3GQ13TSMEiuNmSCvhz7ujyqD1x3ShbaETATHrck+9RaDdUbt+osXaUuns9OFwrDTTrjtwsU8gJyyRA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/scope-manager@8.24.1': + resolution: {integrity: sha512-OdQr6BNBzwRjNEXMQyaGyZzgg7wzjYKfX2ZBV3E04hUCBDv3GQCHiz9RpqdUIiVrMgJGkXm3tcEh4vFSHreS2Q==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/scope-manager@8.35.1': + resolution: {integrity: sha512-s/Bpd4i7ht2934nG+UoSPlYXd08KYz3bmjLEb7Ye1UVob0d1ENiT3lY8bsCmik4RqfSbPw9xJJHbugpPpP5JUg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/tsconfig-utils@8.35.1': + resolution: {integrity: sha512-K5/U9VmT9dTHoNowWZpz+/TObS3xqC5h0xAIjXPw+MNcKV9qg6eSatEnmeAwkjHijhACH0/N7bkhKvbt1+DXWQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: ^5.7.3 + + '@typescript-eslint/type-utils@8.24.1': + resolution: {integrity: sha512-/Do9fmNgCsQ+K4rCz0STI7lYB4phTtEXqqCAs3gZW0pnK7lWNkvWd5iW545GSmApm4AzmQXmSqXPO565B4WVrw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: ^5.7.3 + + '@typescript-eslint/types@8.19.0': + resolution: {integrity: sha512-8XQ4Ss7G9WX8oaYvD4OOLCjIQYgRQxO+qCiR2V2s2GxI9AUpo7riNwo6jDhKtTcaJjT8PY54j2Yb33kWtSJsmA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/types@8.24.1': + resolution: {integrity: sha512-9kqJ+2DkUXiuhoiYIUvIYjGcwle8pcPpdlfkemGvTObzgmYfJ5d0Qm6jwb4NBXP9W1I5tss0VIAnWFumz3mC5A==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/types@8.35.1': + resolution: {integrity: sha512-q/O04vVnKHfrrhNAscndAn1tuQhIkwqnaW+eu5waD5IPts2eX1dgJxgqcPx5BX109/qAz7IG6VrEPTOYKCNfRQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/typescript-estree@8.24.1': + resolution: {integrity: sha512-UPyy4MJ/0RE648DSKQe9g0VDSehPINiejjA6ElqnFaFIhI6ZEiZAkUI0D5MCk0bQcTf/LVqZStvQ6K4lPn/BRg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: ^5.7.3 + + '@typescript-eslint/typescript-estree@8.35.1': + resolution: {integrity: sha512-Vvpuvj4tBxIka7cPs6Y1uvM7gJgdF5Uu9F+mBJBPY4MhvjrjWGK4H0lVgLJd/8PWZ23FTqsaJaLEkBCFUk8Y9g==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: ^5.7.3 + + '@typescript-eslint/utils@8.24.1': + resolution: {integrity: sha512-OOcg3PMMQx9EXspId5iktsI3eMaXVwlhC8BvNnX6B5w9a4dVgpkQZuU8Hy67TolKcl+iFWq0XX+jbDGN4xWxjQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: ^5.7.3 + + '@typescript-eslint/utils@8.35.1': + resolution: {integrity: sha512-lhnwatFmOFcazAsUm3ZnZFpXSxiwoa1Lj50HphnDe1Et01NF4+hrdXONSUHIcbVu2eFb1bAf+5yjXkGVkXBKAQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: ^5.7.3 + + '@typescript-eslint/visitor-keys@8.19.0': + resolution: {integrity: sha512-mCFtBbFBJDCNCWUl5y6sZSCHXw1DEFEk3c/M3nRK2a4XUB8StGFtmcEMizdjKuBzB6e/smJAAWYug3VrdLMr1w==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/visitor-keys@8.24.1': + resolution: {integrity: sha512-EwVHlp5l+2vp8CoqJm9KikPZgi3gbdZAtabKT9KPShGeOcJhsv4Zdo3oc8T8I0uKEmYoU4ItyxbptjF08enaxg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/visitor-keys@8.35.1': + resolution: {integrity: sha512-VRwixir4zBWCSTP/ljEo091lbpypz57PoeAQ9imjG+vbeof9LplljsL1mos4ccG6H9IjfrVGM359RozUnuFhpw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@vitest/expect@3.0.6': + resolution: {integrity: sha512-zBduHf/ja7/QRX4HdP1DSq5XrPgdN+jzLOwaTq/0qZjYfgETNFCKf9nOAp2j3hmom3oTbczuUzrzg9Hafh7hNg==} + + '@vitest/mocker@3.0.6': + resolution: {integrity: sha512-KPztr4/tn7qDGZfqlSPQoF2VgJcKxnDNhmfR3VgZ6Fy1bO8T9Fc1stUiTXtqz0yG24VpD00pZP5f8EOFknjNuQ==} + peerDependencies: + msw: ^2.4.9 + vite: ^5.0.0 || ^6.0.0 + peerDependenciesMeta: + msw: + optional: true + vite: + optional: true + + '@vitest/pretty-format@3.0.6': + resolution: {integrity: sha512-Zyctv3dbNL+67qtHfRnUE/k8qxduOamRfAL1BurEIQSyOEFffoMvx2pnDSSbKAAVxY0Ej2J/GH2dQKI0W2JyVg==} + + '@vitest/runner@3.0.6': + resolution: {integrity: sha512-JopP4m/jGoaG1+CBqubV/5VMbi7L+NQCJTu1J1Pf6YaUbk7bZtaq5CX7p+8sY64Sjn1UQ1XJparHfcvTTdu9cA==} + + '@vitest/snapshot@3.0.6': + resolution: {integrity: sha512-qKSmxNQwT60kNwwJHMVwavvZsMGXWmngD023OHSgn873pV0lylK7dwBTfYP7e4URy5NiBCHHiQGA9DHkYkqRqg==} + + '@vitest/spy@3.0.6': + resolution: {integrity: sha512-HfOGx/bXtjy24fDlTOpgiAEJbRfFxoX3zIGagCqACkFKKZ/TTOE6gYMKXlqecvxEndKFuNHcHqP081ggZ2yM0Q==} + + '@vitest/utils@3.0.6': + resolution: {integrity: sha512-18ktZpf4GQFTbf9jK543uspU03Q2qya7ZGya5yiZ0Gx0nnnalBvd5ZBislbl2EhLjM8A8rt4OilqKG7QwcGkvQ==} + + '@xmldom/xmldom@0.8.10': + resolution: {integrity: sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==} + engines: {node: '>=10.0.0'} + + '@zkochan/which@2.0.3': + resolution: {integrity: sha512-C1ReN7vt2/2O0fyTsx5xnbQuxBrmG5NMSbcIkPKCCfCTJgpZBsuRYzFXHj3nVq8vTfK7vxHUmzfCpSHgO7j4rg==} + engines: {node: '>= 8'} + hasBin: true + + accepts@1.3.8: + resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} + engines: {node: '>= 0.6'} + + acorn-jsx@5.3.2: + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + + acorn-walk@8.3.4: + resolution: {integrity: sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==} + engines: {node: '>=0.4.0'} + + acorn@8.14.0: + resolution: {integrity: sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==} + engines: {node: '>=0.4.0'} + hasBin: true + + acorn@8.15.0: + resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==} + engines: {node: '>=0.4.0'} + hasBin: true + + agent-base@6.0.2: + resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} + engines: {node: '>= 6.0.0'} + + agent-base@7.1.3: + resolution: {integrity: sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==} + engines: {node: '>= 14'} + + agentkeepalive@4.6.0: + resolution: {integrity: sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==} + engines: {node: '>= 8.0.0'} + + aggregate-error@3.1.0: + resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} + engines: {node: '>=8'} + + ajv@6.12.6: + resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + + ajv@8.17.1: + resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==} + + amd-name-resolver@1.3.1: + resolution: {integrity: sha512-26qTEWqZQ+cxSYygZ4Cf8tsjDBLceJahhtewxtKZA3SRa4PluuqYCuheemDQD+7Mf5B7sr+zhTDWAHDh02a1Dw==} + engines: {node: 6.* || 8.* || >= 10.*} + + ansi-align@3.0.1: + resolution: {integrity: sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==} + + ansi-colors@4.1.1: + resolution: {integrity: sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==} + engines: {node: '>=6'} + + ansi-diff@1.2.0: + resolution: {integrity: sha512-BIXwHKpjzghBjcwEV10Y4b17tjHfK4nhEqK3LqyQ3JgcMcjmi3DIevozNgrOpfvBMmrq9dfvrPJSu5/5vNUBQg==} + + ansi-escapes@3.2.0: + resolution: {integrity: sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==} + engines: {node: '>=4'} + + ansi-escapes@4.3.2: + resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} + engines: {node: '>=8'} + + ansi-escapes@5.0.0: + resolution: {integrity: sha512-5GFMVX8HqE/TB+FuBJGuO5XG0WrsA6ptUqoODaT/n9mmUaZFkqnBueB4leqGBCmrUHnCnC4PCZTCd0E7QQ83bA==} + engines: {node: '>=12'} + + ansi-regex@2.1.1: + resolution: {integrity: sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==} + engines: {node: '>=0.10.0'} + + ansi-regex@3.0.1: + resolution: {integrity: sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==} + engines: {node: '>=4'} + + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + ansi-regex@6.1.0: + resolution: {integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==} + engines: {node: '>=12'} + + ansi-split@1.0.1: + resolution: {integrity: sha512-RRxQym4DFtDNmHIkW6aeFVvrXURb11lGAEPXNiryjCe8bK8RsANjzJ0M2aGOkvBYwP4Bl/xZ8ijtr6D3j1x/eg==} + + ansi-styles@2.2.1: + resolution: {integrity: sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==} + engines: {node: '>=0.10.0'} + + ansi-styles@3.2.1: + resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} + engines: {node: '>=4'} + + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + + ansi-styles@6.2.1: + resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} + engines: {node: '>=12'} + + ansicolors@0.3.2: + resolution: {integrity: sha512-QXu7BPrP29VllRxH8GwB7x5iX5qWKAAMLqKQGWTeLWVlNHNOpVMJ91dsxQAIWXpjuW5wqvxu3Jd/nRjrJ+0pqg==} + + ansis@3.17.0: + resolution: {integrity: sha512-0qWUglt9JEqLFr3w1I1pbrChn1grhaiAR2ocX1PP/flRmxgtwTzPFFFnfIlD6aMOLQZgSuCRlidD70lvx8yhzg==} + engines: {node: '>=14'} + + ansis@4.1.0: + resolution: {integrity: sha512-BGcItUBWSMRgOCe+SVZJ+S7yTRG0eGt9cXAHev72yuGcY23hnLA7Bky5L/xLyPINoSN95geovfBkqoTlNZYa7w==} + engines: {node: '>=14'} + + any-observable@0.3.0: + resolution: {integrity: sha512-/FQM1EDkTsf63Ub2C6O7GuYFDsSXUwsaZDurV0np41ocwq0jthUAYCmhBX9f+KwlaCgIuWyr/4WlUQUBfKfZog==} + engines: {node: '>=6'} + peerDependencies: + rxjs: '*' + zenObservable: '*' + peerDependenciesMeta: + rxjs: + optional: true + zenObservable: + optional: true + + any-promise@1.3.0: + resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} + + aproba@2.0.0: + resolution: {integrity: sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==} + + archiver-utils@2.1.0: + resolution: {integrity: sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==} + engines: {node: '>= 6'} + + archiver-utils@3.0.4: + resolution: {integrity: sha512-KVgf4XQVrTjhyWmx6cte4RxonPLR9onExufI1jhvw/MQ4BB6IsZD5gT8Lq+u/+pRkWna/6JoHpiQioaqFP5Rzw==} + engines: {node: '>= 10'} + + archiver@5.3.2: + resolution: {integrity: sha512-+25nxyyznAXF7Nef3y0EbBeqmGZgeN/BxHX29Rs39djAfaFalmQ89SE6CWyDCHzGL0yt/ycBtNOmGTW0FyGWNw==} + engines: {node: '>= 10'} + + archy@1.0.0: + resolution: {integrity: sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw==} + + are-we-there-yet@3.0.1: + resolution: {integrity: sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + deprecated: This package is no longer supported. + + arg@4.1.3: + resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} + + argparse@1.0.10: + resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} + + argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + + array-binsearch@1.0.1: + resolution: {integrity: sha512-KZw1m6nCIGsjuUHnY2e1mOZPxH7widuwutZChvgoXwe8+ZCKM7GiIBtgBMNiUKBycPoh6tLOnJBQApjm3wMelw==} + + array-buffer-byte-length@1.0.2: + resolution: {integrity: sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==} + engines: {node: '>= 0.4'} + + array-flatten@1.1.1: + resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} + + array-includes@3.1.8: + resolution: {integrity: sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==} + engines: {node: '>= 0.4'} + + array-union@2.1.0: + resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} + engines: {node: '>=8'} + + array.prototype.findlastindex@1.2.5: + resolution: {integrity: sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==} + engines: {node: '>= 0.4'} + + array.prototype.flat@1.3.3: + resolution: {integrity: sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==} + engines: {node: '>= 0.4'} + + array.prototype.flatmap@1.3.3: + resolution: {integrity: sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==} + engines: {node: '>= 0.4'} + + arraybuffer.prototype.slice@1.0.4: + resolution: {integrity: sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==} + engines: {node: '>= 0.4'} + + arrify@1.0.1: + resolution: {integrity: sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==} + engines: {node: '>=0.10.0'} + + as-table@1.0.55: + resolution: {integrity: sha512-xvsWESUJn0JN421Xb9MQw6AsMHRCUknCe0Wjlxvjud80mU4E6hQf1A6NzQKcYNmYw62MfzEtXc+badstZP3JpQ==} + + assert-never@1.4.0: + resolution: {integrity: sha512-5oJg84os6NMQNl27T9LnZkvvqzvAnHu03ShCnoj6bsJwS7L8AO4lf+C/XjK/nvzEqQB744moC6V128RucQd1jA==} + + assertion-error@2.0.1: + resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} + engines: {node: '>=12'} + + ast-types@0.13.4: + resolution: {integrity: sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==} + engines: {node: '>=4'} + + astral-regex@2.0.0: + resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==} + engines: {node: '>=8'} + + async@0.2.10: + resolution: {integrity: sha512-eAkdoKxU6/LkKDBzLpT+t6Ff5EtfSF4wx1WfJiPEEV7WNLnDaRXk0oVysiEPm262roaachGexwUv94WhSgN5TQ==} + + async@3.2.6: + resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==} + + at-least-node@1.0.0: + resolution: {integrity: sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==} + engines: {node: '>= 4.0.0'} + + auto-dist-tag@2.1.1: + resolution: {integrity: sha512-w3aUbxMesY8VpJCW26F8enOvJnegb4fDtjDttc1UpBVEzRidEmMHzVI9J9cbeTh92vDfoxVeQezJbnqtAz20iw==} + engines: {node: '>=10'} + hasBin: true + + available-typed-arrays@1.0.7: + resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} + engines: {node: '>= 0.4'} + + b4a@1.6.7: + resolution: {integrity: sha512-OnAYlL5b7LEkALw87fUVafQw5rVR9RjwGd4KUwNQ6DrrNmaVaUCgLipfVlzrPQ4tWOR9P0IXGNOx50jYCCdSJg==} + + babel-plugin-debug-macros@0.3.4: + resolution: {integrity: sha512-wfel/vb3pXfwIDZUrkoDrn5FHmlWI96PCJ3UCDv2a86poJ3EQrnArNW5KfHSVJ9IOgxHbo748cQt7sDU+0KCEw==} + engines: {node: '>=6'} + peerDependencies: + '@babel/core': ^7.0.0 + + babel-plugin-macros@3.1.0: + resolution: {integrity: sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==} + engines: {node: '>=10', npm: '>=6'} + + babel-plugin-polyfill-corejs2@0.4.14: + resolution: {integrity: sha512-Co2Y9wX854ts6U8gAAPXfn0GmAyctHuK8n0Yhfjd6t30g7yvKjspvvOo9yG+z52PZRgFErt7Ka2pYnXCjLKEpg==} + peerDependencies: + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + + babel-plugin-polyfill-corejs3@0.13.0: + resolution: {integrity: sha512-U+GNwMdSFgzVmfhNm8GJUX88AadB3uo9KpJqS3FaqNIPKgySuvMb+bHPsOmmuWyIcuqZj/pzt1RUIUZns4y2+A==} + peerDependencies: + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + + babel-plugin-polyfill-regenerator@0.6.5: + resolution: {integrity: sha512-ISqQ2frbiNU9vIJkzg7dlPpznPZ4jOiUQ1uSmB0fEHeowtN3COYRsXr/xexn64NpU13P06jc/L5TgiJXOgrbEg==} + peerDependencies: + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + + babel-plugin-preval@5.1.0: + resolution: {integrity: sha512-G5R+xmo5LS41A4UyZjOjV0mp9AvkuCyUOAJ6TOv/jTZS+VKh7L7HUDRcCSOb0YCM/u0fFarh7Diz0wjY8rFNFg==} + engines: {node: '>=10', npm: '>=6'} + + babel-plugin-strip-glimmer-utils@0.1.1: + resolution: {integrity: sha512-swQqYIjUQQppAEnaRH2Kuo6N6zIw6uEAPbELvmFgmzwJPt0vqe5wHESPqBk/OepsWfGkv9KQILNd5BKRIDuDtA==} + + babel-plugin-tester@11.0.4: + resolution: {integrity: sha512-cqswtpSPo0e++rZB0l/54EG17LL25l9gLgh59yXfnmNxX+2lZTIOpx2zt4YI9QIClVXc8xf63J6yWwKkzy0jNg==} + engines: {node: ^14.20.0 || ^16.16.0 || >=18.5.0} + peerDependencies: + '@babel/core': '>=7.11.6' + + backbone@1.6.0: + resolution: {integrity: sha512-13PUjmsgw/49EowNcQvfG4gmczz1ximTMhUktj0Jfrjth0MVaTxehpU+qYYX4MxnuIuhmvBLC6/ayxuAGnOhbA==} + + balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + bare-events@2.5.4: + resolution: {integrity: sha512-+gFfDkR8pj4/TrWCGUGWmJIkBwuxPS5F+a5yWjOHQt2hHvNZd5YLzadjmDUtFmMM4y429bnKLa8bYBMHcYdnQA==} + + bare-fs@4.1.5: + resolution: {integrity: sha512-1zccWBMypln0jEE05LzZt+V/8y8AQsQQqxtklqaIyg5nu6OAYFhZxPXinJTSG+kU5qyNmeLgcn9AW7eHiCHVLA==} + engines: {bare: '>=1.16.0'} + peerDependencies: + bare-buffer: '*' + peerDependenciesMeta: + bare-buffer: + optional: true + + bare-os@3.6.1: + resolution: {integrity: sha512-uaIjxokhFidJP+bmmvKSgiMzj2sV5GPHaZVAIktcxcpCyBFFWO+YlikVAdhmUo2vYFvFhOXIAlldqV29L8126g==} + engines: {bare: '>=1.14.0'} + + bare-path@3.0.0: + resolution: {integrity: sha512-tyfW2cQcB5NN8Saijrhqn0Zh7AnFNsnczRcuWODH0eYAXBsJ5gVxAUuNr7tsHSC6IZ77cA0SitzT+s47kot8Mw==} + + bare-stream@2.6.5: + resolution: {integrity: sha512-jSmxKJNJmHySi6hC42zlZnq00rga4jjxcgNZjY9N5WlOe/iOoGRtdwGsHzQv2RlH2KOYMwGUXhf2zXd32BA9RA==} + peerDependencies: + bare-buffer: '*' + bare-events: '*' + peerDependenciesMeta: + bare-buffer: + optional: true + bare-events: + optional: true + + base64-js@1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + + base64id@2.0.0: + resolution: {integrity: sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==} + engines: {node: ^4.5.0 || >= 5.9} + + basic-ftp@5.0.5: + resolution: {integrity: sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg==} + engines: {node: '>=10.0.0'} + + before-after-hook@3.0.2: + resolution: {integrity: sha512-Nik3Sc0ncrMK4UUdXQmAnRtzmNQTAAXmXIopizwZ1W1t8QmfJj+zL4OA2I7XPTPW5z5TDqv4hRo/JzouDJnX3A==} + + better-path-resolve@1.0.0: + resolution: {integrity: sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g==} + engines: {node: '>=4'} + + bl@4.1.0: + resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} + + bluebird@3.7.2: + resolution: {integrity: sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==} + + body-parser@1.20.3: + resolution: {integrity: sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + + bole@5.0.19: + resolution: {integrity: sha512-OgMuI8erST2t4K/Y+tSsn4SOxlKj4JR2wluQgLYadQFPIhj0r3jcmnp0OthgiyNO91CnxR8woKeLQmnMPgl1Ug==} + + boolbase@1.0.0: + resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} + + boxen@5.1.2: + resolution: {integrity: sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==} + engines: {node: '>=10'} + + boxen@8.0.1: + resolution: {integrity: sha512-F3PH5k5juxom4xktynS7MoFY+NUWH5LC4CnH11YB8NPew+HLpmBLCybSAEyb2F+4pRXhuhWqFesoQd6DAyc2hw==} + engines: {node: '>=18'} + + brace-expansion@1.1.12: + resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==} + + brace-expansion@2.0.2: + resolution: {integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==} + + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} + engines: {node: '>=8'} + + browser-stdout@1.3.1: + resolution: {integrity: sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==} + + browserslist@4.25.1: + resolution: {integrity: sha512-KGj0KoOMXLpSNkkEI6Z6mShmQy0bc1I+T7K9N81k4WWMrfz+6fQ6es80B/YLAeRoKvjYE1YSHHOW1qe9xIVzHw==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + + buffer-crc32@0.2.13: + resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} + + buffer-from@1.1.2: + resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + + buffer@5.7.1: + resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} + + builtins@5.1.0: + resolution: {integrity: sha512-SW9lzGTLvWTP1AY8xeAMZimqDrIaSdLQUcVr9DMef51niJ022Ri87SwRRKYm4A6iHfkPaiVUu/Duw2Wc4J7kKg==} + + bundle-name@4.1.0: + resolution: {integrity: sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==} + engines: {node: '>=18'} + + bundle-require@5.1.0: + resolution: {integrity: sha512-3WrrOuZiyaaZPWiEt4G3+IffISVC9HYlWueJEBWED4ZH4aIAC2PnkdnuRrR94M+w6yGWn4AglWtJtBI8YqvgoA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + peerDependencies: + esbuild: ^0.25.0 + + bytes@3.1.2: + resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} + engines: {node: '>= 0.8'} + + cac@6.7.14: + resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} + engines: {node: '>=8'} + + cacache@15.3.0: + resolution: {integrity: sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==} + engines: {node: '>= 10'} + + cacheable-lookup@5.0.4: + resolution: {integrity: sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==} + engines: {node: '>=10.6.0'} + + cacheable-request@7.0.4: + resolution: {integrity: sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==} + engines: {node: '>=8'} + + call-bind-apply-helpers@1.0.1: + resolution: {integrity: sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==} + engines: {node: '>= 0.4'} + + call-bind@1.0.8: + resolution: {integrity: sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==} + engines: {node: '>= 0.4'} + + call-bound@1.0.3: + resolution: {integrity: sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==} + engines: {node: '>= 0.4'} + + callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + + camel-case@4.1.2: + resolution: {integrity: sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==} + + camelcase-keys@6.2.2: + resolution: {integrity: sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==} + engines: {node: '>=8'} + + camelcase@5.3.1: + resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} + engines: {node: '>=6'} + + camelcase@6.3.0: + resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} + engines: {node: '>=10'} + + camelcase@8.0.0: + resolution: {integrity: sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA==} + engines: {node: '>=16'} + + can-write-to-dir@1.1.1: + resolution: {integrity: sha512-eOgiEWqjppB+3DN/5E82EQ8dTINus8d9GXMCbEsUnp2hcUIcXmBvzWmD3tXMk3CuBK0v+ddK9qw0EAF+JVRMjQ==} + engines: {node: '>=10.13'} + + caniuse-api@3.0.0: + resolution: {integrity: sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==} + + caniuse-lite@1.0.30001690: + resolution: {integrity: sha512-5ExiE3qQN6oF8Clf8ifIDcMRCRE/dMGcETG/XGMD8/XiXm6HXQgQTh1yZYLXXpSOsEUlJm1Xr7kGULZTuGtP/w==} + + caniuse-lite@1.0.30001726: + resolution: {integrity: sha512-VQAUIUzBiZ/UnlM28fSp2CRF3ivUn1BWEvxMcVTNwpw91Py1pGbPIyIKtd+tzct9C3ouceCVdGAXxZOpZAsgdw==} + + cardinal@2.1.1: + resolution: {integrity: sha512-JSr5eOgoEymtYHBjNWyjrMqet9Am2miJhlfKNdqLp6zoeAh0KN5dRAcxlecj5mAJrmQomgiOBj35xHLrFjqBpw==} + hasBin: true + + chai@5.2.0: + resolution: {integrity: sha512-mCuXncKXk5iCLhfhwTc0izo0gtEmpz5CtG2y8GiOINBlMVS6v8TMRc5TaLWKS6692m9+dVVfzgeVxR5UxWHTYw==} + engines: {node: '>=12'} + + chalk@1.1.3: + resolution: {integrity: sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==} + engines: {node: '>=0.10.0'} + + chalk@2.4.2: + resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} + engines: {node: '>=4'} + + chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + + chalk@5.4.1: + resolution: {integrity: sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==} + engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + + char-regex@1.0.2: + resolution: {integrity: sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==} + engines: {node: '>=10'} + + charm@1.0.2: + resolution: {integrity: sha512-wqW3VdPnlSWT4eRiYX+hcs+C6ViBPUWk1qTCd+37qw9kEm/a5n2qcyQDMBWvSYKN/ctqZzeXNQaeBjOetJJUkw==} + + check-error@2.1.1: + resolution: {integrity: sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==} + engines: {node: '>= 16'} + + chokidar@4.0.3: + resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==} + engines: {node: '>= 14.16.0'} + + chownr@2.0.0: + resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} + engines: {node: '>=10'} + + chrome-debugging-client@2.0.0: + resolution: {integrity: sha512-aWC72vm+kFS1lefdrLc/9pg8wL0mgNmri6cN6A/UaASH1S2mpUT6RrvgX654sitsefM07RDRTILTev9I2j+AuQ==} + peerDependencies: + devtools-protocol: '*' + + chrome-launcher@0.13.4: + resolution: {integrity: sha512-nnzXiDbGKjDSK6t2I+35OAPBy5Pw/39bgkb/ZAFwMhwJbdYBp6aH+vW28ZgtjdU890Q7D+3wN/tB8N66q5Gi2A==} + + chromium-bidi@0.11.0: + resolution: {integrity: sha512-6CJWHkNRoyZyjV9Rwv2lYONZf1Xm0IuDyNq97nwSsxxP3wf5Bwy15K5rOvVKMtJ127jJBmxFUanSAOjgFRxgrA==} + peerDependencies: + devtools-protocol: '*' + + chromium-bidi@5.1.0: + resolution: {integrity: sha512-9MSRhWRVoRPDG0TgzkHrshFSJJNZzfY5UFqUMuksg7zL1yoZIZ3jLB0YAgHclbiAxPI86pBnwDX1tbzoiV8aFw==} + peerDependencies: + devtools-protocol: '*' + + clean-css@5.3.3: + resolution: {integrity: sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==} + engines: {node: '>= 10.0'} + + clean-stack@2.2.0: + resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==} + engines: {node: '>=6'} + + clean-stack@3.0.1: + resolution: {integrity: sha512-lR9wNiMRcVQjSB3a7xXGLuz4cr4wJuuXlaAEbRutGowQTmlp7R72/DOgN21e8jdwblMWl9UOJMJXarX94pzKdg==} + engines: {node: '>=10'} + + cli-boxes@2.2.1: + resolution: {integrity: sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==} + engines: {node: '>=6'} + + cli-boxes@3.0.0: + resolution: {integrity: sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==} + engines: {node: '>=10'} + + cli-columns@4.0.0: + resolution: {integrity: sha512-XW2Vg+w+L9on9wtwKpyzluIPCWXjaBahI7mTcYjx+BVIYD9c3yqcv/yKC7CmdCZat4rq2yiE1UMSJC5ivKfMtQ==} + engines: {node: '>= 10'} + + cli-cursor@2.1.0: + resolution: {integrity: sha512-8lgKz8LmCRYZZQDpRyT2m5rKJ08TnU4tR9FFFW2rxpxR1FzWi4PQ/NfyODchAatHaUgnSPVcx/R5w6NuTBzFiw==} + engines: {node: '>=4'} + + cli-cursor@5.0.0: + resolution: {integrity: sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==} + engines: {node: '>=18'} + + cli-highlight@2.1.11: + resolution: {integrity: sha512-9KDcoEVwyUXrjcJNvHD0NFc/hiwe/WPVYIleQh2O1N2Zro5gWJZ/K+3DGn8w8P/F6FxOgzyC5bxDyHIgCSPhGg==} + engines: {node: '>=8.0.0', npm: '>=5.0.0'} + hasBin: true + + cli-progress@3.12.0: + resolution: {integrity: sha512-tRkV3HJ1ASwm19THiiLIXLO7Im7wlTuKnvkYaTkyoAPefqjNg7W7DHKUlGRxy9vxDvbyCYQkQozvptuMkGCg8A==} + engines: {node: '>=4'} + + cli-spinners@2.9.2: + resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==} + engines: {node: '>=6'} + + cli-table3@0.6.5: + resolution: {integrity: sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==} + engines: {node: 10.* || >= 12.*} + + cli-truncate@0.2.1: + resolution: {integrity: sha512-f4r4yJnbT++qUPI9NR4XLDLq41gQ+uqnPItWG0F5ZkehuNiTTa3EY0S4AqTSUOeJ7/zU41oWPQSNkW5BqPL9bg==} + engines: {node: '>=0.10.0'} + + cli-truncate@2.1.0: + resolution: {integrity: sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==} + engines: {node: '>=8'} + + cliui@7.0.4: + resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==} + + cliui@8.0.1: + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} + engines: {node: '>=12'} + + clone-response@1.0.3: + resolution: {integrity: sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==} + + clone@1.0.4: + resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} + engines: {node: '>=0.8'} + + code-point-at@1.1.0: + resolution: {integrity: sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==} + engines: {node: '>=0.10.0'} + + color-convert@1.9.3: + resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} + + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-name@1.1.3: + resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + color-support@1.1.3: + resolution: {integrity: sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==} + hasBin: true + + colord@2.9.3: + resolution: {integrity: sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==} + + comlink@4.4.2: + resolution: {integrity: sha512-OxGdvBmJuNKSCMO4NTl1L47VRp6xn2wG4F/2hYzB6tiCb709otOxtEYCSvK80PtjODfXXZu8ds+Nw5kVCjqd2g==} + + commander@10.0.1: + resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==} + engines: {node: '>=14'} + + commander@2.20.3: + resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} + + commander@4.1.1: + resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} + engines: {node: '>= 6'} + + commander@7.2.0: + resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==} + engines: {node: '>= 10'} + + comment-parser@1.4.1: + resolution: {integrity: sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg==} + engines: {node: '>= 12.0.0'} + + common-path-prefix@3.0.0: + resolution: {integrity: sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==} + + commondir@1.0.1: + resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==} + + compress-commons@4.1.2: + resolution: {integrity: sha512-D3uMHtGc/fcO1Gt1/L7i1e33VOvD4A9hfQLP+6ewd+BvG/gQ84Yh4oftEhAdjSMgBgwGL+jsppT7JYNpo6MHHg==} + engines: {node: '>= 10'} + + compressible@2.0.18: + resolution: {integrity: sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==} + engines: {node: '>= 0.6'} + + compression@1.7.5: + resolution: {integrity: sha512-bQJ0YRck5ak3LgtnpKkiabX5pNF7tMUh1BSy2ZBOTh0Dim0BUu6aPPwByIns6/A5Prh8PufSPerMDUklpzes2Q==} + engines: {node: '>= 0.8.0'} + + concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + + concat-with-sourcemaps@1.1.0: + resolution: {integrity: sha512-4gEjHJFT9e+2W/77h/DS5SGUgwDaOwprX8L/gl5+3ixnzkVJJsZWDSelmN3Oilw3LNDZjZV0yqH1hLG3k6nghg==} + + confbox@0.1.8: + resolution: {integrity: sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==} + + config-chain@1.1.13: + resolution: {integrity: sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==} + + console-control-strings@1.1.0: + resolution: {integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==} + + consolidate@0.16.0: + resolution: {integrity: sha512-Nhl1wzCslqXYTJVDyJCu3ODohy9OfBMB5uD2BiBTzd7w+QY0lBzafkR8y8755yMYHAaMD4NuzbAw03/xzfw+eQ==} + engines: {node: '>= 0.10.0'} + deprecated: Please upgrade to consolidate v1.0.0+ as it has been modernized with several long-awaited fixes implemented. Maintenance is supported by Forward Email at https://forwardemail.net ; follow/watch https://github.com/ladjs/consolidate for updates and release changelog + peerDependencies: + arc-templates: ^0.5.3 + atpl: '>=0.7.6' + babel-core: ^6.26.3 + bracket-template: ^1.1.5 + coffee-script: ^1.12.7 + dot: ^1.1.3 + dust: ^0.3.0 + dustjs-helpers: ^1.7.4 + dustjs-linkedin: ^2.7.5 + eco: ^1.1.0-rc-3 + ect: ^0.5.9 + ejs: ^3.1.5 + haml-coffee: ^1.14.1 + hamlet: ^0.3.3 + hamljs: ^0.6.2 + handlebars: ^4.7.6 + hogan.js: ^3.0.2 + htmling: ^0.0.8 + jade: ^1.11.0 + jazz: ^0.0.18 + jqtpl: ~1.1.0 + just: ^0.1.8 + liquid-node: ^3.0.1 + liquor: ^0.0.5 + lodash: ^4.17.20 + marko: ^3.14.4 + mote: ^0.2.0 + mustache: ^4.0.1 + nunjucks: ^3.2.2 + plates: ~0.4.11 + pug: ^3.0.0 + qejs: ^3.0.5 + ractive: ^1.3.12 + razor-tmpl: ^1.3.1 + react: ^16.13.1 + react-dom: ^16.13.1 + slm: ^2.0.0 + squirrelly: ^5.1.0 + swig: ^1.4.2 + swig-templates: ^2.0.3 + teacup: ^2.0.0 + templayed: '>=0.2.3' + then-jade: '*' + then-pug: '*' + tinyliquid: ^0.2.34 + toffee: ^0.3.6 + twig: ^1.15.2 + twing: ^5.0.2 + underscore: ^1.11.0 + vash: ^0.13.0 + velocityjs: ^2.0.1 + walrus: ^0.10.1 + whiskers: ^0.4.0 + peerDependenciesMeta: + arc-templates: + optional: true + atpl: + optional: true + babel-core: + optional: true + bracket-template: + optional: true + coffee-script: + optional: true + dot: + optional: true + dust: + optional: true + dustjs-helpers: + optional: true + dustjs-linkedin: + optional: true + eco: + optional: true + ect: + optional: true + ejs: + optional: true + haml-coffee: + optional: true + hamlet: + optional: true + hamljs: + optional: true + handlebars: + optional: true + hogan.js: + optional: true + htmling: + optional: true + jade: + optional: true + jazz: + optional: true + jqtpl: + optional: true + just: + optional: true + liquid-node: + optional: true + liquor: + optional: true + lodash: + optional: true + marko: + optional: true + mote: + optional: true + mustache: + optional: true + nunjucks: + optional: true + plates: + optional: true + pug: + optional: true + qejs: + optional: true + ractive: + optional: true + razor-tmpl: + optional: true + react: + optional: true + react-dom: + optional: true + slm: + optional: true + squirrelly: + optional: true + swig: + optional: true + swig-templates: + optional: true + teacup: + optional: true + templayed: + optional: true + then-jade: + optional: true + then-pug: + optional: true + tinyliquid: + optional: true + toffee: + optional: true + twig: + optional: true + twing: + optional: true + underscore: + optional: true + vash: + optional: true + velocityjs: + optional: true + walrus: + optional: true + whiskers: + optional: true + + content-disposition@0.5.4: + resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} + engines: {node: '>= 0.6'} + + content-type@1.0.5: + resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} + engines: {node: '>= 0.6'} + + convert-source-map@2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + + cookie-es@1.2.2: + resolution: {integrity: sha512-+W7VmiVINB+ywl1HGXJXmrqkOhpKrIiVZV6tQuV54ZyQC7MMuBt81Vc336GMLoHBq5hV/F9eXgt5Mnx0Rha5Fg==} + + cookie-signature@1.0.6: + resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==} + + cookie@0.7.1: + resolution: {integrity: sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==} + engines: {node: '>= 0.6'} + + cookie@0.7.2: + resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==} + engines: {node: '>= 0.6'} + + core-js-compat@3.43.0: + resolution: {integrity: sha512-2GML2ZsCc5LR7hZYz4AXmjQw8zuy2T//2QntwdnpuYI7jteT6GVYJL7F6C2C57R7gSYrcqVW3lAALefdbhBLDA==} + + core-js@3.39.0: + resolution: {integrity: sha512-raM0ew0/jJUqkJ0E6e8UDtl+y/7ktFivgWvqw8dNSQeNWoSDLvQ1H/RN3aPXB9tBd4/FhyR4RDPGhsNIMsAn7g==} + + core-util-is@1.0.3: + resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} + + cors@2.8.5: + resolution: {integrity: sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==} + engines: {node: '>= 0.10'} + + cosmiconfig@7.1.0: + resolution: {integrity: sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==} + engines: {node: '>=10'} + + cosmiconfig@9.0.0: + resolution: {integrity: sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==} + engines: {node: '>=14'} + peerDependencies: + typescript: ^5.7.3 + peerDependenciesMeta: + typescript: + optional: true + + crc-32@1.2.2: + resolution: {integrity: sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==} + engines: {node: '>=0.8'} + hasBin: true + + crc32-stream@4.0.3: + resolution: {integrity: sha512-NT7w2JVU7DFroFdYkeq8cywxrgjPHWkdX1wjpRQXPX5Asews3tA+Ght6lddQO5Mkumffp3X7GEqku3epj2toIw==} + engines: {node: '>= 10'} + + create-require@1.1.1: + resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} + + cross-spawn@6.0.6: + resolution: {integrity: sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw==} + engines: {node: '>=4.8'} + + cross-spawn@7.0.6: + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} + engines: {node: '>= 8'} + + crossws@0.3.5: + resolution: {integrity: sha512-ojKiDvcmByhwa8YYqbQI/hg7MEU0NC03+pSdEq4ZUnZR9xXpwk7E43SMNGkn+JxJGPFtNvQ48+vV2p+P1ml5PA==} + + crypto-random-string@2.0.0: + resolution: {integrity: sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==} + engines: {node: '>=8'} + + css-declaration-sorter@6.4.1: + resolution: {integrity: sha512-rtdthzxKuyq6IzqX6jEcIzQF/YqccluefyCYheovBOLhFT/drQA9zj/UbRAa9J7C0o6EG6u3E6g+vKkay7/k3g==} + engines: {node: ^10 || ^12 || >=14} + peerDependencies: + postcss: ^8.0.9 + + css-select@4.3.0: + resolution: {integrity: sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==} + + css-tree@1.1.3: + resolution: {integrity: sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==} + engines: {node: '>=8.0.0'} + + css-what@6.1.0: + resolution: {integrity: sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==} + engines: {node: '>= 6'} + + cssesc@3.0.0: + resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} + engines: {node: '>=4'} + hasBin: true + + cssnano-preset-default@5.2.14: + resolution: {integrity: sha512-t0SFesj/ZV2OTylqQVOrFgEh5uanxbO6ZAdeCrNsUQ6fVuXwYTxJPNAGvGTxHbD68ldIJNec7PyYZDBrfDQ+6A==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + cssnano-utils@3.1.0: + resolution: {integrity: sha512-JQNR19/YZhz4psLX/rQ9M83e3z2Wf/HdJbryzte4a3NSuafyp9w/I4U+hx5C2S9g41qlstH7DEWnZaaj83OuEA==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + cssnano@5.1.15: + resolution: {integrity: sha512-j+BKgDcLDQA+eDifLx0EO4XSA56b7uut3BQFH+wbSaSTuGLuiyTa/wbRYthUXX8LC9mLg+WWKe8h+qJuwTAbHw==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + csso@4.2.0: + resolution: {integrity: sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==} + engines: {node: '>=8.0.0'} + + d3-array@2.12.1: + resolution: {integrity: sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==} + + d3-array@3.2.4: + resolution: {integrity: sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==} + engines: {node: '>=12'} + + d3-color@3.1.0: + resolution: {integrity: sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==} + engines: {node: '>=12'} + + d3-format@2.0.0: + resolution: {integrity: sha512-Ab3S6XuE/Q+flY96HXT0jOXcM4EAClYFnRGY5zsjRGNy6qCYrQsMffs7cV5Q9xejb35zxW5hf/guKw34kvIKsA==} + + d3-hierarchy@3.1.2: + resolution: {integrity: sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==} + engines: {node: '>=12'} + + d3-interpolate@2.0.1: + resolution: {integrity: sha512-c5UhwwTs/yybcmTpAVqwSFl6vrQ8JZJoT5F7xNFK9pymv5C0Ymcc9/LIJHtYIggg/yS9YHw8i8O8tgb9pupjeQ==} + + d3-scale@3.3.0: + resolution: {integrity: sha512-1JGp44NQCt5d1g+Yy+GeOnZP7xHo0ii8zsQp6PGzd+C1/dl0KGsp9A7Mxwp+1D1o4unbTTxVdU/ZOIEBoeZPbQ==} + + d3-time-format@3.0.0: + resolution: {integrity: sha512-UXJh6EKsHBTjopVqZBhFysQcoXSv/5yLONZvkQ5Kk3qbwiUYkdX17Xa1PT6U1ZWXGGfB1ey5L8dKMlFq2DO0Ag==} + + d3-time@2.1.1: + resolution: {integrity: sha512-/eIQe/eR4kCQwq7yxi7z4c6qEXf2IYGcjoWB5OOQy4Tq9Uv39/947qlDcN2TLkiTzQWzvnsuYPB9TrWaNfipKQ==} + + dag-map@2.0.2: + resolution: {integrity: sha512-xnsprIzYuDeiyu5zSKwilV/ajRHxnoMlAhEREfyfTgTSViMVY2fGP1ZcHJbtwup26oCkofySU/m6oKJ3HrkW7w==} + + data-uri-to-buffer@2.0.2: + resolution: {integrity: sha512-ND9qDTLc6diwj+Xe5cdAgVTbLVdXbtxTJRXRhli8Mowuaan+0EJOtdqJ0QCHNSSPyoXGx9HX2/VMnKeC34AChA==} + + data-uri-to-buffer@6.0.2: + resolution: {integrity: sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==} + engines: {node: '>= 14'} + + data-view-buffer@1.0.2: + resolution: {integrity: sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==} + engines: {node: '>= 0.4'} + + data-view-byte-length@1.0.2: + resolution: {integrity: sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==} + engines: {node: '>= 0.4'} + + data-view-byte-offset@1.0.1: + resolution: {integrity: sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==} + engines: {node: '>= 0.4'} + + date-fns@1.30.1: + resolution: {integrity: sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw==} + + debug@2.6.9: + resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + debug@3.2.7: + resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + debug@4.3.7: + resolution: {integrity: sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + debug@4.4.0: + resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + debug@4.4.1: + resolution: {integrity: sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + decamelize-keys@1.1.1: + resolution: {integrity: sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==} + engines: {node: '>=0.10.0'} + + decamelize@1.2.0: + resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} + engines: {node: '>=0.10.0'} + + decamelize@4.0.0: + resolution: {integrity: sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==} + engines: {node: '>=10'} + + decompress-response@6.0.0: + resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==} + engines: {node: '>=10'} + + deep-eql@5.0.2: + resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==} + engines: {node: '>=6'} + + deep-extend@0.6.0: + resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} + engines: {node: '>=4.0.0'} + + deep-is@0.1.4: + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + + deepmerge-ts@5.1.0: + resolution: {integrity: sha512-eS8dRJOckyo9maw9Tu5O5RUi/4inFLrnoLkBe3cPfDMx3WZioXtmOew4TXQaxq7Rhl4xjDtR7c6x8nNTxOvbFw==} + engines: {node: '>=16.0.0'} + + deepmerge@4.3.1: + resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} + engines: {node: '>=0.10.0'} + + default-browser-id@5.0.0: + resolution: {integrity: sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==} + engines: {node: '>=18'} + + default-browser@5.2.1: + resolution: {integrity: sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg==} + engines: {node: '>=18'} + + defaults@1.0.4: + resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==} + + defer-to-connect@2.0.1: + resolution: {integrity: sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==} + engines: {node: '>=10'} + + define-data-property@1.1.4: + resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} + engines: {node: '>= 0.4'} + + define-lazy-prop@3.0.0: + resolution: {integrity: sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==} + engines: {node: '>=12'} + + define-properties@1.2.1: + resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} + engines: {node: '>= 0.4'} + + defu@6.1.4: + resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==} + + degenerator@5.0.1: + resolution: {integrity: sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==} + engines: {node: '>= 14'} + + delegates@1.0.0: + resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==} + + depd@2.0.0: + resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} + engines: {node: '>= 0.8'} + + destr@2.0.5: + resolution: {integrity: sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==} + + destroy@1.2.0: + resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + + detect-indent@7.0.1: + resolution: {integrity: sha512-Mc7QhQ8s+cLrnUfU/Ji94vG/r8M26m8f++vyres4ZoojaRDpZ1eSIh/EpzLNwlWuvzSZ3UbDFspjFvTDXe6e/g==} + engines: {node: '>=12.20'} + + detect-libc@2.0.3: + resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==} + engines: {node: '>=8'} + + devtools-protocol@0.0.1367902: + resolution: {integrity: sha512-XxtPuC3PGakY6PD7dG66/o8KwJ/LkH2/EKe19Dcw58w53dv4/vSQEkn/SzuyhHE2q4zPgCkxQBxus3VV4ql+Pg==} + + devtools-protocol@0.0.1464554: + resolution: {integrity: sha512-CAoP3lYfwAGQTaAXYvA6JZR0fjGUb7qec1qf4mToyoH2TZgUFeIqYcjh6f9jNuhHfuZiEdH+PONHYrLhRQX6aw==} + + devtools-protocol@0.0.975963: + resolution: {integrity: sha512-SZX9ZgZjxNx0NGjl+FQlJ5oxPZbtOkr64IvUkxVjbTZZQS5OcY6YC0mVDK4Dgig6Ly2iIfW8mszlE+08dg2jDw==} + + diff@4.0.2: + resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} + engines: {node: '>=0.3.1'} + + diff@7.0.0: + resolution: {integrity: sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw==} + engines: {node: '>=0.3.1'} + + dir-glob@3.0.1: + resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} + engines: {node: '>=8'} + + doctrine@2.1.0: + resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} + engines: {node: '>=0.10.0'} + + doctrine@3.0.0: + resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} + engines: {node: '>=6.0.0'} + + dom-serializer@1.4.1: + resolution: {integrity: sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==} + + dom-types@1.1.2: + resolution: {integrity: sha512-yBe608cqVMPsjOzNnID8VdoOBvpewvp7e9Z4E+hcrDMHDlpl8Wv+HJ+xtNLMeA1X9rWtGIbscI6LDpe32H7Krw==} + + domelementtype@2.3.0: + resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} + + domhandler@4.3.1: + resolution: {integrity: sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==} + engines: {node: '>= 4'} + + domutils@2.8.0: + resolution: {integrity: sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==} + + dot-case@3.0.4: + resolution: {integrity: sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==} + + dotenv-cli@7.4.4: + resolution: {integrity: sha512-XkBYCG0tPIes+YZr4SpfFv76SQrV/LeCE8CI7JSEMi3VR9MvTihCGTOtbIexD6i2mXF+6px7trb1imVCXSNMDw==} + hasBin: true + + dotenv-expand@10.0.0: + resolution: {integrity: sha512-GopVGCpVS1UKH75VKHGuQFqS1Gusej0z4FyQkPdwjil2gNIv+LNsqBlboOzpJFZKVT95GkCyWJbBSdFEFUWI2A==} + engines: {node: '>=12'} + + dotenv@16.4.7: + resolution: {integrity: sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==} + engines: {node: '>=12'} + + dunder-proto@1.0.1: + resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} + engines: {node: '>= 0.4'} + + eastasianwidth@0.2.0: + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + + easy-table@1.2.0: + resolution: {integrity: sha512-OFzVOv03YpvtcWGe5AayU5G2hgybsg3iqA6drU8UaoZyB9jLGMTrz9+asnLp/E+6qPh88yEI1gvyZFZ41dmgww==} + + ee-first@1.1.1: + resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} + + eight-colors@1.3.1: + resolution: {integrity: sha512-7nXPYDeKh6DgJDR/mpt2G7N/hCNSGwwoPVmoI3+4TEwOb07VFN1WMPG0DFf6nMEjrkgdj8Og7l7IaEEk3VE6Zg==} + + ejs@3.1.10: + resolution: {integrity: sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==} + engines: {node: '>=0.10.0'} + hasBin: true + + electron-to-chromium@1.5.178: + resolution: {integrity: sha512-wObbz/ar3Bc6e4X5vf0iO8xTN8YAjN/tgiAOJLr7yjYFtP9wAjq8Mb5h0yn6kResir+VYx2DXBj9NNobs0ETSA==} + + elegant-spinner@1.0.1: + resolution: {integrity: sha512-B+ZM+RXvRqQaAmkMlO/oSe5nMUOaUnyfGYCEHoR8wrXsZR2mA0XVibsxV1bvTwxdRWah1PkQqso2EzhILGHtEQ==} + engines: {node: '>=0.10.0'} + + emoji-regex@10.4.0: + resolution: {integrity: sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==} + + emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + + emoji-regex@9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + + encodeurl@1.0.2: + resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} + engines: {node: '>= 0.8'} + + encodeurl@2.0.0: + resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==} + engines: {node: '>= 0.8'} + + encoding@0.1.13: + resolution: {integrity: sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==} + + end-of-stream@1.4.4: + resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} + + end-of-stream@1.4.5: + resolution: {integrity: sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==} + + engine.io-parser@5.2.3: + resolution: {integrity: sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==} + engines: {node: '>=10.0.0'} + + engine.io@6.6.2: + resolution: {integrity: sha512-gmNvsYi9C8iErnZdVcJnvCpSKbWTt1E8+JZo8b+daLninywUWi5NQ5STSHZ9rFjFO7imNcvb8Pc5pe/wMR5xEw==} + engines: {node: '>=10.2.0'} + + enhanced-resolve@5.18.0: + resolution: {integrity: sha512-0/r0MySGYG8YqlayBZ6MuCfECmHFdJ5qyPh8s8wa5Hnm6SaFLSK1VYCbj+NKp090Nm1caZhD+QTnmxO7esYGyQ==} + engines: {node: '>=10.13.0'} + + enquirer@2.4.1: + resolution: {integrity: sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==} + engines: {node: '>=8.6'} + + ensure-posix-path@1.1.1: + resolution: {integrity: sha512-VWU0/zXzVbeJNXvME/5EmLuEj2TauvoaTz6aFYK1Z92JCBlDlZ3Gu0tuGR42kpW1754ywTs+QB0g5TP0oj9Zaw==} + + entities@2.2.0: + resolution: {integrity: sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==} + + entities@4.5.0: + resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} + engines: {node: '>=0.12'} + + env-paths@2.2.1: + resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} + engines: {node: '>=6'} + + err-code@2.0.3: + resolution: {integrity: sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==} + + error-ex@1.3.2: + resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} + + es-abstract@1.23.8: + resolution: {integrity: sha512-lfab8IzDn6EpI1ibZakcgS6WsfEBiB+43cuJo+wgylx1xKXf+Sp+YR3vFuQwC/u3sxYwV8Cxe3B0DpVUu/WiJQ==} + engines: {node: '>= 0.4'} + + es-define-property@1.0.1: + resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} + engines: {node: '>= 0.4'} + + es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + + es-module-lexer@1.6.0: + resolution: {integrity: sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ==} + + es-object-atoms@1.0.0: + resolution: {integrity: sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==} + engines: {node: '>= 0.4'} + + es-set-tostringtag@2.0.3: + resolution: {integrity: sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==} + engines: {node: '>= 0.4'} + + es-shim-unscopables@1.0.2: + resolution: {integrity: sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==} + + es-to-primitive@1.3.0: + resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==} + engines: {node: '>= 0.4'} + + esbuild@0.25.5: + resolution: {integrity: sha512-P8OtKZRv/5J5hhz0cUAdu/cLuPIKXpQl1R9pZtvmHWQvrAUVd0UNIPT4IB4W3rNOqVO0rlqHmCIbSwxh/c9yUQ==} + engines: {node: '>=18'} + hasBin: true + + escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} + engines: {node: '>=6'} + + escape-html@1.0.3: + resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} + + escape-string-regexp@1.0.5: + resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} + engines: {node: '>=0.8.0'} + + escape-string-regexp@4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + + escodegen@2.1.0: + resolution: {integrity: sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==} + engines: {node: '>=6.0'} + hasBin: true + + eslint-compat-utils@0.5.1: + resolution: {integrity: sha512-3z3vFexKIEnjHE3zCMRo6fn/e44U7T1khUjg+Hp0ZQMCigh28rALD0nPFBcGZuiLC5rLZa2ubQHDRln09JfU2Q==} + engines: {node: '>=12'} + peerDependencies: + eslint: '>=6.0.0' + + eslint-compat-utils@0.6.4: + resolution: {integrity: sha512-/u+GQt8NMfXO8w17QendT4gvO5acfxQsAKirAt0LVxDnr2N8YLCVbregaNc/Yhp7NM128DwCaRvr8PLDfeNkQw==} + engines: {node: '>=12'} + peerDependencies: + eslint: '>=6.0.0' + + eslint-config-flat-gitignore@1.0.0: + resolution: {integrity: sha512-EWpSLrAP80IdcYK5sIhq/qAY0pmUdBnbzqzpE3QAn6H6wLBN26cMRoMNU9Di8upTzUSL6TXeYRxWhTYuz8+UQA==} + peerDependencies: + eslint: ^9.5.0 + + eslint-config-prettier@10.0.1: + resolution: {integrity: sha512-lZBts941cyJyeaooiKxAtzoPHTN+GbQTJFAIdQbRhA4/8whaAraEh47Whw/ZFfrjNSnlAxqfm9i0XVAEkULjCw==} + hasBin: true + peerDependencies: + eslint: '>=7.0.0' + + eslint-import-resolver-node@0.3.9: + resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==} + + eslint-import-resolver-typescript@3.8.2: + resolution: {integrity: sha512-o0nvXxsatYCDTzI1K5b3aYGQ6PjpDGJEVN86zqJw5SEewhmmggfRTotd2dqWr2t2zbeYpIEWGTCkgtUpIEIcaQ==} + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + eslint: '*' + eslint-plugin-import: '*' + eslint-plugin-import-x: '*' + peerDependenciesMeta: + eslint-plugin-import: + optional: true + eslint-plugin-import-x: + optional: true + + eslint-interactive@11.1.0: + resolution: {integrity: sha512-qiZax3rbugRE1AzeUPSM0MAybdvSnou4rVDfz3J3r6LdNKtmepYNL/F/pfMprypj9Ejhwht0CgzUrqTVc8H7og==} + engines: {node: '>=18.0.0'} + hasBin: true + peerDependencies: + eslint: ^8.45.0 || ^9.0.0 + + eslint-json-compat-utils@0.2.1: + resolution: {integrity: sha512-YzEodbDyW8DX8bImKhAcCeu/L31Dd/70Bidx2Qex9OFUtgzXLqtfWL4Hr5fM/aCCB8QUZLuJur0S9k6UfgFkfg==} + engines: {node: '>=12'} + peerDependencies: + '@eslint/json': '*' + eslint: '*' + jsonc-eslint-parser: ^2.4.0 + peerDependenciesMeta: + '@eslint/json': + optional: true + + eslint-module-utils@2.12.0: + resolution: {integrity: sha512-wALZ0HFoytlyh/1+4wuZ9FJCD/leWHQzzrxJ8+rebyReSLk7LApMyd3WJaLVoN+D5+WIdJyDK1c6JnE65V4Zyg==} + engines: {node: '>=4'} + peerDependencies: + '@typescript-eslint/parser': '*' + eslint: '*' + eslint-import-resolver-node: '*' + eslint-import-resolver-typescript: '*' + eslint-import-resolver-webpack: '*' + peerDependenciesMeta: + '@typescript-eslint/parser': + optional: true + eslint: + optional: true + eslint-import-resolver-node: + optional: true + eslint-import-resolver-typescript: + optional: true + eslint-import-resolver-webpack: + optional: true + + eslint-plugin-es-x@7.8.0: + resolution: {integrity: sha512-7Ds8+wAAoV3T+LAKeu39Y5BzXCrGKrcISfgKEqTS4BDN8SFEDQd0S43jiQ8vIa3wUKD07qitZdfzlenSi8/0qQ==} + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + eslint: '>=8' + + eslint-plugin-import-x@4.6.1: + resolution: {integrity: sha512-wluSUifMIb7UfwWXqx7Yx0lE/SGCcGXECLx/9bCmbY2nneLwvAZ4vkd1IXDjPKFvdcdUgr1BaRnaRpx3k2+Pfw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + + eslint-plugin-import@2.31.0: + resolution: {integrity: sha512-ixmkI62Rbc2/w8Vfxyh1jQRTdRTF52VxwRVHl/ykPAmqG+Nb7/kNn+byLP0LxPgI7zWA16Jt82SybJInmMia3A==} + engines: {node: '>=4'} + peerDependencies: + '@typescript-eslint/parser': '*' + eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9 + peerDependenciesMeta: + '@typescript-eslint/parser': + optional: true + + eslint-plugin-jsonc@2.19.1: + resolution: {integrity: sha512-MmlAOaZK1+Lg7YoCZPGRjb88ZjT+ct/KTsvcsbZdBm+w8WMzGx+XEmexk0m40P1WV9G2rFV7X3klyRGRpFXEjA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: '>=6.0.0' + + eslint-plugin-n@17.15.1: + resolution: {integrity: sha512-KFw7x02hZZkBdbZEFQduRGH4VkIH4MW97ClsbAM4Y4E6KguBJWGfWG1P4HEIpZk2bkoWf0bojpnjNAhYQP8beA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: '>=8.23.0' + + eslint-plugin-qunit@8.1.2: + resolution: {integrity: sha512-2gDQdHlQW8GVXD7YYkO8vbm9Ldc60JeGMuQN5QlD48OeZ8znBvvoHWZZMeXjvoDPReGaLEvyuWrDtrI8bDbcqw==} + engines: {node: ^16.0.0 || ^18.0.0 || >=20.0.0} + + eslint-plugin-regexp@2.7.0: + resolution: {integrity: sha512-U8oZI77SBtH8U3ulZ05iu0qEzIizyEDXd+BWHvyVxTOjGwcDcvy/kEpgFG4DYca2ByRLiVPFZ2GeH7j1pdvZTA==} + engines: {node: ^18 || >=20} + peerDependencies: + eslint: '>=8.44.0' + + eslint-plugin-simple-import-sort@12.1.1: + resolution: {integrity: sha512-6nuzu4xwQtE3332Uz0to+TxDQYRLTKRESSc2hefVT48Zc8JthmN23Gx9lnYhu0FtkRSL1oxny3kJ2aveVhmOVA==} + peerDependencies: + eslint: '>=5.0.0' + + eslint-plugin-unused-imports@4.1.4: + resolution: {integrity: sha512-YptD6IzQjDardkl0POxnnRBhU1OEePMV0nd6siHaRBbd+lyh6NAhFEobiznKU7kTsSsDeSD62Pe7kAM1b7dAZQ==} + peerDependencies: + '@typescript-eslint/eslint-plugin': ^8.0.0-0 || ^7.0.0 || ^6.0.0 || ^5.0.0 + eslint: ^9.0.0 || ^8.0.0 + peerDependenciesMeta: + '@typescript-eslint/eslint-plugin': + optional: true + + eslint-scope@8.2.0: + resolution: {integrity: sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + eslint-utils@3.0.0: + resolution: {integrity: sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==} + engines: {node: ^10.0.0 || ^12.0.0 || >= 14.0.0} + peerDependencies: + eslint: '>=5' + + eslint-visitor-keys@2.1.0: + resolution: {integrity: sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==} + engines: {node: '>=10'} + + eslint-visitor-keys@3.4.3: + resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + eslint-visitor-keys@4.2.0: + resolution: {integrity: sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + eslint-visitor-keys@4.2.1: + resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + eslint@9.20.1: + resolution: {integrity: sha512-m1mM33o6dBUjxl2qb6wv6nGNwCAsns1eKtaQ4l/NPHeTvhiUPbtdfMyktxN4B3fgHIgsYh1VT3V9txblpQHq+g==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + hasBin: true + peerDependencies: + jiti: '*' + peerDependenciesMeta: + jiti: + optional: true + + esno@0.16.3: + resolution: {integrity: sha512-6slSBEV1lMKcX13DBifvnDFpNno5WXhw4j/ff7RI0y51BZiDqEe5dNhhjhIQ3iCOQuzsm2MbVzmwqbN78BBhPg==} + hasBin: true + + espree@10.3.0: + resolution: {integrity: sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + espree@9.6.1: + resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + esprima@4.0.1: + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} + engines: {node: '>=4'} + hasBin: true + + esquery@1.6.0: + resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} + engines: {node: '>=0.10'} + + esrecurse@4.3.0: + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} + + estraverse@5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + + estree-walker@0.6.1: + resolution: {integrity: sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==} + + estree-walker@2.0.2: + resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} + + estree-walker@3.0.3: + resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + + esutils@2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + + etag@1.8.1: + resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} + engines: {node: '>= 0.6'} + + eventemitter3@4.0.7: + resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==} + + events-to-array@1.1.2: + resolution: {integrity: sha512-inRWzRY7nG+aXZxBzEqYKB3HPgwflZRopAjDCHv0whhRx+MTUr1ei0ICZUypdyE0HRm4L2d5VEcIqLD6yl+BFA==} + + execa@1.0.0: + resolution: {integrity: sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==} + engines: {node: '>=6'} + + execa@4.1.0: + resolution: {integrity: sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==} + engines: {node: '>=10'} + + execa@5.1.1: + resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} + engines: {node: '>=10'} + + execa@6.1.0: + resolution: {integrity: sha512-QVWlX2e50heYJcCPG0iWtf8r0xjEYfz/OYLGDYH+IyjWezzPNxz63qNFOu0l4YftGWuizFVZHHs8PrLU5p2IDA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + execa@7.1.1: + resolution: {integrity: sha512-wH0eMf/UXckdUYnO21+HDztteVv05rq2GXksxT4fCGeHkBhw1DROXh40wcjMcRqDOWE7iPJ4n3M7e2+YFP+76Q==} + engines: {node: ^14.18.0 || ^16.14.0 || >=18.0.0} + + execa@7.2.0: + resolution: {integrity: sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA==} + engines: {node: ^14.18.0 || ^16.14.0 || >=18.0.0} + + execa@9.5.2: + resolution: {integrity: sha512-EHlpxMCpHWSAh1dgS6bVeoLAXGnJNdR93aabr4QCGbzOM73o5XmRfM/e5FUqsw3aagP8S8XEWUWFAxnRBnAF0Q==} + engines: {node: ^18.19.0 || >=20.5.0} + + expect-type@1.1.0: + resolution: {integrity: sha512-bFi65yM+xZgk+u/KRIpekdSYkTB5W1pEf0Lt8Q8Msh7b+eQ7LXVtIB1Bkm4fvclDEL1b2CZkMhv2mOeF8tMdkA==} + engines: {node: '>=12.0.0'} + + express@4.21.2: + resolution: {integrity: sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==} + engines: {node: '>= 0.10.0'} + + extract-zip@2.0.1: + resolution: {integrity: sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==} + engines: {node: '>= 10.17.0'} + hasBin: true + + fast-content-type-parse@2.0.1: + resolution: {integrity: sha512-nGqtvLrj5w0naR6tDPfB4cUmYCqouzyQiz6C5y/LtcDllJdrcc6WaWW6iXyIIOErTa/XRybj28aasdn4LkVk6Q==} + + fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + + fast-fifo@1.3.2: + resolution: {integrity: sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==} + + fast-glob@3.3.3: + resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} + engines: {node: '>=8.6.0'} + + fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + + fast-levenshtein@2.0.6: + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + + fast-safe-stringify@2.1.1: + resolution: {integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==} + + fast-uri@3.0.5: + resolution: {integrity: sha512-5JnBCWpFlMo0a3ciDy/JckMzzv1U9coZrIhedq+HXxxUfDTAiS0LA8OKVao4G9BxmCVck/jtA5r3KAtRWEyD8Q==} + + fastq@1.18.0: + resolution: {integrity: sha512-QKHXPW0hD8g4UET03SdOdunzSouc9N4AuHdsX8XNcTsuz+yYFILVNIX4l9yHABMhiEI9Db0JTTIpu0wB+Y1QQw==} + + fd-slicer@1.1.0: + resolution: {integrity: sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==} + + fdir@6.4.3: + resolution: {integrity: sha512-PMXmW2y1hDDfTSRc9gaXIuCCRpuoz3Kaz8cUelp3smouvfT632ozg2vrT6lJsHKKOF59YLbOGfAWGUcKEfRMQw==} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + + fdir@6.4.6: + resolution: {integrity: sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + + figures@1.7.0: + resolution: {integrity: sha512-UxKlfCRuCBxSXU4C6t9scbDyWZ4VlaFFdojKtzJuSkuOBQ5CNFum+zZXFwHjo+CxBC1t6zlYPgHIgFjL8ggoEQ==} + engines: {node: '>=0.10.0'} + + figures@2.0.0: + resolution: {integrity: sha512-Oa2M9atig69ZkfwiApY8F2Yy+tzMbazyvqv21R0NsSC8floSOC09BbT1ITWAdoMGQvJ/aZnR1KMwdx9tvHnTNA==} + engines: {node: '>=4'} + + figures@6.1.0: + resolution: {integrity: sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg==} + engines: {node: '>=18'} + + file-entry-cache@8.0.0: + resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} + engines: {node: '>=16.0.0'} + + filelist@1.0.4: + resolution: {integrity: sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==} + + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} + engines: {node: '>=8'} + + finalhandler@1.3.1: + resolution: {integrity: sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==} + engines: {node: '>= 0.8'} + + find-cache-dir@5.0.0: + resolution: {integrity: sha512-OuWNfjfP05JcpAP3JPgAKUhWefjMRfI5iAoSsvE24ANYWJaepAtlSgWECSVEuRgSXpyNEc9DJwG/TZpgcOqyig==} + engines: {node: '>=16'} + + find-up-simple@1.0.0: + resolution: {integrity: sha512-q7Us7kcjj2VMePAa02hDAF6d+MzsdsAWEwYyOpwUtlerRBkOEPBCRZrAV4XfcSN8fHAgaD0hP7miwoay6DCprw==} + engines: {node: '>=18'} + + find-up@3.0.0: + resolution: {integrity: sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==} + engines: {node: '>=6'} + + find-up@4.1.0: + resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} + engines: {node: '>=8'} + + find-up@5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + + find-up@6.3.0: + resolution: {integrity: sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + find-up@7.0.0: + resolution: {integrity: sha512-YyZM99iHrqLKjmt4LJDj58KI+fYyufRLBSYcqycxf//KpBk9FoewoGX0450m9nB44qrZnovzC2oeP5hUibxc/g==} + engines: {node: '>=18'} + + fireworm@0.7.2: + resolution: {integrity: sha512-GjebTzq+NKKhfmDxjKq3RXwQcN9xRmZWhnnuC9L+/x5wBQtR0aaQM50HsjrzJ2wc28v1vSdfOpELok0TKR4ddg==} + + flat-cache@4.0.1: + resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} + engines: {node: '>=16'} + + flat@5.0.2: + resolution: {integrity: sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==} + hasBin: true + + flatted@3.3.2: + resolution: {integrity: sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==} + + follow-redirects@1.15.9: + resolution: {integrity: sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + + for-each@0.3.3: + resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} + + foreground-child@3.3.0: + resolution: {integrity: sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==} + engines: {node: '>=14'} + + forwarded@0.2.0: + resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} + engines: {node: '>= 0.6'} + + fresh@0.5.2: + resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} + engines: {node: '>= 0.6'} + + fs-constants@1.0.0: + resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} + + fs-extra@10.1.0: + resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} + engines: {node: '>=12'} + + fs-extra@11.3.0: + resolution: {integrity: sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew==} + engines: {node: '>=14.14'} + + fs-extra@8.1.0: + resolution: {integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==} + engines: {node: '>=6 <7 || >=8'} + + fs-extra@9.1.0: + resolution: {integrity: sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==} + engines: {node: '>=10'} + + fs-minipass@2.1.0: + resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==} + engines: {node: '>= 8'} + + fs.realpath@1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + function.prototype.name@1.1.8: + resolution: {integrity: sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==} + engines: {node: '>= 0.4'} + + functions-have-names@1.2.3: + resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} + + gauge@4.0.4: + resolution: {integrity: sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + deprecated: This package is no longer supported. + + gauge@5.0.2: + resolution: {integrity: sha512-pMaFftXPtiGIHCJHdcUUx9Rby/rFT/Kkt3fIIGCs+9PMDIljSyRiqraTlxNtBReJRDfUefpa263RQ3vnp5G/LQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + deprecated: This package is no longer supported. + + generic-names@4.0.0: + resolution: {integrity: sha512-ySFolZQfw9FoDb3ed9d80Cm9f0+r7qj+HJkWjeD9RBfpxEVTlVhol+gvaQB/78WbwYfbnNh8nWHHBSlg072y6A==} + + gensync@1.0.0-beta.2: + resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} + engines: {node: '>=6.9.0'} + + get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + + get-east-asian-width@1.3.0: + resolution: {integrity: sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==} + engines: {node: '>=18'} + + get-intrinsic@1.2.6: + resolution: {integrity: sha512-qxsEs+9A+u85HhllWJJFicJfPDhRmjzoYdl64aMWW9yRIJmSyxdn8IEkuIM530/7T+lv0TIHd8L6Q/ra0tEoeA==} + engines: {node: '>= 0.4'} + + get-package-type@0.1.0: + resolution: {integrity: sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==} + engines: {node: '>=8.0.0'} + + get-port-please@3.1.2: + resolution: {integrity: sha512-Gxc29eLs1fbn6LQ4jSU4vXjlwyZhF5HsGuMAa7gqBP4Rw4yxxltyDUuF5MBclFzDTXO+ACchGQoeela4DSfzdQ==} + + get-source@2.0.12: + resolution: {integrity: sha512-X5+4+iD+HoSeEED+uwrQ07BOQr0kEDFMVqqpBuI+RaZBpBpHCuXxo70bjar6f0b0u/DQJsJ7ssurpP0V60Az+w==} + + get-stream@4.1.0: + resolution: {integrity: sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==} + engines: {node: '>=6'} + + get-stream@5.2.0: + resolution: {integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==} + engines: {node: '>=8'} + + get-stream@6.0.1: + resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} + engines: {node: '>=10'} + + get-stream@9.0.1: + resolution: {integrity: sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==} + engines: {node: '>=18'} + + get-symbol-description@1.1.0: + resolution: {integrity: sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==} + engines: {node: '>= 0.4'} + + get-tsconfig@4.10.0: + resolution: {integrity: sha512-kGzZ3LWWQcGIAmg6iWvXn0ei6WDtV26wzHRMwDSzmAbcXrTEXxHy6IehI6/4eT6VRKyMP1eF1VqwrVUmE/LR7A==} + + get-tsconfig@4.10.1: + resolution: {integrity: sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ==} + + get-tsconfig@4.8.1: + resolution: {integrity: sha512-k9PN+cFBmaLWtVz29SkUoqU5O0slLuHJXt/2P+tMVFT+phsSGXGkp9t3rQIqdz0e+06EHNGs3oM6ZX1s2zHxRg==} + + get-uri@6.0.4: + resolution: {integrity: sha512-E1b1lFFLvLgak2whF2xDBcOy6NLVGZBqqjJjsIhvopKfWWEi64pLVTWWehV8KlLerZkfNTA95sTe2OdJKm1OzQ==} + engines: {node: '>= 14'} + + github-changelog@1.0.2: + resolution: {integrity: sha512-ieWWj+wEHcWwhofXOB6HwxYbRCmWMZ8q8NHjt+g8d0GVA8AJE3h7uxjZ9ZqT8l9TPrGH5HRjaVOqO3PiU4pUSQ==} + engines: {node: 12.* || 14.* || >= 16} + hasBin: true + + glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + + glob-parent@6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} + + glob@10.2.3: + resolution: {integrity: sha512-Kb4rfmBVE3eQTAimgmeqc2LwSnN0wIOkkUL6HmxEFxNJ4fHghYHVbFba/HcGcRjE6s9KoMNK3rSOwkL4PioZjg==} + engines: {node: '>=16 || 14 >=14.17'} + hasBin: true + + glob@10.4.5: + resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} + hasBin: true + + glob@11.0.1: + resolution: {integrity: sha512-zrQDm8XPnYEKawJScsnM0QzobJxlT/kHOOlRTio8IH/GrmxRE5fjllkzdaHclIuNjUQTJYH2xHNIGfdpJkDJUw==} + engines: {node: 20 || >=22} + hasBin: true + + glob@7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + deprecated: Glob versions prior to v9 are no longer supported + + global-directory@4.0.1: + resolution: {integrity: sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q==} + engines: {node: '>=18'} + + globals@14.0.0: + resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} + engines: {node: '>=18'} + + globals@15.14.0: + resolution: {integrity: sha512-OkToC372DtlQeje9/zHIo5CT8lRP/FUgEOKBEhU4e0abL7J7CD24fD9ohiLN5hagG/kWCYj4K5oaxxtj2Z0Dig==} + engines: {node: '>=18'} + + globals@15.15.0: + resolution: {integrity: sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==} + engines: {node: '>=18'} + + globalthis@1.0.4: + resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==} + engines: {node: '>= 0.4'} + + globalyzer@0.1.0: + resolution: {integrity: sha512-40oNTM9UfG6aBmuKxk/giHn5nQ8RVz/SS4Ir6zgzOv9/qC3kKZ9v4etGTcJbEl/NyVQH7FGU7d+X1egr57Md2Q==} + + globby@11.1.0: + resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} + engines: {node: '>=10'} + + globby@14.1.0: + resolution: {integrity: sha512-0Ia46fDOaT7k4og1PDW4YbodWWr3scS2vAr2lTbsplOt2WkKp0vQbkI9wKis/T5LV/dqPjO3bpS/z6GTJB82LA==} + engines: {node: '>=18'} + + globrex@0.1.2: + resolution: {integrity: sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==} + + gopd@1.2.0: + resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} + engines: {node: '>= 0.4'} + + got@11.8.6: + resolution: {integrity: sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==} + engines: {node: '>=10.19.0'} + + graceful-fs@4.2.10: + resolution: {integrity: sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==} + + graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + + graphemer@1.4.0: + resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} + + growly@1.3.0: + resolution: {integrity: sha512-+xGQY0YyAWCnqy7Cd++hc2JqMYzlm0dG30Jd0beaA64sROr8C4nt8Yc9V5Ro3avlSUDTN0ulqP/VBKi1/lLygw==} + + h3@1.15.3: + resolution: {integrity: sha512-z6GknHqyX0h9aQaTx22VZDf6QyZn+0Nh+Ym8O/u0SGSkyF5cuTJYKlc8MkzW3Nzf9LE1ivcpmYC3FUGpywhuUQ==} + + handlebars@4.7.8: + resolution: {integrity: sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==} + engines: {node: '>=0.4.7'} + hasBin: true + + hard-rejection@2.1.0: + resolution: {integrity: sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==} + engines: {node: '>=6'} + + has-ansi@2.0.0: + resolution: {integrity: sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==} + engines: {node: '>=0.10.0'} + + has-bigints@1.1.0: + resolution: {integrity: sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==} + engines: {node: '>= 0.4'} + + has-flag@3.0.0: + resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} + engines: {node: '>=4'} + + has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + + has-property-descriptors@1.0.2: + resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} + + has-proto@1.2.0: + resolution: {integrity: sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==} + engines: {node: '>= 0.4'} + + has-symbols@1.1.0: + resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} + engines: {node: '>= 0.4'} + + has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} + + has-unicode@2.0.1: + resolution: {integrity: sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==} + + hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + + he@1.2.0: + resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} + hasBin: true + + highlight.js@10.7.3: + resolution: {integrity: sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==} + + hosted-git-info@2.8.9: + resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} + + hosted-git-info@4.1.0: + resolution: {integrity: sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==} + engines: {node: '>=10'} + + hosted-git-info@7.0.2: + resolution: {integrity: sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==} + engines: {node: ^16.14.0 || >=18.0.0} + + hosted-git-info@8.0.2: + resolution: {integrity: sha512-sYKnA7eGln5ov8T8gnYlkSOxFJvywzEx9BueN6xo/GKO8PGiI6uK6xx+DIGe45T3bdVjLAQDQW1aicT8z8JwQg==} + engines: {node: ^18.17.0 || >=20.5.0} + + html-minifier-terser@7.2.0: + resolution: {integrity: sha512-tXgn3QfqPIpGl9o+K5tpcj3/MN4SfLtsx2GWwBC3SSd0tXQGyF3gsSqad8loJgKZGM3ZxbYDd5yhiBIdWpmvLA==} + engines: {node: ^14.13.1 || >=16.0.0} + hasBin: true + + http-cache-semantics@4.1.1: + resolution: {integrity: sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==} + + http-call@5.3.0: + resolution: {integrity: sha512-ahwimsC23ICE4kPl9xTBjKB4inbRaeLyZeRunC/1Jy/Z6X8tv22MEAjK+KBOMSVLaqXPTTmd8638waVIKLGx2w==} + engines: {node: '>=8.0.0'} + + http-errors@2.0.0: + resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} + engines: {node: '>= 0.8'} + + http-proxy-agent@4.0.1: + resolution: {integrity: sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==} + engines: {node: '>= 6'} + + http-proxy-agent@7.0.2: + resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==} + engines: {node: '>= 14'} + + http-proxy@1.18.1: + resolution: {integrity: sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==} + engines: {node: '>=8.0.0'} + + http2-wrapper@1.0.3: + resolution: {integrity: sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==} + engines: {node: '>=10.19.0'} + + https-proxy-agent@5.0.1: + resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} + engines: {node: '>= 6'} + + https-proxy-agent@7.0.6: + resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==} + engines: {node: '>= 14'} + + human-signals@1.1.1: + resolution: {integrity: sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==} + engines: {node: '>=8.12.0'} + + human-signals@2.1.0: + resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} + engines: {node: '>=10.17.0'} + + human-signals@3.0.1: + resolution: {integrity: sha512-rQLskxnM/5OCldHo+wNXbpVgDn5A17CUoKX+7Sokwaknlq7CdSnphy0W39GU8dw59XiCXmFXDg4fRuckQRKewQ==} + engines: {node: '>=12.20.0'} + + human-signals@4.3.1: + resolution: {integrity: sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==} + engines: {node: '>=14.18.0'} + + human-signals@8.0.0: + resolution: {integrity: sha512-/1/GPCpDUCCYwlERiYjxoczfP0zfvZMU/OWgQPMya9AbAE24vseigFdhAMObpc8Q4lc/kjutPfUddDYyAmejnA==} + engines: {node: '>=18.18.0'} + + humanize-ms@1.2.1: + resolution: {integrity: sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==} + + hyperlinker@1.0.0: + resolution: {integrity: sha512-Ty8UblRWFEcfSuIaajM34LdPXIhbs1ajEX/BBPv24J+enSVaEVY63xQ6lTO9VRYS5LAoghIG0IDJ+p+IPzKUQQ==} + engines: {node: '>=4'} + + iconv-lite@0.4.24: + resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} + engines: {node: '>=0.10.0'} + + iconv-lite@0.6.3: + resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} + engines: {node: '>=0.10.0'} + + icss-replace-symbols@1.1.0: + resolution: {integrity: sha512-chIaY3Vh2mh2Q3RGXttaDIzeiPvaVXJ+C4DAh/w3c37SKZ/U6PGMmuicR2EQQp9bKG8zLMCl7I+PtIoOOPp8Gg==} + + icss-utils@5.1.0: + resolution: {integrity: sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==} + engines: {node: ^10 || ^12 || >= 14} + peerDependencies: + postcss: ^8.1.0 + + ieee754@1.2.1: + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + + ignore@5.3.2: + resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} + engines: {node: '>= 4'} + + ignore@7.0.3: + resolution: {integrity: sha512-bAH5jbK/F3T3Jls4I0SO1hmPR0dKU0a7+SY6n1yzRtG54FLO8d6w/nxLFX2Nb7dBu6cCWXPaAME6cYqFUMmuCA==} + engines: {node: '>= 4'} + + import-cwd@3.0.0: + resolution: {integrity: sha512-4pnzH16plW+hgvRECbDWpQl3cqtvSofHWh44met7ESfZ8UZOWWddm8hEyDTqREJ9RbYHY8gi8DqmaelApoOGMg==} + engines: {node: '>=8'} + + import-fresh@3.3.0: + resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} + engines: {node: '>=6'} + + import-fresh@3.3.1: + resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} + engines: {node: '>=6'} + + import-from@3.0.0: + resolution: {integrity: sha512-CiuXOFFSzkU5x/CR0+z7T91Iht4CXgfCxVOFRhh2Zyhg5wOpWvvDLQUsWl+gcN+QscYBjez8hDCt85O7RLDttQ==} + engines: {node: '>=8'} + + imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + + indent-string@3.2.0: + resolution: {integrity: sha512-BYqTHXTGUIvg7t1r4sJNKcbDZkL92nkXA8YtRpbjFHRHGDL/NtUeiBJMeE60kIFN/Mg8ESaWQvftaYMGJzQZCQ==} + engines: {node: '>=4'} + + indent-string@4.0.0: + resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} + engines: {node: '>=8'} + + index-to-position@1.1.0: + resolution: {integrity: sha512-XPdx9Dq4t9Qk1mTMbWONJqU7boCoumEH7fRET37HX5+khDUl3J2W6PdALxhILYlIYx2amlwYcRPp28p0tSiojg==} + engines: {node: '>=18'} + + individual@3.0.0: + resolution: {integrity: sha512-rUY5vtT748NMRbEMrTNiFfy29BgGZwGXUi2NFUVMWQrogSLzlJvQV9eeMWi+g1aVaQ53tpyLAQtd5x/JH0Nh1g==} + + infer-owner@1.0.4: + resolution: {integrity: sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==} + + inflight@1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. + + inherits@2.0.3: + resolution: {integrity: sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==} + + inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + + ini@1.3.8: + resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} + + ini@3.0.1: + resolution: {integrity: sha512-it4HyVAUTKBc6m8e1iXWvXSTdndF7HbdN713+kvLrymxTaU4AUBWrJ4vEooP+V7fexnVD3LKcBshjGGPefSMUQ==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + + ini@4.1.1: + resolution: {integrity: sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + ini@5.0.0: + resolution: {integrity: sha512-+N0ngpO3e7cRUWOJAS7qw0IZIVc6XPrW4MlFBdD066F2L4k1L6ker3hLqSq7iXxU5tgS4WGkIUElWn5vogAEnw==} + engines: {node: ^18.17.0 || >=20.5.0} + + internal-slot@1.1.0: + resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==} + engines: {node: '>= 0.4'} + + internmap@1.0.1: + resolution: {integrity: sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw==} + + internmap@2.0.3: + resolution: {integrity: sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==} + engines: {node: '>=12'} + + ip-address@9.0.5: + resolution: {integrity: sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==} + engines: {node: '>= 12'} + + ipaddr.js@1.9.1: + resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} + engines: {node: '>= 0.10'} + + iron-webcrypto@1.2.1: + resolution: {integrity: sha512-feOM6FaSr6rEABp/eDfVseKyTMDt+KGpeB35SkVn9Tyn0CqvVsY3EwI0v5i8nMHyJnzCIQf7nsy3p41TPkJZhg==} + + is-array-buffer@3.0.5: + resolution: {integrity: sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==} + engines: {node: '>= 0.4'} + + is-arrayish@0.2.1: + resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + + is-async-function@2.0.0: + resolution: {integrity: sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==} + engines: {node: '>= 0.4'} + + is-bigint@1.1.0: + resolution: {integrity: sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==} + engines: {node: '>= 0.4'} + + is-boolean-object@1.2.1: + resolution: {integrity: sha512-l9qO6eFlUETHtuihLcYOaLKByJ1f+N4kthcU9YjHy3N+B3hWv0y/2Nd0mu/7lTFnRQHTrSdXF50HQ3bl5fEnng==} + engines: {node: '>= 0.4'} + + is-bun-module@1.3.0: + resolution: {integrity: sha512-DgXeu5UWI0IsMQundYb5UAOzm6G2eVnarJ0byP6Tm55iZNKceD59LNPA2L4VvsScTtHcw0yEkVwSf7PC+QoLSA==} + + is-callable@1.2.7: + resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} + engines: {node: '>= 0.4'} + + is-core-module@2.16.1: + resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} + engines: {node: '>= 0.4'} + + is-data-view@1.0.2: + resolution: {integrity: sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==} + engines: {node: '>= 0.4'} + + is-date-object@1.1.0: + resolution: {integrity: sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==} + engines: {node: '>= 0.4'} + + is-docker@2.2.1: + resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} + engines: {node: '>=8'} + hasBin: true + + is-docker@3.0.0: + resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + hasBin: true + + is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + + is-finalizationregistry@1.1.1: + resolution: {integrity: sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==} + engines: {node: '>= 0.4'} + + is-fullwidth-code-point@1.0.0: + resolution: {integrity: sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==} + engines: {node: '>=0.10.0'} + + is-fullwidth-code-point@2.0.0: + resolution: {integrity: sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==} + engines: {node: '>=4'} + + is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + + is-generator-function@1.0.10: + resolution: {integrity: sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==} + engines: {node: '>= 0.4'} + + is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + + is-inside-container@1.0.0: + resolution: {integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==} + engines: {node: '>=14.16'} + hasBin: true + + is-installed-globally@1.0.0: + resolution: {integrity: sha512-K55T22lfpQ63N4KEN57jZUAaAYqYHEe8veb/TycJRk9DdSCLLcovXz/mL6mOnhQaZsQGwPhuFopdQIlqGSEjiQ==} + engines: {node: '>=18'} + + is-interactive@2.0.0: + resolution: {integrity: sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==} + engines: {node: '>=12'} + + is-lambda@1.0.1: + resolution: {integrity: sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==} + + is-map@2.0.3: + resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} + engines: {node: '>= 0.4'} + + is-module@1.0.0: + resolution: {integrity: sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==} + + is-number-object@1.1.1: + resolution: {integrity: sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==} + engines: {node: '>= 0.4'} + + is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + + is-observable@1.1.0: + resolution: {integrity: sha512-NqCa4Sa2d+u7BWc6CukaObG3Fh+CU9bvixbpcXYhy2VvYS7vVGIdAgnIS5Ks3A/cqk4rebLJ9s8zBstT2aKnIA==} + engines: {node: '>=4'} + + is-path-inside@4.0.0: + resolution: {integrity: sha512-lJJV/5dYS+RcL8uQdBDW9c9uWFLLBNRyFhnAKXw5tVqLlKZ4RMGZKv+YQ/IA3OhD+RpbJa1LLFM1FQPGyIXvOA==} + engines: {node: '>=12'} + + is-plain-obj@1.1.0: + resolution: {integrity: sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==} + engines: {node: '>=0.10.0'} + + is-plain-obj@2.1.0: + resolution: {integrity: sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==} + engines: {node: '>=8'} + + is-plain-obj@4.1.0: + resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} + engines: {node: '>=12'} + + is-promise@2.2.2: + resolution: {integrity: sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==} + + is-reference@1.2.1: + resolution: {integrity: sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==} + + is-regex@1.2.1: + resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==} + engines: {node: '>= 0.4'} + + is-retry-allowed@1.2.0: + resolution: {integrity: sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg==} + engines: {node: '>=0.10.0'} + + is-set@2.0.3: + resolution: {integrity: sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==} + engines: {node: '>= 0.4'} + + is-shared-array-buffer@1.0.4: + resolution: {integrity: sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==} + engines: {node: '>= 0.4'} + + is-stream@1.1.0: + resolution: {integrity: sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==} + engines: {node: '>=0.10.0'} + + is-stream@2.0.1: + resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} + engines: {node: '>=8'} + + is-stream@3.0.0: + resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + is-stream@4.0.1: + resolution: {integrity: sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==} + engines: {node: '>=18'} + + is-string@1.1.1: + resolution: {integrity: sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==} + engines: {node: '>= 0.4'} + + is-subdir@1.2.0: + resolution: {integrity: sha512-2AT6j+gXe/1ueqbW6fLZJiIw3F8iXGJtt0yDrZaBhAZEG1raiTxKWU+IPqMCzQAXOUCKdA4UDMgacKH25XG2Cw==} + engines: {node: '>=4'} + + is-symbol@1.1.1: + resolution: {integrity: sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==} + engines: {node: '>= 0.4'} + + is-type@0.0.1: + resolution: {integrity: sha512-YwJh/zBVrcJ90aAnPBM0CbHvm7lG9ao7lIFeqTZ1UQj4iFLpM5CikdaU+dGGesrMJwxLqPGmjjrUrQ6Kn3Zh+w==} + + is-typed-array@1.1.15: + resolution: {integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==} + engines: {node: '>= 0.4'} + + is-typedarray@1.0.0: + resolution: {integrity: sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==} + + is-unicode-supported@0.1.0: + resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} + engines: {node: '>=10'} + + is-unicode-supported@1.3.0: + resolution: {integrity: sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==} + engines: {node: '>=12'} + + is-unicode-supported@2.1.0: + resolution: {integrity: sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==} + engines: {node: '>=18'} + + is-weakmap@2.0.2: + resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==} + engines: {node: '>= 0.4'} + + is-weakref@1.1.0: + resolution: {integrity: sha512-SXM8Nwyys6nT5WP6pltOwKytLV7FqQ4UiibxVmW+EIosHcmCqkkjViTb5SNssDlkCiEYRP1/pdWUKVvZBmsR2Q==} + engines: {node: '>= 0.4'} + + is-weakset@2.0.4: + resolution: {integrity: sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==} + engines: {node: '>= 0.4'} + + is-windows@1.0.2: + resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==} + engines: {node: '>=0.10.0'} + + is-wsl@2.2.0: + resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} + engines: {node: '>=8'} + + is-wsl@3.1.0: + resolution: {integrity: sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==} + engines: {node: '>=16'} + + isarray@1.0.0: + resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} + + isarray@2.0.5: + resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} + + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + isexe@3.1.1: + resolution: {integrity: sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==} + engines: {node: '>=16'} + + jackspeak@2.3.6: + resolution: {integrity: sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==} + engines: {node: '>=14'} + + jackspeak@3.4.3: + resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} + + jackspeak@4.0.2: + resolution: {integrity: sha512-bZsjR/iRjl1Nk1UkjGpAzLNfQtzuijhn2g+pbZb98HQ1Gk8vM9hfbxeMBP+M2/UUdwj0RqGG3mlvk2MsAqwvEw==} + engines: {node: 20 || >=22} + + jake@10.9.2: + resolution: {integrity: sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA==} + engines: {node: '>=10'} + hasBin: true + + jiti@2.4.2: + resolution: {integrity: sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==} + hasBin: true + + jju@1.4.0: + resolution: {integrity: sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==} + + js-reporters@2.1.0: + resolution: {integrity: sha512-Q4GcEcPSb6ovhqp91claM3WPbSntQxbIn+3JiJgEXturys2ttWgs31VC60Yja+2unpNOH2A2qyjWFU2thCQ8sg==} + engines: {node: '>=10'} + + js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + + js-yaml@3.14.1: + resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} + hasBin: true + + js-yaml@4.1.0: + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + hasBin: true + + jsbn@1.1.0: + resolution: {integrity: sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==} + + jsdoc-type-pratt-parser@4.1.0: + resolution: {integrity: sha512-Hicd6JK5Njt2QB6XYFS7ok9e37O8AYk3jTcppG4YVQnYjOemymvTcmc7OWsmq/Qqj5TdRFO5/x/tIPmBeRtGHg==} + engines: {node: '>=12.0.0'} + + jsesc@3.0.2: + resolution: {integrity: sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==} + engines: {node: '>=6'} + hasBin: true + + jsesc@3.1.0: + resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} + engines: {node: '>=6'} + hasBin: true + + json-buffer@3.0.1: + resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + + json-parse-better-errors@1.0.2: + resolution: {integrity: sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==} + + json-parse-even-better-errors@2.3.1: + resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + + json-parse-even-better-errors@3.0.2: + resolution: {integrity: sha512-fi0NG4bPjCHunUJffmLd0gxssIgkNmArMvis4iNah6Owg1MCJjWhEcDLmsK6iGkJq3tHwbDkTlce70/tmXN4cQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + json-parse-even-better-errors@4.0.0: + resolution: {integrity: sha512-lR4MXjGNgkJc7tkQ97kb2nuEMnNCyU//XYVH0MKTGcXEiSudQ5MKGKen3C5QubYy0vmq+JGitUg92uuywGEwIA==} + engines: {node: ^18.17.0 || >=20.5.0} + + json-query@2.2.2: + resolution: {integrity: sha512-y+IcVZSdqNmS4fO8t1uZF6RMMs0xh3SrTjJr9bp1X3+v0Q13+7Cyv12dSmKwDswp/H427BVtpkLWhGxYu3ZWRA==} + + json-schema-traverse@0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + + json-schema-traverse@1.0.0: + resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + + json-stable-stringify-without-jsonify@1.0.1: + resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + + json-stringify-safe@5.0.1: + resolution: {integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==} + + json5@1.0.2: + resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==} + hasBin: true + + json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + + jsonc-eslint-parser@2.4.0: + resolution: {integrity: sha512-WYDyuc/uFcGp6YtM2H0uKmUwieOuzeE/5YocFJLnLfclZ4inf3mRn8ZVy1s7Hxji7Jxm6Ss8gqpexD/GlKoGgg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + jsonfile@4.0.0: + resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} + + jsonfile@6.1.0: + resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} + + jstat@1.9.6: + resolution: {integrity: sha512-rPBkJbK2TnA8pzs93QcDDPlKcrtZWuuCo2dVR0TFLOJSxhqfWOVCSp8aV3/oSbn+4uY4yw1URtLpHQedtmXfug==} + + keyv@4.5.4: + resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + + kind-of@6.0.3: + resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} + engines: {node: '>=0.10.0'} + + knip@5.44.4: + resolution: {integrity: sha512-Ryn8LwWHLId8jSK1DgtT0hmg5DbzkqAtH+Gg3vZJpmSMgGHMspej9Ag+qKTm8wsPLDjVetuEz/lIsobo0XCMvQ==} + engines: {node: '>=18.18.0'} + hasBin: true + peerDependencies: + '@types/node': ^22.13.4 + typescript: ^5.7.3 + + ky@1.7.4: + resolution: {integrity: sha512-zYEr/gh7uLW2l4su11bmQ2M9xLgQLjyvx58UyNM/6nuqyWFHPX5ktMjvpev3F8QWdjSsHUpnWew4PBCswBNuMQ==} + engines: {node: '>=18'} + + latest-version@9.0.0: + resolution: {integrity: sha512-7W0vV3rqv5tokqkBAFV1LbR7HPOWzXQDpDgEuib/aJ1jsZZx6x3c2mBI+TJhJzOhkGeaLbCKEHXEXLfirtG2JA==} + engines: {node: '>=18'} + + lazystream@1.0.1: + resolution: {integrity: sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==} + engines: {node: '>= 0.6.3'} + + levn@0.4.1: + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} + engines: {node: '>= 0.8.0'} + + lighthouse-logger@1.4.2: + resolution: {integrity: sha512-gPWxznF6TKmUHrOQjlVo2UbaL2EJ71mb2CCeRs/2qBpi4L/g4LUVc9+3lKQ6DTUZwJswfM7ainGrLO1+fOqa2g==} + + lilconfig@2.1.0: + resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==} + engines: {node: '>=10'} + + lilconfig@3.1.3: + resolution: {integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==} + engines: {node: '>=14'} + + lines-and-columns@1.2.4: + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + + lines-and-columns@2.0.4: + resolution: {integrity: sha512-wM1+Z03eypVAVUCE7QdSqpVIvelbOakn1M0bPDoA4SGWPx3sNDVUiMo3L6To6WWGClB7VyXnhQ4Sn7gxiJbE6A==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + listr-silent-renderer@1.1.1: + resolution: {integrity: sha512-L26cIFm7/oZeSNVhWB6faeorXhMg4HNlb/dS/7jHhr708jxlXrtrBWo4YUxZQkc6dGoxEAe6J/D3juTRBUzjtA==} + engines: {node: '>=4'} + + listr-update-renderer@0.5.0: + resolution: {integrity: sha512-tKRsZpKz8GSGqoI/+caPmfrypiaq+OQCbd+CovEC24uk1h952lVj5sC7SqyFUm+OaJ5HN/a1YLt5cit2FMNsFA==} + engines: {node: '>=6'} + peerDependencies: + listr: ^0.14.2 + + listr-verbose-renderer@0.5.0: + resolution: {integrity: sha512-04PDPqSlsqIOaaaGZ+41vq5FejI9auqTInicFRndCBgE3bXG8D6W1I+mWhk+1nqbHmyhla/6BUrd5OSiHwKRXw==} + engines: {node: '>=4'} + + listr@0.14.3: + resolution: {integrity: sha512-RmAl7su35BFd/xoMamRjpIE4j3v+L28o8CT5YhAXQJm1fD+1l9ngXY8JAQRJ+tFK2i5njvi0iRUKV09vPwA0iA==} + engines: {node: '>=6'} + + load-json-file@6.2.0: + resolution: {integrity: sha512-gUD/epcRms75Cw8RT1pUdHugZYM5ce64ucs2GEISABwkRsOQr0q2wm/MV2TKThycIe5e0ytRweW2RZxclogCdQ==} + engines: {node: '>=8'} + + load-tsconfig@0.2.5: + resolution: {integrity: sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + loader-utils@3.3.1: + resolution: {integrity: sha512-FMJTLMXfCLMLfJxcX9PFqX5qD88Z5MRGaZCVzfuqeZSPsyiBzs+pahDQjbIWz2QIzPZz0NX9Zy4FX3lmK6YHIg==} + engines: {node: '>= 12.13.0'} + + loader.js@4.7.0: + resolution: {integrity: sha512-9M2KvGT6duzGMgkOcTkWb+PR/Q2Oe54df/tLgHGVmFpAmtqJ553xJh6N63iFYI2yjo2PeJXbS5skHi/QpJq4vA==} + + locate-path@3.0.0: + resolution: {integrity: sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==} + engines: {node: '>=6'} + + locate-path@5.0.0: + resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} + engines: {node: '>=8'} + + locate-path@6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + + locate-path@7.2.0: + resolution: {integrity: sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + lodash._baseflatten@3.1.4: + resolution: {integrity: sha512-fESngZd+X4k+GbTxdMutf8ohQa0s3sJEHIcwtu4/LsIQ2JTDzdRxDCMQjW+ezzwRitLmHnacVVmosCbxifefbw==} + + lodash._getnative@3.9.1: + resolution: {integrity: sha512-RrL9VxMEPyDMHOd9uFbvMe8X55X16/cGM5IgOKgRElQZutpX89iS6vwl64duTV1/16w5JY7tuFNXqoekmh1EmA==} + + lodash._isiterateecall@3.0.9: + resolution: {integrity: sha512-De+ZbrMu6eThFti/CSzhRvTKMgQToLxbij58LMfM8JnYDNSOjkjTCIaa8ixglOeGh2nyPlakbt5bJWJ7gvpYlQ==} + + lodash.camelcase@4.3.0: + resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==} + + lodash.clonedeep@4.5.0: + resolution: {integrity: sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==} + + lodash.debounce@3.1.1: + resolution: {integrity: sha512-lcmJwMpdPAtChA4hfiwxTtgFeNAaow701wWUgVUqeD0XJF7vMXIN+bu/2FJSGxT0NUbZy9g9VFrlOFfPjl+0Ew==} + + lodash.debounce@4.0.8: + resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==} + + lodash.defaults@4.2.0: + resolution: {integrity: sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==} + + lodash.difference@4.5.0: + resolution: {integrity: sha512-dS2j+W26TQ7taQBGN8Lbbq04ssV3emRw4NY58WErlTO29pIqS0HmoT5aJ9+TUQ1N3G+JOZSji4eugsWwGp9yPA==} + + lodash.flatten@3.0.2: + resolution: {integrity: sha512-jCXLoNcqQRbnT/KWZq2fIREHWeczrzpTR0vsycm96l/pu5hGeAntVBG0t7GuM/2wFqmnZs3d1eGptnAH2E8+xQ==} + + lodash.flatten@4.4.0: + resolution: {integrity: sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==} + + lodash.isarguments@3.1.0: + resolution: {integrity: sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==} + + lodash.isarray@3.0.4: + resolution: {integrity: sha512-JwObCrNJuT0Nnbuecmqr5DgtuBppuCvGD9lxjFpAzwnVtdGoDQ1zig+5W8k5/6Gcn0gZ3936HDAlGd28i7sOGQ==} + + lodash.isplainobject@4.0.6: + resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==} + + lodash.memoize@4.1.2: + resolution: {integrity: sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==} + + lodash.merge@4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + + lodash.mergewith@4.6.2: + resolution: {integrity: sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==} + + lodash.truncate@4.4.2: + resolution: {integrity: sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==} + + lodash.union@4.6.0: + resolution: {integrity: sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw==} + + lodash.uniq@4.5.0: + resolution: {integrity: sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==} + + lodash@4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + + log-symbols@1.0.2: + resolution: {integrity: sha512-mmPrW0Fh2fxOzdBbFv4g1m6pR72haFLPJ2G5SJEELf1y+iaQrDG6cWCPjy54RHYbZAt7X+ls690Kw62AdWXBzQ==} + engines: {node: '>=0.10.0'} + + log-symbols@4.1.0: + resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} + engines: {node: '>=10'} + + log-symbols@6.0.0: + resolution: {integrity: sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==} + engines: {node: '>=18'} + + log-update@2.3.0: + resolution: {integrity: sha512-vlP11XfFGyeNQlmEn9tJ66rEW1coA/79m5z6BCkudjbAGE83uhAcGYrBFwfs3AdLiLzGRusRPAbSPK9xZteCmg==} + engines: {node: '>=4'} + + loupe@3.1.2: + resolution: {integrity: sha512-23I4pFZHmAemUnz8WZXbYRSKYj801VDaNv9ETuMh7IrMc7VuVVSo+Z9iLE3ni30+U48iDWfi30d3twAXBYmnCg==} + + loupe@3.1.3: + resolution: {integrity: sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug==} + + lower-case@2.0.2: + resolution: {integrity: sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==} + + lowercase-keys@2.0.0: + resolution: {integrity: sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==} + engines: {node: '>=8'} + + lru-cache@10.4.3: + resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} + + lru-cache@11.0.2: + resolution: {integrity: sha512-123qHRfJBmo2jXDbo/a5YOQrJoHF/GNQTLzQ5+IdK5pWpceK17yRc6ozlWd25FxvGKQbIUs91fDFkXmDHTKcyA==} + engines: {node: 20 || >=22} + + lru-cache@5.1.1: + resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + + lru-cache@6.0.0: + resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} + engines: {node: '>=10'} + + lru-cache@7.18.3: + resolution: {integrity: sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==} + engines: {node: '>=12'} + + magic-string@0.25.9: + resolution: {integrity: sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==} + + magic-string@0.30.0: + resolution: {integrity: sha512-LA+31JYDJLs82r2ScLrlz1GjSgu66ZV518eyWT+S8VhyQn/JL0u9MeBOvQMGYiPk1DBiSN9DDMOcXvigJZaViQ==} + engines: {node: '>=12'} + + magic-string@0.30.17: + resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==} + + make-error@1.3.6: + resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} + + make-fetch-happen@9.1.0: + resolution: {integrity: sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==} + engines: {node: '>= 10'} + + map-age-cleaner@0.1.3: + resolution: {integrity: sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==} + engines: {node: '>=6'} + + map-obj@1.0.1: + resolution: {integrity: sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==} + engines: {node: '>=0.10.0'} + + map-obj@4.3.0: + resolution: {integrity: sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==} + engines: {node: '>=8'} + + marky@1.3.0: + resolution: {integrity: sha512-ocnPZQLNpvbedwTy9kNrQEsknEfgvcLMvOtz3sFeWApDq1MXH1TqkCIx58xlpESsfwQOnuBO9beyQuNGzVvuhQ==} + + math-intrinsics@1.1.0: + resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} + engines: {node: '>= 0.4'} + + mdn-data@2.0.14: + resolution: {integrity: sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==} + + media-typer@0.3.0: + resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} + engines: {node: '>= 0.6'} + + mem@8.1.1: + resolution: {integrity: sha512-qFCFUDs7U3b8mBDPyz5EToEKoAkgCzqquIgi9nkkR9bixxOVOre+09lbuH7+9Kn2NFpm56M3GUWVbU2hQgdACA==} + engines: {node: '>=10'} + + meow@9.0.0: + resolution: {integrity: sha512-+obSblOQmRhcyBt62furQqRAQpNyWXo8BuQ5bN7dG8wmwQ+vwHKp/rCFD4CrTP8CsDQD1sjoZ94K417XEUk8IQ==} + engines: {node: '>=10'} + + merge-descriptors@1.0.3: + resolution: {integrity: sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==} + + merge-stream@2.0.0: + resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} + + merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + + methods@1.1.2: + resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} + engines: {node: '>= 0.6'} + + micromatch@4.0.8: + resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} + engines: {node: '>=8.6'} + + mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + + mime-db@1.53.0: + resolution: {integrity: sha512-oHlN/w+3MQ3rba9rqFr6V/ypF10LSkdwUysQL7GkXoTgIWeV+tcXGA852TBxH+gsh8UWoyhR1hKcoMJTuWflpg==} + engines: {node: '>= 0.6'} + + mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + + mime@1.6.0: + resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} + engines: {node: '>=4'} + hasBin: true + + mimic-fn@1.2.0: + resolution: {integrity: sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==} + engines: {node: '>=4'} + + mimic-fn@2.1.0: + resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} + engines: {node: '>=6'} + + mimic-fn@3.1.0: + resolution: {integrity: sha512-Ysbi9uYW9hFyfrThdDEQuykN4Ey6BuwPD2kpI5ES/nFTDn/98yxYNLZJcgUAKPT/mcrLLKaGzJR9YVxJrIdASQ==} + engines: {node: '>=8'} + + mimic-fn@4.0.0: + resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} + engines: {node: '>=12'} + + mimic-function@5.0.1: + resolution: {integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==} + engines: {node: '>=18'} + + mimic-response@1.0.1: + resolution: {integrity: sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==} + engines: {node: '>=4'} + + mimic-response@3.1.0: + resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==} + engines: {node: '>=10'} + + min-indent@1.0.1: + resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} + engines: {node: '>=4'} + + minimatch@10.0.1: + resolution: {integrity: sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==} + engines: {node: 20 || >=22} + + minimatch@3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + + minimatch@5.1.6: + resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} + engines: {node: '>=10'} + + minimatch@9.0.5: + resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} + engines: {node: '>=16 || 14 >=14.17'} + + minimist-options@4.1.0: + resolution: {integrity: sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==} + engines: {node: '>= 6'} + + minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + + minipass-collect@1.0.2: + resolution: {integrity: sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==} + engines: {node: '>= 8'} + + minipass-fetch@1.4.1: + resolution: {integrity: sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw==} + engines: {node: '>=8'} + + minipass-flush@1.0.5: + resolution: {integrity: sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==} + engines: {node: '>= 8'} + + minipass-pipeline@1.2.4: + resolution: {integrity: sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==} + engines: {node: '>=8'} + + minipass-sized@1.0.3: + resolution: {integrity: sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==} + engines: {node: '>=8'} + + minipass@2.9.0: + resolution: {integrity: sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==} + + minipass@3.3.6: + resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==} + engines: {node: '>=8'} + + minipass@4.2.8: + resolution: {integrity: sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==} + engines: {node: '>=8'} + + minipass@5.0.0: + resolution: {integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==} + engines: {node: '>=8'} + + minipass@7.1.2: + resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} + engines: {node: '>=16 || 14 >=14.17'} + + minizlib@2.1.2: + resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==} + engines: {node: '>= 8'} + + mitt@3.0.1: + resolution: {integrity: sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==} + + mkdirp@0.5.6: + resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} + hasBin: true + + mkdirp@1.0.4: + resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} + engines: {node: '>=10'} + hasBin: true + + mkdirp@3.0.1: + resolution: {integrity: sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==} + engines: {node: '>=10'} + hasBin: true + + mlly@1.7.4: + resolution: {integrity: sha512-qmdSIPC4bDJXgZTCR7XosJiNKySV7O215tsPtDN9iEO/7q/76b/ijtgRu/+epFXSJhijtTCCGp3DWS549P3xKw==} + + mocha@11.7.1: + resolution: {integrity: sha512-5EK+Cty6KheMS/YLPPMJC64g5V61gIR25KsRItHw6x4hEKT6Njp1n9LOlH4gpevuwMVS66SXaBBpg+RWZkza4A==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + hasBin: true + + mri@1.2.0: + resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} + engines: {node: '>=4'} + + mrmime@2.0.1: + resolution: {integrity: sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==} + engines: {node: '>=10'} + + ms@2.0.0: + resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + mustache@4.2.0: + resolution: {integrity: sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==} + hasBin: true + + mz@2.7.0: + resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} + + nanoid@3.3.11: + resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + nanoid@3.3.8: + resolution: {integrity: sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + natural-compare@1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + + natural-orderby@2.0.3: + resolution: {integrity: sha512-p7KTHxU0CUrcOXe62Zfrb5Z13nLvPhSWR/so3kFulUQU0sgUll2Z0LwpsLN351eOOD+hRGu/F1g+6xDfPeD++Q==} + + ndjson@2.0.0: + resolution: {integrity: sha512-nGl7LRGrzugTtaFcJMhLbpzJM6XdivmbkdlaGcrk/LXg2KL/YBC6z1g70xh0/al+oFuVFP8N8kiWRucmeEH/qQ==} + engines: {node: '>=10'} + hasBin: true + + negotiator@0.6.3: + resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} + engines: {node: '>= 0.6'} + + negotiator@0.6.4: + resolution: {integrity: sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==} + engines: {node: '>= 0.6'} + + neo-async@2.6.2: + resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} + + netmask@2.0.2: + resolution: {integrity: sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==} + engines: {node: '>= 0.4.0'} + + nice-try@1.0.5: + resolution: {integrity: sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==} + + no-case@3.0.4: + resolution: {integrity: sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==} + + node-mock-http@1.0.1: + resolution: {integrity: sha512-0gJJgENizp4ghds/Ywu2FCmcRsgBTmRQzYPZm61wy+Em2sBarSka0OhQS5huLBg6od1zkNpnWMCZloQDFVvOMQ==} + + node-notifier@10.0.1: + resolution: {integrity: sha512-YX7TSyDukOZ0g+gmzjB6abKu+hTGvO8+8+gIFDsRCU2t8fLV/P2unmt+LGFaIa4y64aX98Qksa97rgz4vMNeLQ==} + + node-releases@2.0.19: + resolution: {integrity: sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==} + + node-watch@0.7.3: + resolution: {integrity: sha512-3l4E8uMPY1HdMMryPRUAl+oIHtXtyiTlIiESNSVSNxcPfzAFzeTbXFQkZfAwBbo0B1qMSG8nUABx+Gd+YrbKrQ==} + engines: {node: '>=6'} + + normalize-package-data@2.5.0: + resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} + + normalize-package-data@3.0.3: + resolution: {integrity: sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==} + engines: {node: '>=10'} + + normalize-package-data@6.0.2: + resolution: {integrity: sha512-V6gygoYb/5EmNI+MEGrWkC+e6+Rr7mTmfHrxDbLzxQogBkgzo76rkok0Am6thgSF7Mv2nLOajAJj5vDJZEFn7g==} + engines: {node: ^16.14.0 || >=18.0.0} + + normalize-path@3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + + normalize-registry-url@2.0.0: + resolution: {integrity: sha512-3e9FwDyRAhbxXw4slm4Tjv40u78yPwMc/WZkACpqNQOs5sM7wic853AeTLkMFEVhivZkclGYlse8iYsklz0Yvg==} + + normalize-url@6.1.0: + resolution: {integrity: sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==} + engines: {node: '>=10'} + + npm-install-checks@7.1.1: + resolution: {integrity: sha512-u6DCwbow5ynAX5BdiHQ9qvexme4U3qHW3MWe5NqH+NeBm0LbiH6zvGjNNew1fY+AZZUtVHbOPF3j7mJxbUzpXg==} + engines: {node: ^18.17.0 || >=20.5.0} + + npm-normalize-package-bin@4.0.0: + resolution: {integrity: sha512-TZKxPvItzai9kN9H/TkmCtx/ZN/hvr3vUycjlfmH0ootY9yFBzNOpiXAdIn1Iteqsvk4lQn6B5PTrt+n6h8k/w==} + engines: {node: ^18.17.0 || >=20.5.0} + + npm-package-arg@12.0.2: + resolution: {integrity: sha512-f1NpFjNI9O4VbKMOlA5QoBq/vSQPORHcTZ2feJpFkTHJ9eQkdlmZEKSjcAhxTGInC7RlEyScT9ui67NaOsjFWA==} + engines: {node: ^18.17.0 || >=20.5.0} + + npm-pick-manifest@10.0.0: + resolution: {integrity: sha512-r4fFa4FqYY8xaM7fHecQ9Z2nE9hgNfJR+EmoKv0+chvzWkBcORX3r0FpTByP+CbOVJDladMXnPQGVN8PBLGuTQ==} + engines: {node: ^18.17.0 || >=20.5.0} + + npm-run-path@2.0.2: + resolution: {integrity: sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==} + engines: {node: '>=4'} + + npm-run-path@4.0.1: + resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} + engines: {node: '>=8'} + + npm-run-path@5.3.0: + resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + npm-run-path@6.0.0: + resolution: {integrity: sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA==} + engines: {node: '>=18'} + + npmlog@6.0.2: + resolution: {integrity: sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + deprecated: This package is no longer supported. + + nth-check@2.1.1: + resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} + + number-is-nan@1.0.1: + resolution: {integrity: sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==} + engines: {node: '>=0.10.0'} + + object-assign@4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + + object-hash@1.3.1: + resolution: {integrity: sha512-OSuu/pU4ENM9kmREg0BdNrUDIl1heYa4mBZacJc+vVWz4GtAwu7jO8s4AIt2aGRUTqxykpWzI3Oqnsm13tTMDA==} + engines: {node: '>= 0.10.0'} + + object-inspect@1.13.3: + resolution: {integrity: sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==} + engines: {node: '>= 0.4'} + + object-keys@1.1.1: + resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} + engines: {node: '>= 0.4'} + + object-treeify@1.1.33: + resolution: {integrity: sha512-EFVjAYfzWqWsBMRHPMAXLCDIJnpMhdWAqR7xG6M6a2cs6PMFpl/+Z20w9zDW4vkxOFfddegBKq9Rehd0bxWE7A==} + engines: {node: '>= 10'} + + object.assign@4.1.7: + resolution: {integrity: sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==} + engines: {node: '>= 0.4'} + + object.fromentries@2.0.8: + resolution: {integrity: sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==} + engines: {node: '>= 0.4'} + + object.groupby@1.0.3: + resolution: {integrity: sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==} + engines: {node: '>= 0.4'} + + object.values@1.2.1: + resolution: {integrity: sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==} + engines: {node: '>= 0.4'} + + on-finished@2.4.1: + resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} + engines: {node: '>= 0.8'} + + on-headers@1.0.2: + resolution: {integrity: sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==} + engines: {node: '>= 0.8'} + + once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + + onetime@2.0.1: + resolution: {integrity: sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ==} + engines: {node: '>=4'} + + onetime@5.1.2: + resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} + engines: {node: '>=6'} + + onetime@6.0.0: + resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} + engines: {node: '>=12'} + + onetime@7.0.0: + resolution: {integrity: sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==} + engines: {node: '>=18'} + + open@10.1.2: + resolution: {integrity: sha512-cxN6aIDPz6rm8hbebcP7vrQNhvRcveZoJU72Y7vskh4oIm+BZwBECnx5nTmrlres1Qapvx27Qo1Auukpf8PKXw==} + engines: {node: '>=18'} + + optionator@0.9.4: + resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} + engines: {node: '>= 0.8.0'} + + ora@8.1.1: + resolution: {integrity: sha512-YWielGi1XzG1UTvOaCFaNgEnuhZVMSHYkW/FQ7UX8O26PtlpdM84c0f7wLPlkvx2RfiQmnzd61d/MGxmpQeJPw==} + engines: {node: '>=18'} + + os-tmpdir@1.0.2: + resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==} + engines: {node: '>=0.10.0'} + + own-keys@1.0.1: + resolution: {integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==} + engines: {node: '>= 0.4'} + + p-cancelable@2.1.1: + resolution: {integrity: sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==} + engines: {node: '>=8'} + + p-defer@1.0.0: + resolution: {integrity: sha512-wB3wfAxZpk2AzOfUMJNL+d36xothRSyj8EXOa4f6GMqYDN9BJaaSISbsk+wS9abmnebVw95C2Kb5t85UmpCxuw==} + engines: {node: '>=4'} + + p-filter@2.1.0: + resolution: {integrity: sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw==} + engines: {node: '>=8'} + + p-finally@1.0.0: + resolution: {integrity: sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==} + engines: {node: '>=4'} + + p-limit@2.3.0: + resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} + engines: {node: '>=6'} + + p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + + p-limit@4.0.0: + resolution: {integrity: sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + p-locate@3.0.0: + resolution: {integrity: sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==} + engines: {node: '>=6'} + + p-locate@4.1.0: + resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} + engines: {node: '>=8'} + + p-locate@5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + + p-locate@6.0.0: + resolution: {integrity: sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + p-map@2.1.0: + resolution: {integrity: sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==} + engines: {node: '>=6'} + + p-map@3.0.0: + resolution: {integrity: sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==} + engines: {node: '>=8'} + + p-map@4.0.0: + resolution: {integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==} + engines: {node: '>=10'} + + p-map@7.0.3: + resolution: {integrity: sha512-VkndIv2fIB99swvQoA65bm+fsmt6UNdGeIB0oxBs+WhAhdh08QA04JXpI7rbB9r08/nkbysKoya9rtDERYOYMA==} + engines: {node: '>=18'} + + p-queue@6.6.2: + resolution: {integrity: sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ==} + engines: {node: '>=8'} + + p-timeout@3.2.0: + resolution: {integrity: sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==} + engines: {node: '>=8'} + + p-try@2.2.0: + resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} + engines: {node: '>=6'} + + pac-proxy-agent@7.1.0: + resolution: {integrity: sha512-Z5FnLVVZSnX7WjBg0mhDtydeRZ1xMcATZThjySQUHqr+0ksP8kqaw23fNKkaaN/Z8gwLUs/W7xdl0I75eP2Xyw==} + engines: {node: '>= 14'} + + pac-resolver@7.0.1: + resolution: {integrity: sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==} + engines: {node: '>= 14'} + + package-json-from-dist@1.0.1: + resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} + + package-json@10.0.1: + resolution: {integrity: sha512-ua1L4OgXSBdsu1FPb7F3tYH0F48a6kxvod4pLUlGY9COeJAJQNX/sNH2IiEmsxw7lqYiAwrdHMjz1FctOsyDQg==} + engines: {node: '>=18'} + + package-json@6.5.0: + resolution: {integrity: sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==} + engines: {node: '>=8'} + + package-manager-detector@0.2.8: + resolution: {integrity: sha512-ts9KSdroZisdvKMWVAVCXiKqnqNfXz4+IbrBG8/BWx/TR5le+jfenvoBuIZ6UWM9nz47W7AbD9qYfAwfWMIwzA==} + + param-case@3.0.4: + resolution: {integrity: sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==} + + parent-module@1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} + + parse-github-repo-url@1.4.1: + resolution: {integrity: sha512-bSWyzBKqcSL4RrncTpGsEKoJ7H8a4L3++ifTAbTFeMHyq2wRV+42DGmQcHIrJIvdcacjIOxEuKH/w4tthF17gg==} + + parse-json@4.0.0: + resolution: {integrity: sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==} + engines: {node: '>=4'} + + parse-json@5.2.0: + resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} + engines: {node: '>=8'} + + parse-json@7.1.1: + resolution: {integrity: sha512-SgOTCX/EZXtZxBE5eJ97P4yGM5n37BwRU+YMsH4vNzFqJV/oWFXXCmwFlgWUM4PrakybVOueJJ6pwHqSVhTFDw==} + engines: {node: '>=16'} + + parse-json@8.3.0: + resolution: {integrity: sha512-ybiGyvspI+fAoRQbIPRddCcSTV9/LsJbf0e/S85VLowVGzRmokfneg2kwVW/KU5rOXrPSbF1qAKPMgNTqqROQQ==} + engines: {node: '>=18'} + + parse-ms@2.1.0: + resolution: {integrity: sha512-kHt7kzLoS9VBZfUsiKjv43mr91ea+U05EyKkEtqp7vNbHxmaVuEqN7XxeEVnGrMtYOAxGrDElSi96K7EgO1zCA==} + engines: {node: '>=6'} + + parse-ms@4.0.0: + resolution: {integrity: sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==} + engines: {node: '>=18'} + + parse5-htmlparser2-tree-adapter@6.0.1: + resolution: {integrity: sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==} + + parse5@5.1.1: + resolution: {integrity: sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==} + + parse5@6.0.1: + resolution: {integrity: sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==} + + parseurl@1.3.3: + resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} + engines: {node: '>= 0.8'} + + pascal-case@3.1.2: + resolution: {integrity: sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==} + + password-prompt@1.1.3: + resolution: {integrity: sha512-HkrjG2aJlvF0t2BMH0e2LB/EHf3Lcq3fNMzy4GYHcQblAvOl+QQji1Lx7WRBMqpVK8p+KR7bCg7oqAMXtdgqyw==} + + path-absolute@1.0.1: + resolution: {integrity: sha512-gds5iRhSeOcDtj8gfWkRHLtZKTPsFVuh7utbjYtvnclw4XM+ffRzJrwqMhOD1PVqef7nBLmgsu1vIujjvAJrAw==} + engines: {node: '>=4'} + + path-exists@3.0.0: + resolution: {integrity: sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==} + engines: {node: '>=4'} + + path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + + path-exists@5.0.0: + resolution: {integrity: sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + path-is-absolute@1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + + path-key@2.0.1: + resolution: {integrity: sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==} + engines: {node: '>=4'} + + path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + path-key@4.0.0: + resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} + engines: {node: '>=12'} + + path-name@1.0.0: + resolution: {integrity: sha512-/dcAb5vMXH0f51yvMuSUqFpxUcA8JelbRmE5mW/p4CUJxrNgK24IkstnV7ENtg2IDGBOu6izKTG6eilbnbNKWQ==} + + path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + + path-scurry@1.11.1: + resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} + engines: {node: '>=16 || 14 >=14.18'} + + path-scurry@2.0.0: + resolution: {integrity: sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==} + engines: {node: 20 || >=22} + + path-temp@2.1.0: + resolution: {integrity: sha512-cMMJTAZlion/RWRRC48UbrDymEIt+/YSD/l8NqjneyDw2rDOBQcP5yRkMB4CYGn47KMhZvbblBP7Z79OsMw72w==} + engines: {node: '>=8.15'} + + path-to-regexp@0.1.12: + resolution: {integrity: sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==} + + path-type@4.0.0: + resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} + engines: {node: '>=8'} + + path-type@6.0.0: + resolution: {integrity: sha512-Vj7sf++t5pBD637NSfkxpHSMfWaeig5+DKWLhcqIYx6mWQz5hdJTGDVMQiJcw1ZYkhs7AazKDGpRVji1LJCZUQ==} + engines: {node: '>=18'} + + path@0.12.7: + resolution: {integrity: sha512-aXXC6s+1w7otVF9UletFkFcDsJeO7lSZBPUQhtb5O0xJe8LtYhj/GxldoL09bBj9+ZmE2hNoHqQSFMN5fikh4Q==} + + pathe@1.1.2: + resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==} + + pathe@2.0.2: + resolution: {integrity: sha512-15Ztpk+nov8DR524R4BF7uEuzESgzUEAV4Ah7CUMNGXdE5ELuvxElxGXndBl32vMSsWa1jpNf22Z+Er3sKwq+w==} + + pathe@2.0.3: + resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} + + pathval@2.0.0: + resolution: {integrity: sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==} + engines: {node: '>= 14.16'} + + pend@1.2.0: + resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==} + + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + + picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + + picomatch@4.0.2: + resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==} + engines: {node: '>=12'} + + pify@5.0.0: + resolution: {integrity: sha512-eW/gHNMlxdSP6dmG6uJip6FXN0EQBwm2clYYd8Wul42Cwu/DK8HEftzsapcNdYe2MfLiIwZqsDk2RDEsTE79hA==} + engines: {node: '>=10'} + + pirates@4.0.6: + resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==} + engines: {node: '>= 6'} + + pkg-dir@7.0.0: + resolution: {integrity: sha512-Ie9z/WINcxxLp27BKOCHGde4ITq9UklYKDzVo1nhk5sqGEXU3FpkwP5GM2voTGJkGd9B3Otl+Q4uwSOeSUtOBA==} + engines: {node: '>=14.16'} + + pkg-entry-points@1.1.1: + resolution: {integrity: sha512-BhZa7iaPmB4b3vKIACoppyUoYn8/sFs17VJJtzrzPZvEnN2nqrgg911tdL65lA2m1ml6UI3iPeYbZQ4VXpn1mA==} + + pkg-types@1.3.0: + resolution: {integrity: sha512-kS7yWjVFCkIw9hqdJBoMxDdzEngmkr5FXeWZZfQ6GoYacjVnsW6l2CcYW/0ThD0vF4LPJgVYnrg4d0uuhwYQbg==} + + pkg-up@3.1.0: + resolution: {integrity: sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==} + engines: {node: '>=8'} + + possible-typed-array-names@1.0.0: + resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==} + engines: {node: '>= 0.4'} + + postcss-calc@8.2.4: + resolution: {integrity: sha512-SmWMSJmB8MRnnULldx0lQIyhSNvuDl9HfrZkaqqE/WHAhToYsAvDq+yAsA/kIyINDszOp3Rh0GFoNuH5Ypsm3Q==} + peerDependencies: + postcss: ^8.2.2 + + postcss-colormin@5.3.1: + resolution: {integrity: sha512-UsWQG0AqTFQmpBegeLLc1+c3jIqBNB0zlDGRWR+dQ3pRKJL1oeMzyqmH3o2PIfn9MBdNrVPWhDbT769LxCTLJQ==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-convert-values@5.1.3: + resolution: {integrity: sha512-82pC1xkJZtcJEfiLw6UXnXVXScgtBrjlO5CBmuDQc+dlb88ZYheFsjTn40+zBVi3DkfF7iezO0nJUPLcJK3pvA==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-discard-comments@5.1.2: + resolution: {integrity: sha512-+L8208OVbHVF2UQf1iDmRcbdjJkuBF6IS29yBDSiWUIzpYaAhtNl6JYnYm12FnkeCwQqF5LeklOu6rAqgfBZqQ==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-discard-duplicates@5.1.0: + resolution: {integrity: sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-discard-empty@5.1.1: + resolution: {integrity: sha512-zPz4WljiSuLWsI0ir4Mcnr4qQQ5e1Ukc3i7UfE2XcrwKK2LIPIqE5jxMRxO6GbI3cv//ztXDsXwEWT3BHOGh3A==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-discard-overridden@5.1.0: + resolution: {integrity: sha512-21nOL7RqWR1kasIVdKs8HNqQJhFxLsyRfAnUDm4Fe4t4mCWL9OJiHvlHPjcd8zc5Myu89b/7wZDnOSjFgeWRtw==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-load-config@3.1.4: + resolution: {integrity: sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==} + engines: {node: '>= 10'} + peerDependencies: + postcss: '>=8.0.9' + ts-node: '>=9.0.0' + peerDependenciesMeta: + postcss: + optional: true + ts-node: + optional: true + + postcss-merge-longhand@5.1.7: + resolution: {integrity: sha512-YCI9gZB+PLNskrK0BB3/2OzPnGhPkBEwmwhfYk1ilBHYVAZB7/tkTHFBAnCrvBBOmeYyMYw3DMjT55SyxMBzjQ==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-merge-rules@5.1.4: + resolution: {integrity: sha512-0R2IuYpgU93y9lhVbO/OylTtKMVcHb67zjWIfCiKR9rWL3GUk1677LAqD/BcHizukdZEjT8Ru3oHRoAYoJy44g==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-minify-font-values@5.1.0: + resolution: {integrity: sha512-el3mYTgx13ZAPPirSVsHqFzl+BBBDrXvbySvPGFnQcTI4iNslrPaFq4muTkLZmKlGk4gyFAYUBMH30+HurREyA==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-minify-gradients@5.1.1: + resolution: {integrity: sha512-VGvXMTpCEo4qHTNSa9A0a3D+dxGFZCYwR6Jokk+/3oB6flu2/PnPXAh2x7x52EkY5xlIHLm+Le8tJxe/7TNhzw==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-minify-params@5.1.4: + resolution: {integrity: sha512-+mePA3MgdmVmv6g+30rn57USjOGSAyuxUmkfiWpzalZ8aiBkdPYjXWtHuwJGm1v5Ojy0Z0LaSYhHaLJQB0P8Jw==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-minify-selectors@5.2.1: + resolution: {integrity: sha512-nPJu7OjZJTsVUmPdm2TcaiohIwxP+v8ha9NehQ2ye9szv4orirRU3SDdtUmKH+10nzn0bAyOXZ0UEr7OpvLehg==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-modules-extract-imports@3.1.0: + resolution: {integrity: sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==} + engines: {node: ^10 || ^12 || >= 14} + peerDependencies: + postcss: ^8.1.0 + + postcss-modules-local-by-default@4.0.5: + resolution: {integrity: sha512-6MieY7sIfTK0hYfafw1OMEG+2bg8Q1ocHCpoWLqOKj3JXlKu4G7btkmM/B7lFubYkYWmRSPLZi5chid63ZaZYw==} + engines: {node: ^10 || ^12 || >= 14} + peerDependencies: + postcss: ^8.1.0 + + postcss-modules-scope@3.2.0: + resolution: {integrity: sha512-oq+g1ssrsZOsx9M96c5w8laRmvEu9C3adDSjI8oTcbfkrTE8hx/zfyobUoWIxaKPO8bt6S62kxpw5GqypEw1QQ==} + engines: {node: ^10 || ^12 || >= 14} + peerDependencies: + postcss: ^8.1.0 + + postcss-modules-values@4.0.0: + resolution: {integrity: sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==} + engines: {node: ^10 || ^12 || >= 14} + peerDependencies: + postcss: ^8.1.0 + + postcss-modules@4.3.1: + resolution: {integrity: sha512-ItUhSUxBBdNamkT3KzIZwYNNRFKmkJrofvC2nWab3CPKhYBQ1f27XXh1PAPE27Psx58jeelPsxWB/+og+KEH0Q==} + peerDependencies: + postcss: ^8.0.0 + + postcss-normalize-charset@5.1.0: + resolution: {integrity: sha512-mSgUJ+pd/ldRGVx26p2wz9dNZ7ji6Pn8VWBajMXFf8jk7vUoSrZ2lt/wZR7DtlZYKesmZI680qjr2CeFF2fbUg==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-normalize-display-values@5.1.0: + resolution: {integrity: sha512-WP4KIM4o2dazQXWmFaqMmcvsKmhdINFblgSeRgn8BJ6vxaMyaJkwAzpPpuvSIoG/rmX3M+IrRZEz2H0glrQNEA==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-normalize-positions@5.1.1: + resolution: {integrity: sha512-6UpCb0G4eofTCQLFVuI3EVNZzBNPiIKcA1AKVka+31fTVySphr3VUgAIULBhxZkKgwLImhzMR2Bw1ORK+37INg==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-normalize-repeat-style@5.1.1: + resolution: {integrity: sha512-mFpLspGWkQtBcWIRFLmewo8aC3ImN2i/J3v8YCFUwDnPu3Xz4rLohDO26lGjwNsQxB3YF0KKRwspGzE2JEuS0g==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-normalize-string@5.1.0: + resolution: {integrity: sha512-oYiIJOf4T9T1N4i+abeIc7Vgm/xPCGih4bZz5Nm0/ARVJ7K6xrDlLwvwqOydvyL3RHNf8qZk6vo3aatiw/go3w==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-normalize-timing-functions@5.1.0: + resolution: {integrity: sha512-DOEkzJ4SAXv5xkHl0Wa9cZLF3WCBhF3o1SKVxKQAa+0pYKlueTpCgvkFAHfk+Y64ezX9+nITGrDZeVGgITJXjg==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-normalize-unicode@5.1.1: + resolution: {integrity: sha512-qnCL5jzkNUmKVhZoENp1mJiGNPcsJCs1aaRmURmeJGES23Z/ajaln+EPTD+rBeNkSryI+2WTdW+lwcVdOikrpA==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-normalize-url@5.1.0: + resolution: {integrity: sha512-5upGeDO+PVthOxSmds43ZeMeZfKH+/DKgGRD7TElkkyS46JXAUhMzIKiCa7BabPeIy3AQcTkXwVVN7DbqsiCew==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-normalize-whitespace@5.1.1: + resolution: {integrity: sha512-83ZJ4t3NUDETIHTa3uEg6asWjSBYL5EdkVB0sDncx9ERzOKBVJIUeDO9RyA9Zwtig8El1d79HBp0JEi8wvGQnA==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-ordered-values@5.1.3: + resolution: {integrity: sha512-9UO79VUhPwEkzbb3RNpqqghc6lcYej1aveQteWY+4POIwlqkYE21HKWaLDF6lWNuqCobEAyTovVhtI32Rbv2RQ==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-reduce-initial@5.1.2: + resolution: {integrity: sha512-dE/y2XRaqAi6OvjzD22pjTUQ8eOfc6m/natGHgKFBK9DxFmIm69YmaRVQrGgFlEfc1HePIurY0TmDeROK05rIg==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-reduce-transforms@5.1.0: + resolution: {integrity: sha512-2fbdbmgir5AvpW9RLtdONx1QoYG2/EtqpNQbFASDlixBbAYuTcJ0dECwlqNqH7VbaUnEnh8SrxOe2sRIn24XyQ==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-selector-parser@6.1.2: + resolution: {integrity: sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==} + engines: {node: '>=4'} + + postcss-svgo@5.1.0: + resolution: {integrity: sha512-D75KsH1zm5ZrHyxPakAxJWtkyXew5qwS70v56exwvw542d9CRtTo78K0WeFxZB4G7JXKKMbEZtZayTGdIky/eA==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-unique-selectors@5.1.1: + resolution: {integrity: sha512-5JiODlELrz8L2HwxfPnhOWZYWDxVHWL83ufOv84NrcgipI7TaeRsatAhK4Tr2/ZiYldpK/wBvw5BD3qfaK96GA==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-value-parser@4.2.0: + resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} + + postcss@8.5.3: + resolution: {integrity: sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==} + engines: {node: ^10 || ^12 || >=14} + + postcss@8.5.6: + resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==} + engines: {node: ^10 || ^12 || >=14} + + prelude-ls@1.2.1: + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} + engines: {node: '>= 0.8.0'} + + prettier@2.8.8: + resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==} + engines: {node: '>=10.13.0'} + hasBin: true + + prettier@3.5.1: + resolution: {integrity: sha512-hPpFQvHwL3Qv5AdRvBFMhnKo4tYxp0ReXiPn2bxkiohEX6mBeBwEpBSQTkD458RaaDKQMYSp4hX4UtfUTA5wDw==} + engines: {node: '>=14'} + hasBin: true + + pretty-bytes@5.6.0: + resolution: {integrity: sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==} + engines: {node: '>=6'} + + pretty-ms@7.0.1: + resolution: {integrity: sha512-973driJZvxiGOQ5ONsFhOF/DtzPMOMtgC11kCpUrPGMTgqp2q/1gwzCquocrN33is0VZ5GFHXZYMM9l6h67v2Q==} + engines: {node: '>=10'} + + pretty-ms@9.2.0: + resolution: {integrity: sha512-4yf0QO/sllf/1zbZWYnvWw3NxCQwLXKzIj0G849LSufP15BXKM0rbD2Z3wVnkMfjdn/CB0Dpp444gYAACdsplg==} + engines: {node: '>=18'} + + preval.macro@5.0.0: + resolution: {integrity: sha512-+OZRqZYx1pjZ7H5Jis8bPFXkiT7lwA46UzAT4IjuzFVKwkJK+TwIx1TCqrqNCf8U3e5O12mEJEz1BXslkCLWfQ==} + engines: {node: '>=10'} + + printable-characters@1.0.42: + resolution: {integrity: sha512-dKp+C4iXWK4vVYZmYSd0KBH5F/h1HoZRsbJ82AVKRO3PEo8L4lBS/vLwhVtpwwuYcoIsVY+1JYKR268yn480uQ==} + + printf@0.6.1: + resolution: {integrity: sha512-is0ctgGdPJ5951KulgfzvHGwJtZ5ck8l042vRkV6jrkpBzTmb/lueTqguWHy2JfVA+RY6gFVlaZgUS0j7S/dsw==} + engines: {node: '>= 0.9.0'} + + proc-log@5.0.0: + resolution: {integrity: sha512-Azwzvl90HaF0aCz1JrDdXQykFakSSNPaPoiZ9fm5qJIMHioDZEi7OAdRwSm6rSoPtY3Qutnm3L7ogmg3dc+wbQ==} + engines: {node: ^18.17.0 || >=20.5.0} + + process-nextick-args@2.0.1: + resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} + + process@0.11.10: + resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==} + engines: {node: '>= 0.6.0'} + + progress@2.0.3: + resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==} + engines: {node: '>=0.4.0'} + + promise-inflight@1.0.1: + resolution: {integrity: sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==} + peerDependencies: + bluebird: '*' + peerDependenciesMeta: + bluebird: + optional: true + + promise-retry@2.0.1: + resolution: {integrity: sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==} + engines: {node: '>=10'} + + promise.series@0.2.0: + resolution: {integrity: sha512-VWQJyU2bcDTgZw8kpfBpB/ejZASlCrzwz5f2hjb/zlujOEB4oeiAhHygAWq8ubsX2GVkD4kCU5V2dwOTaCY5EQ==} + engines: {node: '>=0.12'} + + proto-list@1.2.4: + resolution: {integrity: sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==} + + proxy-addr@2.0.7: + resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} + engines: {node: '>= 0.10'} + + proxy-agent@6.5.0: + resolution: {integrity: sha512-TmatMXdr2KlRiA2CyDu8GqR8EjahTG3aY3nXjdzFyoZbmB8hrBsTyMezhULIXKnC0jpfjlmiZ3+EaCzoInSu/A==} + engines: {node: '>= 14'} + + proxy-from-env@1.1.0: + resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + + psl@1.15.0: + resolution: {integrity: sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==} + + publint@0.3.2: + resolution: {integrity: sha512-fPs7QUbUvwixxPYUUTn0Kqp0rbH5rbiAOZwQOXMkIj+4Nopby1AngodSQmzTkJWTJ5R4uVV8oYmgVIjj+tgv1w==} + engines: {node: '>=18'} + hasBin: true + + pump@3.0.2: + resolution: {integrity: sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==} + + pump@3.0.3: + resolution: {integrity: sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==} + + punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} + + puppeteer-chromium-resolver@23.0.0: + resolution: {integrity: sha512-PbSXK4ERPwp+eYm+SVY5vMWCxsdeJcddwz4avXvDx7kE9DLE+L86Xg027sypw2oan5yi6557brzVsbajcMmy2g==} + + puppeteer-chromium-resolver@24.0.1: + resolution: {integrity: sha512-whu9e5qmnZekCP5hvlYMe7rWe4cU9seCISRlfT0vXGlCsy7psbeXHdGW6QdXrwyadvCTiD1Ft62jPaqia8ZQaA==} + + puppeteer-core@23.11.1: + resolution: {integrity: sha512-3HZ2/7hdDKZvZQ7dhhITOUg4/wOrDRjyK2ZBllRB0ZCOi9u0cwq1ACHDjBB+nX+7+kltHjQvBRdeY7+W0T+7Gg==} + engines: {node: '>=18'} + + puppeteer-core@24.11.2: + resolution: {integrity: sha512-c49WifNb8hix+gQH17TldmD6TC/Md2HBaTJLHexIUq4sZvo2pyHY/Pp25qFQjibksBu/SJRYUY7JsoaepNbiRA==} + engines: {node: '>=18'} + + puppeteer@23.11.1: + resolution: {integrity: sha512-53uIX3KR5en8l7Vd8n5DUv90Ae9QDQsyIthaUFVzwV6yU750RjqRznEtNMBT20VthqAdemnJN+hxVdmMHKt7Zw==} + engines: {node: '>=18'} + hasBin: true + + puppeteer@24.11.2: + resolution: {integrity: sha512-HopdRZWHa5zk0HSwd8hU+GlahQ3fmesTAqMIDHVY9HasCvppcYuHYXyjml0nlm+nbwVCqAQWV+dSmiNCrZGTGQ==} + engines: {node: '>=18'} + hasBin: true + + qs@6.13.0: + resolution: {integrity: sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==} + engines: {node: '>=0.6'} + + querystringify@2.2.0: + resolution: {integrity: sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==} + + queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + + quick-lru@4.0.1: + resolution: {integrity: sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==} + engines: {node: '>=8'} + + quick-lru@5.1.1: + resolution: {integrity: sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==} + engines: {node: '>=10'} + + qunit@2.24.1: + resolution: {integrity: sha512-Eu0k/5JDjx0QnqxsE1WavnDNDgL1zgMZKsMw/AoAxnsl9p4RgyLODyo2N7abZY7CEAnvl5YUqFZdkImzbgXzSg==} + engines: {node: '>=10'} + hasBin: true + + race-cancellation@0.4.1: + resolution: {integrity: sha512-TF1vf4q/a5mwER9DoIuniE/qNIRM3Begyoe+21VUKgsyQAT4iIfSqlK7aG4Of1J1wzeATqVwbDP0dwX9GhaGcw==} + + radix3@1.1.2: + resolution: {integrity: sha512-b484I/7b8rDEdSDKckSSBA8knMpcdsXudlE/LNL639wFoHKwLbEkQFZHWEYwDC0wa0FKUcCY+GAF73Z7wxNVFA==} + + randombytes@2.1.0: + resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} + + range-parser@1.2.1: + resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} + engines: {node: '>= 0.6'} + + raw-body@2.5.2: + resolution: {integrity: sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==} + engines: {node: '>= 0.8'} + + rc@1.2.8: + resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} + hasBin: true + + read-ini-file@4.0.0: + resolution: {integrity: sha512-zz4qv/sKETv7nAkATqSJ9YMbKD8NXRPuA8d17VdYCuNYrVstB1S6UAMU6aytf5vRa9MESbZN7jLZdcmrOxz4gg==} + engines: {node: '>=14.6'} + + read-pkg-up@7.0.1: + resolution: {integrity: sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==} + engines: {node: '>=8'} + + read-pkg@5.2.0: + resolution: {integrity: sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==} + engines: {node: '>=8'} + + read-pkg@8.1.0: + resolution: {integrity: sha512-PORM8AgzXeskHO/WEv312k9U03B8K9JSiWF/8N9sUuFjBa+9SF2u6K7VClzXwDXab51jCd8Nd36CNM+zR97ScQ==} + engines: {node: '>=16'} + + read-pkg@9.0.1: + resolution: {integrity: sha512-9viLL4/n1BJUCT1NXVTdS1jtm80yDEgR5T4yCelII49Mbj0v1rZdKqj7zCiYdbB0CuCgdrvHcNogAKTFPBocFA==} + engines: {node: '>=18'} + + read-yaml-file@2.1.0: + resolution: {integrity: sha512-UkRNRIwnhG+y7hpqnycCL/xbTk7+ia9VuVTC0S+zVbwd65DI9eUpRMfsWIGrCWxTU/mi+JW8cHQCrv+zfCbEPQ==} + engines: {node: '>=10.13'} + + readable-stream@2.3.8: + resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} + + readable-stream@3.6.2: + resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} + engines: {node: '>= 6'} + + readdir-glob@1.1.3: + resolution: {integrity: sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA==} + + readdirp@4.0.2: + resolution: {integrity: sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==} + engines: {node: '>= 14.16.0'} + + realpath-missing@1.1.0: + resolution: {integrity: sha512-wnWtnywepjg/eHIgWR97R7UuM5i+qHLA195qdN9UPKvcMqfn60+67S8sPPW3vDlSEfYHoFkKU8IvpCNty3zQvQ==} + engines: {node: '>=10'} + + redent@3.0.0: + resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==} + engines: {node: '>=8'} + + redeyed@2.1.1: + resolution: {integrity: sha512-FNpGGo1DycYAdnrKFxCMmKYgo/mILAqtRYbkdQD8Ep/Hk2PQ5+aEAEx+IU713RTDmuBaH0c8P5ZozurNu5ObRQ==} + + refa@0.12.1: + resolution: {integrity: sha512-J8rn6v4DBb2nnFqkqwy6/NnTYMcgLA+sLr0iIO41qpv0n+ngb7ksag2tMRl0inb1bbO/esUwzW1vbJi7K0sI0g==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + + reflect.getprototypeof@1.0.9: + resolution: {integrity: sha512-r0Ay04Snci87djAsI4U+WNRcSw5S4pOH7qFjd/veA5gC7TbqESR3tcj28ia95L/fYUDw11JKP7uqUKUAfVvV5Q==} + engines: {node: '>= 0.4'} + + regenerate-unicode-properties@10.2.0: + resolution: {integrity: sha512-DqHn3DwbmmPVzeKj9woBadqmXxLvQoQIwu7nopMc72ztvxVmVk2SBhSnx67zuye5TP+lJsb/TBQsjLKhnDf3MA==} + engines: {node: '>=4'} + + regenerate@1.4.2: + resolution: {integrity: sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==} + + regexp-ast-analysis@0.7.1: + resolution: {integrity: sha512-sZuz1dYW/ZsfG17WSAG7eS85r5a0dDsvg+7BiiYR5o6lKCAtUrEwdmRmaGF6rwVj3LcmAeYkOWKEPlbPzN3Y3A==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + + regexp.prototype.flags@1.5.3: + resolution: {integrity: sha512-vqlC04+RQoFalODCbCumG2xIOvapzVMHwsyIGM/SIE8fRhFFsXeH8/QQ+s0T0kDAhKc4k30s73/0ydkHQz6HlQ==} + engines: {node: '>= 0.4'} + + regexpu-core@6.2.0: + resolution: {integrity: sha512-H66BPQMrv+V16t8xtmq+UC0CBpiTBA60V8ibS1QVReIp8T1z8hwFxqcGzm9K6lgsN7sB5edVH8a+ze6Fqm4weA==} + engines: {node: '>=4'} + + registry-auth-token@4.2.2: + resolution: {integrity: sha512-PC5ZysNb42zpFME6D/XlIgtNGdTl8bBOCw90xQLVMpzuuubJKYDWFAEuUNc+Cn8Z8724tg2SDhDRrkVEsqfDMg==} + engines: {node: '>=6.0.0'} + + registry-auth-token@5.0.3: + resolution: {integrity: sha512-1bpc9IyC+e+CNFRaWyn77tk4xGG4PPUyfakSmA6F6cvUDjrm58dfyJ3II+9yb10EDkHoy1LaPSmHaWLOH3m6HA==} + engines: {node: '>=14'} + + registry-auth-token@5.1.0: + resolution: {integrity: sha512-GdekYuwLXLxMuFTwAPg5UKGLW/UXzQrZvH/Zj791BQif5T05T0RsaLfHc9q3ZOKi7n+BoprPD9mJ0O0k4xzUlw==} + engines: {node: '>=14'} + + registry-url@5.1.0: + resolution: {integrity: sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==} + engines: {node: '>=8'} + + registry-url@6.0.1: + resolution: {integrity: sha512-+crtS5QjFRqFCoQmvGduwYWEBng99ZvmFvF+cUJkGYF1L1BfU8C6Zp9T7f5vPAwyLkUExpvK+ANVZmGU49qi4Q==} + engines: {node: '>=12'} + + regjsgen@0.8.0: + resolution: {integrity: sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==} + + regjsparser@0.12.0: + resolution: {integrity: sha512-cnE+y8bz4NhMjISKbgeVJtqNbtf5QpjZP+Bslo+UqkIt9QPnX9q095eiRRASJG1/tz6dlNr6Z5NsBiWYokp6EQ==} + hasBin: true + + relateurl@0.2.7: + resolution: {integrity: sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==} + engines: {node: '>= 0.10'} + + release-plan@0.13.1: + resolution: {integrity: sha512-hvlQge4Q7xw3xo1amuJcxBN8TUKp0rDIb4a8aAIvN4nQDzqZxCnOG27gUotYE9Oh5ELpx8cXJnn61Lo9CzOgeA==} + hasBin: true + + require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + + require-from-string@2.0.2: + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} + engines: {node: '>=0.10.0'} + + requireindex@1.2.0: + resolution: {integrity: sha512-L9jEkOi3ASd9PYit2cwRfyppc9NoABujTP8/5gFcbERmo5jUoAKovIC3fsF17pkTnGsrByysqX+Kxd2OTNI1ww==} + engines: {node: '>=0.10.5'} + + requires-port@1.0.0: + resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==} + + resolve-alpn@1.2.1: + resolution: {integrity: sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==} + + resolve-from@4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + + resolve-from@5.0.0: + resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} + engines: {node: '>=8'} + + resolve-pkg-maps@1.0.0: + resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} + + resolve@1.22.10: + resolution: {integrity: sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==} + engines: {node: '>= 0.4'} + hasBin: true + + responselike@2.0.1: + resolution: {integrity: sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==} + + restore-cursor@2.0.0: + resolution: {integrity: sha512-6IzJLuGi4+R14vwagDHX+JrXmPVtPpn4mffDJ1UdR7/Edm87fl6yi8mMBIVvFtJaNTUvjughmW4hwLhRG7gC1Q==} + engines: {node: '>=4'} + + restore-cursor@5.1.0: + resolution: {integrity: sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==} + engines: {node: '>=18'} + + retry@0.12.0: + resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==} + engines: {node: '>= 4'} + + reusify@1.0.4: + resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + + rimraf@3.0.2: + resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} + deprecated: Rimraf versions prior to v4 are no longer supported + hasBin: true + + rimraf@5.0.10: + resolution: {integrity: sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==} + hasBin: true + + rimraf@6.0.1: + resolution: {integrity: sha512-9dkvaxAsk/xNXSJzMgFqqMCuFgt2+KsOFek3TMLfo8NCPfWpBmqwyNn5Y+NX56QUYfCtsyhF3ayiboEoUmJk/A==} + engines: {node: 20 || >=22} + hasBin: true + + rollup-plugin-dts@6.1.1: + resolution: {integrity: sha512-aSHRcJ6KG2IHIioYlvAOcEq6U99sVtqDDKVhnwt70rW6tsz3tv5OSjEiWcgzfsHdLyGXZ/3b/7b/+Za3Y6r1XA==} + engines: {node: '>=16'} + peerDependencies: + rollup: ^3.29.4 || ^4 + typescript: ^5.7.3 + + rollup-plugin-insert@1.3.2: + resolution: {integrity: sha512-oTlUJikRZ1dYW9Kg9LHbG0T8pKNboHvMI0VZZoOUbqYPHE7rrKERHlGd3xsHH6W1KTr9Fcl4+UgrjpVkveWgPA==} + engines: {node: '>=8.0.0'} + peerDependencies: + rollup: '*' + + rollup-plugin-polyfill-node@0.13.0: + resolution: {integrity: sha512-FYEvpCaD5jGtyBuBFcQImEGmTxDTPbiHjJdrYIp+mFIwgXiXabxvKUK7ZT9P31ozu2Tqm9llYQMRWsfvTMTAOw==} + peerDependencies: + rollup: ^1.20.0 || ^2.0.0 || ^3.0.0 || ^4.0.0 + + rollup-plugin-postcss@4.0.2: + resolution: {integrity: sha512-05EaY6zvZdmvPUDi3uCcAQoESDcYnv8ogJJQRp6V5kZ6J6P7uAVJlrTZcaaA20wTH527YTnKfkAoPxWI/jPp4w==} + engines: {node: '>=10'} + peerDependencies: + postcss: 8.x + + rollup-pluginutils@2.8.2: + resolution: {integrity: sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==} + + rollup@4.34.8: + resolution: {integrity: sha512-489gTVMzAYdiZHFVA/ig/iYFllCcWFHMvUHI1rpFmkoUtRlQxqh6/yiNqnYibjMZ2b/+FUQwldG+aLsEt6bglQ==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + + rollup@4.44.1: + resolution: {integrity: sha512-x8H8aPvD+xbl0Do8oez5f5o8eMS3trfCghc4HhLAnCkj7Vl0d1JWGs0UF/D886zLW2rOj2QymV/JcSSsw+XDNg==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + + run-applescript@7.0.0: + resolution: {integrity: sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==} + engines: {node: '>=18'} + + run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + + rxjs@6.6.7: + resolution: {integrity: sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==} + engines: {npm: '>=2.0.0'} + + rxjs@7.8.1: + resolution: {integrity: sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==} + + sade@1.8.1: + resolution: {integrity: sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==} + engines: {node: '>=6'} + + safe-array-concat@1.1.3: + resolution: {integrity: sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==} + engines: {node: '>=0.4'} + + safe-buffer@5.1.2: + resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} + + safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + + safe-execa@0.1.2: + resolution: {integrity: sha512-vdTshSQ2JsRCgT8eKZWNJIL26C6bVqy1SOmuCMlKHegVeo8KYRobRrefOdUq9OozSPUUiSxrylteeRmLOMFfWg==} + engines: {node: '>=12'} + + safe-identifier@0.4.2: + resolution: {integrity: sha512-6pNbSMW6OhAi9j+N8V+U715yBQsaWJ7eyEUaOrawX+isg5ZxhUlV1NipNtgaKHmFGiABwt+ZF04Ii+3Xjkg+8w==} + + safe-push-apply@1.0.0: + resolution: {integrity: sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==} + engines: {node: '>= 0.4'} + + safe-regex-test@1.1.0: + resolution: {integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==} + engines: {node: '>= 0.4'} + + safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + + scslre@0.3.0: + resolution: {integrity: sha512-3A6sD0WYP7+QrjbfNA2FN3FsOaGGFoekCVgTyypy53gPxhbkCIjtO6YWgdrfM+n/8sI8JeXZOIxsHjMTNxQ4nQ==} + engines: {node: ^14.0.0 || >=16.0.0} + + semver@5.7.2: + resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} + hasBin: true + + semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true + + semver@7.7.2: + resolution: {integrity: sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==} + engines: {node: '>=10'} + hasBin: true + + send@0.19.0: + resolution: {integrity: sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==} + engines: {node: '>= 0.8.0'} + + serialize-javascript@6.0.2: + resolution: {integrity: sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==} + + serve-static@1.16.2: + resolution: {integrity: sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==} + engines: {node: '>= 0.8.0'} + + set-blocking@2.0.0: + resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} + + set-function-length@1.2.2: + resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} + engines: {node: '>= 0.4'} + + set-function-name@2.0.2: + resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==} + engines: {node: '>= 0.4'} + + setprototypeof@1.2.0: + resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} + + shebang-command@1.2.0: + resolution: {integrity: sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==} + engines: {node: '>=0.10.0'} + + shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + + shebang-regex@1.0.0: + resolution: {integrity: sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==} + engines: {node: '>=0.10.0'} + + shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + + shellwords@0.1.1: + resolution: {integrity: sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==} + + side-channel-list@1.0.0: + resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==} + engines: {node: '>= 0.4'} + + side-channel-map@1.0.1: + resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==} + engines: {node: '>= 0.4'} + + side-channel-weakmap@1.0.2: + resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==} + engines: {node: '>= 0.4'} + + side-channel@1.1.0: + resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} + engines: {node: '>= 0.4'} + + siginfo@2.0.0: + resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} + + signal-exit@3.0.7: + resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + + signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + + silent-error@1.1.1: + resolution: {integrity: sha512-n4iEKyNcg4v6/jpb3c0/iyH2G1nzUNl7Gpqtn/mHIJK9S/q/7MCfoO4rwVOoO59qPFIc0hVHvMbiOJ0NdtxKKw==} + + simple-html-tokenizer@0.5.11: + resolution: {integrity: sha512-C2WEK/Z3HoSFbYq8tI7ni3eOo/NneSPRoPpcM7WdLjFOArFuyXEjAoCdOC3DgMfRyziZQ1hCNR4mrNdWEvD0og==} + + slash@3.0.0: + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} + engines: {node: '>=8'} + + slash@5.1.0: + resolution: {integrity: sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==} + engines: {node: '>=14.16'} + + slice-ansi@0.0.4: + resolution: {integrity: sha512-up04hB2hR92PgjpyU3y/eg91yIBILyjVY26NvvciY3EVVPjybkMszMpXQ9QAkcS3I5rtJBDLoTxxg+qvW8c7rw==} + engines: {node: '>=0.10.0'} + + slice-ansi@3.0.0: + resolution: {integrity: sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==} + engines: {node: '>=8'} + + slice-ansi@4.0.0: + resolution: {integrity: sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==} + engines: {node: '>=10'} + + smart-buffer@4.2.0: + resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==} + engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} + + smob@1.5.0: + resolution: {integrity: sha512-g6T+p7QO8npa+/hNx9ohv1E5pVCmWrVCUzUXJyLdMmftX6ER0oiWY/w9knEonLpnOp6b6FenKnMfR8gqwWdwig==} + + smol-toml@1.3.1: + resolution: {integrity: sha512-tEYNll18pPKHroYSmLLrksq233j021G0giwW7P3D24jC54pQ5W5BXMsQ/Mvw1OJCmEYDgY+lrzT+3nNUtoNfXQ==} + engines: {node: '>= 18'} + + socket.io-adapter@2.5.5: + resolution: {integrity: sha512-eLDQas5dzPgOWCk9GuuJC2lBqItuhKI4uxGgo9aIV7MYbk2h9Q6uULEh8WBzThoI7l+qU9Ast9fVUmkqPP9wYg==} + + socket.io-parser@4.2.4: + resolution: {integrity: sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==} + engines: {node: '>=10.0.0'} + + socket.io@4.8.1: + resolution: {integrity: sha512-oZ7iUCxph8WYRHHcjBEc9unw3adt5CmSNlppj/5Q4k2RIrhl8Z5yY2Xr4j9zj0+wzVZ0bxmYoGSzKJnRl6A4yg==} + engines: {node: '>=10.2.0'} + + socks-proxy-agent@6.2.1: + resolution: {integrity: sha512-a6KW9G+6B3nWZ1yB8G7pJwL3ggLy1uTzKAgCb7ttblwqdz9fMGJUuTy3uFzEP48FAs9FLILlmzDlE2JJhVQaXQ==} + engines: {node: '>= 10'} + + socks-proxy-agent@8.0.5: + resolution: {integrity: sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==} + engines: {node: '>= 14'} + + socks@2.8.3: + resolution: {integrity: sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==} + engines: {node: '>= 10.0.0', npm: '>= 3.0.0'} + + sort-keys@4.2.0: + resolution: {integrity: sha512-aUYIEU/UviqPgc8mHR6IW1EGxkAXpeRETYcrzg8cLAvUPZcpAlleSXHV2mY7G12GphSH6Gzv+4MMVSSkbdteHg==} + engines: {node: '>=8'} + + sort-keys@5.1.0: + resolution: {integrity: sha512-aSbHV0DaBcr7u0PVHXzM6NbZNAtrr9sF6+Qfs9UUVG7Ll3jQ6hHi8F/xqIIcn2rvIVbr0v/2zyjSdwSV47AgLQ==} + engines: {node: '>=12'} + + source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + engines: {node: '>=0.10.0'} + + source-map-support@0.5.21: + resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} + + source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + + sourcemap-codec@1.4.8: + resolution: {integrity: sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==} + deprecated: Please use @jridgewell/sourcemap-codec instead + + spawn-args@0.2.0: + resolution: {integrity: sha512-73BoniQDcRWgnLAf/suKH6V5H54gd1KLzwYN9FB6J/evqTV33htH9xwV/4BHek+++jzxpVlZQKKZkqstPQPmQg==} + + spdx-correct@3.2.0: + resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==} + + spdx-exceptions@2.5.0: + resolution: {integrity: sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==} + + spdx-expression-parse@3.0.1: + resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} + + spdx-license-ids@3.0.20: + resolution: {integrity: sha512-jg25NiDV/1fLtSgEgyvVyDunvaNHbuwF9lfNV17gSmPFAlYzdfNBlLtLzXTevwkPj7DhGbmN9VnmJIgLnhvaBw==} + + split2@3.2.2: + resolution: {integrity: sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==} + + sprintf-js@1.0.3: + resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + + sprintf-js@1.1.3: + resolution: {integrity: sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==} + + ssri@8.0.1: + resolution: {integrity: sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==} + engines: {node: '>= 8'} + + stable-hash@0.0.4: + resolution: {integrity: sha512-LjdcbuBeLcdETCrPn9i8AYAZ1eCtu4ECAWtP7UleOiZ9LzVxRzzUZEoZ8zB24nhkQnDWyET0I+3sWokSDS3E7g==} + + stable@0.1.8: + resolution: {integrity: sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==} + deprecated: 'Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility' + + stackback@0.0.2: + resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} + + stacktracey@2.1.8: + resolution: {integrity: sha512-Kpij9riA+UNg7TnphqjH7/CzctQ/owJGNbFkfEeve4Z4uxT5+JapVLFXcsurIfN34gnTWZNJ/f7NMG0E8JDzTw==} + + statuses@2.0.1: + resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} + engines: {node: '>= 0.8'} + + std-env@3.8.0: + resolution: {integrity: sha512-Bc3YwwCB+OzldMxOXJIIvC6cPRWr/LxOp48CdQTOkPyk/t4JWWJbrilwBd7RJzKV8QW7tJkcgAmeuLLJugl5/w==} + + stdin-discarder@0.2.2: + resolution: {integrity: sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==} + engines: {node: '>=18'} + + streamx@2.22.1: + resolution: {integrity: sha512-znKXEBxfatz2GBNK02kRnCXjV+AA4kjZIUxeWSr3UGirZMJfTE9uiwKHobnbgxWyL/JWro8tTq+vOqAK1/qbSA==} + + string-hash@1.1.3: + resolution: {integrity: sha512-kJUvRUFK49aub+a7T1nNE66EJbZBMnBgoC1UbCZ5n6bsZKBRga4KgBRTMn/pFkeCZSYtNeSyMxPDM0AXWELk2A==} + + string-length@4.0.2: + resolution: {integrity: sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==} + engines: {node: '>=10'} + + string-width@1.0.2: + resolution: {integrity: sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw==} + engines: {node: '>=0.10.0'} + + string-width@2.1.1: + resolution: {integrity: sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==} + engines: {node: '>=4'} + + string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + + string-width@5.1.2: + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} + engines: {node: '>=12'} + + string-width@7.2.0: + resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} + engines: {node: '>=18'} + + string.prototype.trim@1.2.10: + resolution: {integrity: sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==} + engines: {node: '>= 0.4'} + + string.prototype.trimend@1.0.9: + resolution: {integrity: sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==} + engines: {node: '>= 0.4'} + + string.prototype.trimstart@1.0.8: + resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==} + engines: {node: '>= 0.4'} + + string_decoder@1.1.1: + resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} + + string_decoder@1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + + strip-ansi@3.0.1: + resolution: {integrity: sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==} + engines: {node: '>=0.10.0'} + + strip-ansi@4.0.0: + resolution: {integrity: sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==} + engines: {node: '>=4'} + + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + + strip-ansi@7.1.0: + resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} + engines: {node: '>=12'} + + strip-bom@3.0.0: + resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} + engines: {node: '>=4'} + + strip-bom@4.0.0: + resolution: {integrity: sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==} + engines: {node: '>=8'} + + strip-comments-strings@1.2.0: + resolution: {integrity: sha512-zwF4bmnyEjZwRhaak9jUWNxc0DoeKBJ7lwSN/LEc8dQXZcUFG6auaaTQJokQWXopLdM3iTx01nQT8E4aL29DAQ==} + + strip-eof@1.0.0: + resolution: {integrity: sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==} + engines: {node: '>=0.10.0'} + + strip-final-newline@2.0.0: + resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} + engines: {node: '>=6'} + + strip-final-newline@3.0.0: + resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} + engines: {node: '>=12'} + + strip-final-newline@4.0.0: + resolution: {integrity: sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw==} + engines: {node: '>=18'} + + strip-indent@3.0.0: + resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} + engines: {node: '>=8'} + + strip-json-comments@2.0.1: + resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==} + engines: {node: '>=0.10.0'} + + strip-json-comments@3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + + strip-json-comments@5.0.1: + resolution: {integrity: sha512-0fk9zBqO67Nq5M/m45qHCJxylV/DhBlIOVExqgOMiCCrzrhU6tCibRXNqE3jwJLftzE9SNuZtYbpzcO+i9FiKw==} + engines: {node: '>=14.16'} + + style-inject@0.3.0: + resolution: {integrity: sha512-IezA2qp+vcdlhJaVm5SOdPPTUu0FCEqfNSli2vRuSIBbu5Nq5UvygTk/VzeCqfLz2Atj3dVII5QBKGZRZ0edzw==} + + styled_string@0.0.1: + resolution: {integrity: sha512-DU2KZiB6VbPkO2tGSqQ9n96ZstUPjW7X4sGO6V2m1myIQluX0p1Ol8BrA/l6/EesqhMqXOIXs3cJNOy1UuU2BA==} + + stylehacks@5.1.1: + resolution: {integrity: sha512-sBpcd5Hx7G6seo7b1LkpttvTz7ikD0LlH5RmdcBNb6fFR0Fl7LQwHDFr300q4cwUqi+IYrFGmsIHieMBfnN/Bw==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + sucrase@3.35.0: + resolution: {integrity: sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==} + engines: {node: '>=16 || 14 >=14.17'} + hasBin: true + + summary@2.1.0: + resolution: {integrity: sha512-nMIjMrd5Z2nuB2RZCKJfFMjgS3fygbeyGk9PxPPaJR1RIcyN9yn4A63Isovzm3ZtQuEkLBVgMdPup8UeLH7aQw==} + + supports-color@2.0.0: + resolution: {integrity: sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==} + engines: {node: '>=0.8.0'} + + supports-color@5.5.0: + resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} + engines: {node: '>=4'} + + supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + + supports-color@8.1.1: + resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} + engines: {node: '>=10'} + + supports-hyperlinks@2.3.0: + resolution: {integrity: sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==} + engines: {node: '>=8'} + + supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + + svgo@2.8.0: + resolution: {integrity: sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==} + engines: {node: '>=10.13.0'} + hasBin: true + + symbol-observable@1.2.0: + resolution: {integrity: sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==} + engines: {node: '>=0.10.0'} + + synckit@0.6.2: + resolution: {integrity: sha512-Vhf+bUa//YSTYKseDiiEuQmhGCoIF3CVBhunm3r/DQnYiGT4JssmnKQc44BIyOZRK2pKjXXAgbhfmbeoC9CJpA==} + engines: {node: '>=12.20'} + + table@6.9.0: + resolution: {integrity: sha512-9kY+CygyYM6j02t5YFHbNz2FN5QmYGv9zAjVp4lCDjlCw7amdckXlEt/bjMhUIfj4ThGRE4gCUH5+yGnNuPo5A==} + engines: {node: '>=10.0.0'} + + tap-parser@7.0.0: + resolution: {integrity: sha512-05G8/LrzqOOFvZhhAk32wsGiPZ1lfUrl+iV7+OkKgfofZxiceZWMHkKmow71YsyVQ8IvGBP2EjcIjE5gL4l5lA==} + hasBin: true + + tapable@2.2.1: + resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==} + engines: {node: '>=6'} + + tar-fs@3.1.0: + resolution: {integrity: sha512-5Mty5y/sOF1YWj1J6GiBodjlDc05CUR8PKXrsnFAiSG0xA+GHeWLovaZPYUDXkH/1iKRf2+M5+OrRgzC7O9b7w==} + + tar-stream@2.2.0: + resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==} + engines: {node: '>=6'} + + tar-stream@3.1.7: + resolution: {integrity: sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==} + + tar@6.2.1: + resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==} + engines: {node: '>=10'} + + terminal-link@3.0.0: + resolution: {integrity: sha512-flFL3m4wuixmf6IfhFJd1YPiLiMuxEc8uHRM1buzIeZPm22Au2pDqBJQgdo7n1WfPU1ONFGv7YDwpFBmHGF6lg==} + engines: {node: '>=12'} + + terser@5.37.0: + resolution: {integrity: sha512-B8wRRkmre4ERucLM/uXx4MOV5cbnOlVAqUst+1+iLKPI0dOgFO28f84ptoQt9HEI537PMzfYa/d+GEPKTRXmYA==} + engines: {node: '>=10'} + hasBin: true + + terser@5.43.1: + resolution: {integrity: sha512-+6erLbBm0+LROX2sPXlUYx/ux5PyE9K/a92Wrt6oA+WDAoFTdpHE5tCYCI5PNzq2y8df4rA+QgHLJuR4jNymsg==} + engines: {node: '>=10'} + hasBin: true + + testem-failure-only-reporter@1.0.0: + resolution: {integrity: sha512-G3fC1FSW/mI2ElrzaJfGEtTHBB7U1IFimwC1oIpUc1+wYsgw+2tCUV1t+cB/dsBbryq4Cbe1NQ397fJ2maCs7g==} + + testem@3.15.2: + resolution: {integrity: sha512-mRzqZktqTCWi/rUP/RQOKXvMtuvY3lxuzBVb1xGXPnRNGMEj/1DaLGn6X447yOsz6SlWxSsZfcNuiE7fT1MOKg==} + engines: {node: '>= 7.*'} + hasBin: true + + text-decoder@1.2.3: + resolution: {integrity: sha512-3/o9z3X0X0fTupwsYvR03pJ/DjWuqqrfwBgTQzdWDiQSm9KitAyz/9WqsT2JQW7KV2m+bC2ol/zqpW37NHxLaA==} + + thenify-all@1.6.0: + resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} + engines: {node: '>=0.8'} + + thenify@3.3.1: + resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} + + through2@4.0.2: + resolution: {integrity: sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==} + + through@2.3.8: + resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} + + tiny-glob@0.2.9: + resolution: {integrity: sha512-g/55ssRPUjShh+xkfx9UPDXqhckHEsHr4Vd9zX55oSdGZc/MD0m3sferOkwWtp98bv+kcVfEHtRJgBVJzelrzg==} + + tinybench@2.9.0: + resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} + + tinyexec@0.3.2: + resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==} + + tinyglobby@0.2.12: + resolution: {integrity: sha512-qkf4trmKSIiMTs/E63cxH+ojC2unam7rJ0WrauAzpT3ECNTxGRMlaXxVbfxMUC/w0LaYk6jQ4y/nGR9uBO3tww==} + engines: {node: '>=12.0.0'} + + tinyglobby@0.2.14: + resolution: {integrity: sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==} + engines: {node: '>=12.0.0'} + + tinypool@1.0.2: + resolution: {integrity: sha512-al6n+QEANGFOMf/dmUMsuS5/r9B06uwlyNjZZql/zv8J7ybHCgoihBNORZCY2mzUuAnomQa2JdhyHKzZxPCrFA==} + engines: {node: ^18.0.0 || >=20.0.0} + + tinyrainbow@2.0.0: + resolution: {integrity: sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==} + engines: {node: '>=14.0.0'} + + tinyspy@3.0.2: + resolution: {integrity: sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==} + engines: {node: '>=14.0.0'} + + tmp@0.0.33: + resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} + engines: {node: '>=0.6.0'} + + tmp@0.2.3: + resolution: {integrity: sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==} + engines: {node: '>=14.14'} + + to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + + toidentifier@1.0.1: + resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} + engines: {node: '>=0.6'} + + toml@3.0.0: + resolution: {integrity: sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w==} + + tough-cookie@4.1.4: + resolution: {integrity: sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==} + engines: {node: '>=6'} + + tracerbench@8.0.1: + resolution: {integrity: sha512-IQwfb6cJbdk0t0p7MGt1NjrmKr+QNmtW2MbaN1cRmd89r2P9fXUnLVXdsItGkq0Sgg6SGHi5dqDDTptgsRquSw==} + engines: {node: '>=14.0.0'} + hasBin: true + + trim-newlines@3.0.1: + resolution: {integrity: sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==} + engines: {node: '>=8'} + + ts-api-utils@2.0.1: + resolution: {integrity: sha512-dnlgjFSVetynI8nzgJ+qF62efpglpWRk8isUEWZGWlJYySCTD6aKvbUDu+zbPeDakk3bg5H4XpitHukgfL1m9w==} + engines: {node: '>=18.12'} + peerDependencies: + typescript: ^5.7.3 + + ts-api-utils@2.1.0: + resolution: {integrity: sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==} + engines: {node: '>=18.12'} + peerDependencies: + typescript: ^5.7.3 + + ts-interface-checker@0.1.13: + resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} + + ts-node@10.9.2: + resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==} + hasBin: true + peerDependencies: + '@swc/core': '>=1.2.50' + '@swc/wasm': '>=1.2.50' + '@types/node': ^22.13.4 + typescript: ^5.7.3 + peerDependenciesMeta: + '@swc/core': + optional: true + '@swc/wasm': + optional: true + + tsconfig-paths@3.15.0: + resolution: {integrity: sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==} + + tslib@1.14.1: + resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} + + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + + tsx@3.14.0: + resolution: {integrity: sha512-xHtFaKtHxM9LOklMmJdI3BEnQq/D5F73Of2E1GDrITi9sgoVkvIsrQUTY1G8FlmGtA+awCI4EBlTRRYxkL2sRg==} + hasBin: true + + tsx@4.19.2: + resolution: {integrity: sha512-pOUl6Vo2LUq/bSa8S5q7b91cgNSjctn9ugq/+Mvow99qW6x/UZYwzxy/3NmqoT66eHYfCVvFvACC58UBPFf28g==} + engines: {node: '>=18.0.0'} + hasBin: true + + tunnel-agent@0.6.0: + resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==} + + turbo-darwin-64@2.4.2: + resolution: {integrity: sha512-HFfemyWB60CJtEvVQj9yby5rkkWw9fLAdLtAPGtPQoU3tKh8t/uzCAZKso2aPVbib9vGUuGbPGoGpaRXdVhj5g==} + cpu: [x64] + os: [darwin] + + turbo-darwin-arm64@2.4.2: + resolution: {integrity: sha512-uwSx1dsBSSFeEC0nxyx2O219FEsS/haiESaWwE9JI8mHkQK61s6w6fN2G586krKxyNam4AIxRltleL+O2Em94g==} + cpu: [arm64] + os: [darwin] + + turbo-linux-64@2.4.2: + resolution: {integrity: sha512-Fy/uL8z/LAYcPbm7a1LwFnTY9pIi5FAi12iuHsgB7zHjdh4eeIKS2NIg4nroAmTcUTUZ0/cVTo4bDOCUcS3aKw==} + cpu: [x64] + os: [linux] + + turbo-linux-arm64@2.4.2: + resolution: {integrity: sha512-AEA0d8h5W/K6iiXfEgiNwWt0yqRL1NpBs8zQCLdc4/L7WeYeJW3sORWX8zt7xhutF/KW9gTm8ehKpiK6cCIsAA==} + cpu: [arm64] + os: [linux] + + turbo-windows-64@2.4.2: + resolution: {integrity: sha512-CybtIZ9wRgnnNFVN9En9G+rxsO+mwU81fvW4RpE8BWyNEkhQ8J28qYf4PaimueMxGHHp/28i/G7Kcdn2GAWG0g==} + cpu: [x64] + os: [win32] + + turbo-windows-arm64@2.4.2: + resolution: {integrity: sha512-7V0yneVPL8Y3TgrkUIjw7Odmwu1tHnyIiPHFM7eFcA7U+H6hPXyCxge7nC3wOKfjhKCQqUm+Vf/k6kjmLz5G4g==} + cpu: [arm64] + os: [win32] + + turbo@2.4.2: + resolution: {integrity: sha512-Qxi0ioQCxMRUCcHKHZkTnYH8e7XCpNfg9QiJcyfWIc+ZXeaCjzV5rCGlbQlTXMAtI8qgfP8fZADv3CFtPwqdPQ==} + hasBin: true + + type-check@0.4.0: + resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} + engines: {node: '>= 0.8.0'} + + type-fest@0.18.1: + resolution: {integrity: sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==} + engines: {node: '>=10'} + + type-fest@0.20.2: + resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} + engines: {node: '>=10'} + + type-fest@0.21.3: + resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} + engines: {node: '>=10'} + + type-fest@0.6.0: + resolution: {integrity: sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==} + engines: {node: '>=8'} + + type-fest@0.8.1: + resolution: {integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==} + engines: {node: '>=8'} + + type-fest@1.4.0: + resolution: {integrity: sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==} + engines: {node: '>=10'} + + type-fest@3.13.1: + resolution: {integrity: sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==} + engines: {node: '>=14.16'} + + type-fest@4.35.0: + resolution: {integrity: sha512-2/AwEFQDFEy30iOLjrvHDIH7e4HEWH+f1Yl1bI5XMqzuoCUqwYCdxachgsgv0og/JdVZUhbfjcJAoHj5L1753A==} + engines: {node: '>=16'} + + type-fest@4.41.0: + resolution: {integrity: sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==} + engines: {node: '>=16'} + + type-is@1.6.18: + resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} + engines: {node: '>= 0.6'} + + typed-array-buffer@1.0.3: + resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==} + engines: {node: '>= 0.4'} + + typed-array-byte-length@1.0.3: + resolution: {integrity: sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==} + engines: {node: '>= 0.4'} + + typed-array-byte-offset@1.0.4: + resolution: {integrity: sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==} + engines: {node: '>= 0.4'} + + typed-array-length@1.0.7: + resolution: {integrity: sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==} + engines: {node: '>= 0.4'} + + typed-query-selector@2.12.0: + resolution: {integrity: sha512-SbklCd1F0EiZOyPiW192rrHZzZ5sBijB6xM+cpmrwDqObvdtunOHHIk9fCGsoK5JVIYXoyEp4iEdE3upFH3PAg==} + + typedarray-to-buffer@3.1.5: + resolution: {integrity: sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==} + + typescript-eslint@8.24.1: + resolution: {integrity: sha512-cw3rEdzDqBs70TIcb0Gdzbt6h11BSs2pS0yaq7hDWDBtCCSei1pPSUXE9qUdQ/Wm9NgFg8mKtMt1b8fTHIl1jA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: ^5.7.3 + + typescript@5.7.3: + resolution: {integrity: sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==} + engines: {node: '>=14.17'} + hasBin: true + + ufo@1.5.4: + resolution: {integrity: sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==} + + ufo@1.6.1: + resolution: {integrity: sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==} + + uglify-js@3.19.3: + resolution: {integrity: sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==} + engines: {node: '>=0.8.0'} + hasBin: true + + unbox-primitive@1.1.0: + resolution: {integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==} + engines: {node: '>= 0.4'} + + unbzip2-stream@1.4.3: + resolution: {integrity: sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==} + + uncrypto@0.1.3: + resolution: {integrity: sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==} + + underscore@1.13.7: + resolution: {integrity: sha512-GMXzWtsc57XAtguZgaQViUOzs0KTkk8ojr3/xAxXLITqf/3EMwxC0inyETfDFjH/Krbhuep0HNbbjI9i/q3F3g==} + + undici-types@6.20.0: + resolution: {integrity: sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==} + + unicode-canonical-property-names-ecmascript@2.0.1: + resolution: {integrity: sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==} + engines: {node: '>=4'} + + unicode-match-property-ecmascript@2.0.0: + resolution: {integrity: sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==} + engines: {node: '>=4'} + + unicode-match-property-value-ecmascript@2.2.0: + resolution: {integrity: sha512-4IehN3V/+kkr5YeSSDDQG8QLqO26XpL2XP3GQtqwlT/QYSECAwFztxVHjlbh0+gjJ3XmNLS0zDsbgs9jWKExLg==} + engines: {node: '>=4'} + + unicode-property-aliases-ecmascript@2.1.0: + resolution: {integrity: sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==} + engines: {node: '>=4'} + + unicorn-magic@0.1.0: + resolution: {integrity: sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==} + engines: {node: '>=18'} + + unicorn-magic@0.3.0: + resolution: {integrity: sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==} + engines: {node: '>=18'} + + unique-filename@1.1.1: + resolution: {integrity: sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==} + + unique-slug@2.0.2: + resolution: {integrity: sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==} + + unique-string@2.0.0: + resolution: {integrity: sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==} + engines: {node: '>=8'} + + universal-user-agent@7.0.2: + resolution: {integrity: sha512-0JCqzSKnStlRRQfCdowvqy3cy0Dvtlb8xecj/H8JFZuCze4rwjPZQOgvFvn0Ws/usCHQFGpyr+pB9adaGwXn4Q==} + + universalify@0.1.2: + resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} + engines: {node: '>= 4.0.0'} + + universalify@0.2.0: + resolution: {integrity: sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==} + engines: {node: '>= 4.0.0'} + + universalify@2.0.1: + resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} + engines: {node: '>= 10.0.0'} + + unpipe@1.0.0: + resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} + engines: {node: '>= 0.8'} + + unplugin-fonts@1.3.1: + resolution: {integrity: sha512-GmaJWPAWH6lBI4fP8xKdbMZJwTgsnr8PGJOfQE52jlod8QkqSO4M529Nox2L8zYapjB5hox2wCu4N3c/LOal/A==} + peerDependencies: + '@nuxt/kit': ^3.0.0 + vite: ^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 + peerDependenciesMeta: + '@nuxt/kit': + optional: true + + unplugin@2.0.0-beta.1: + resolution: {integrity: sha512-2qzQo5LN2DmUZXkWDHvGKLF5BP0WN+KthD6aPnPJ8plRBIjv4lh5O07eYcSxgO2znNw9s4MNhEO1sB+JDllDbQ==} + engines: {node: '>=18.12.0'} + + update-browserslist-db@1.1.3: + resolution: {integrity: sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + + uri-js@4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + + url-parse@1.5.10: + resolution: {integrity: sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==} + + util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + + util@0.10.4: + resolution: {integrity: sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==} + + utils-merge@1.0.1: + resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} + engines: {node: '>= 0.4.0'} + + uuid@8.3.2: + resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} + hasBin: true + + v8-compile-cache-lib@3.0.1: + resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} + + validate-npm-package-license@3.0.4: + resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} + + validate-npm-package-name@5.0.0: + resolution: {integrity: sha512-YuKoXDAhBYxY7SfOKxHBDoSyENFeW5VvIIQp2TGQuit8gpK6MnWaQelBKxso72DoxTZfZdcP3W90LqpSkgPzLQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + validate-npm-package-name@6.0.0: + resolution: {integrity: sha512-d7KLgL1LD3U3fgnvWEY1cQXoO/q6EQ1BSz48Sa149V/5zVTAbgmZIpyI8TRi6U9/JNyeYLlTKsEMPtLC27RFUg==} + engines: {node: ^18.17.0 || >=20.5.0} + + vary@1.1.2: + resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} + engines: {node: '>= 0.8'} + + vite-node@3.0.6: + resolution: {integrity: sha512-s51RzrTkXKJrhNbUzQRsarjmAae7VmMPAsRT7lppVpIg6mK3zGthP9Hgz0YQQKuNcF+Ii7DfYk3Fxz40jRmePw==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + hasBin: true + + vite@6.3.5: + resolution: {integrity: sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + hasBin: true + peerDependencies: + '@types/node': ^22.13.4 + jiti: '>=1.21.0' + less: '*' + lightningcss: ^1.21.0 + sass: '*' + sass-embedded: '*' + stylus: '*' + sugarss: '*' + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + '@types/node': + optional: true + jiti: + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: + optional: true + + vite@7.0.2: + resolution: {integrity: sha512-hxdyZDY1CM6SNpKI4w4lcUc3Mtkd9ej4ECWVHSMrOdSinVc2zYOAppHeGc/hzmRo3pxM5blMzkuWHOJA/3NiFw==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + peerDependencies: + '@types/node': ^22.13.4 + jiti: '>=1.21.0' + less: ^4.0.0 + lightningcss: ^1.21.0 + sass: ^1.70.0 + sass-embedded: ^1.70.0 + stylus: '>=0.54.8' + sugarss: ^5.0.0 + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + '@types/node': + optional: true + jiti: + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: + optional: true + + vitest@3.0.6: + resolution: {integrity: sha512-/iL1Sc5VeDZKPDe58oGK4HUFLhw6b5XdY1MYawjuSaDA4sEfYlY9HnS6aCEG26fX+MgUi7MwlduTBHHAI/OvMA==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + hasBin: true + peerDependencies: + '@edge-runtime/vm': '*' + '@types/debug': ^4.1.12 + '@types/node': ^22.13.4 + '@vitest/browser': 3.0.6 + '@vitest/ui': 3.0.6 + happy-dom: '*' + jsdom: '*' + peerDependenciesMeta: + '@edge-runtime/vm': + optional: true + '@types/debug': + optional: true + '@types/node': + optional: true + '@vitest/browser': + optional: true + '@vitest/ui': + optional: true + happy-dom: + optional: true + jsdom: + optional: true + + wcwidth@1.0.1: + resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} + + webpack-virtual-modules@0.6.2: + resolution: {integrity: sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==} + + which-boxed-primitive@1.1.1: + resolution: {integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==} + engines: {node: '>= 0.4'} + + which-builtin-type@1.2.1: + resolution: {integrity: sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==} + engines: {node: '>= 0.4'} + + which-collection@1.0.2: + resolution: {integrity: sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==} + engines: {node: '>= 0.4'} + + which-typed-array@1.1.18: + resolution: {integrity: sha512-qEcY+KJYlWyLH9vNbsr6/5j59AXk5ni5aakf8ldzBvGde6Iz4sxZGkJyWSAueTG7QhOvNRYb1lDdFmL5Td0QKA==} + engines: {node: '>= 0.4'} + + which@1.3.1: + resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==} + hasBin: true + + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + + which@5.0.0: + resolution: {integrity: sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ==} + engines: {node: ^18.17.0 || >=20.5.0} + hasBin: true + + why-is-node-running@2.3.0: + resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} + engines: {node: '>=8'} + hasBin: true + + wide-align@1.1.5: + resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==} + + widest-line@3.1.0: + resolution: {integrity: sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==} + engines: {node: '>=8'} + + widest-line@5.0.0: + resolution: {integrity: sha512-c9bZp7b5YtRj2wOe6dlj32MK+Bx/M/d+9VB2SHM1OtsUHR0aV0tdP6DWh/iMt0kWi1t5g1Iudu6hQRNd1A4PVA==} + engines: {node: '>=18'} + + word-wrap@1.2.5: + resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} + engines: {node: '>=0.10.0'} + + wordwrap@1.0.0: + resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==} + + workerpool@9.3.3: + resolution: {integrity: sha512-slxCaKbYjEdFT/o2rH9xS1hf4uRDch1w7Uo+apxhZ+sf/1d9e0ZVkn42kPNGP2dgjIx6YFvSevj0zHvbWe2jdw==} + + wrap-ansi@3.0.1: + resolution: {integrity: sha512-iXR3tDXpbnTpzjKSylUJRkLuOrEC7hwEB221cgn6wtF8wpmz28puFXAEfPT5zrjM3wahygB//VuWEr1vTkDcNQ==} + engines: {node: '>=4'} + + wrap-ansi@6.2.0: + resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} + engines: {node: '>=8'} + + wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + + wrap-ansi@8.1.0: + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} + engines: {node: '>=12'} + + wrap-ansi@9.0.0: + resolution: {integrity: sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==} + engines: {node: '>=18'} + + wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + + write-file-atomic@3.0.3: + resolution: {integrity: sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==} + + write-file-atomic@5.0.1: + resolution: {integrity: sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + write-json-file@5.0.0: + resolution: {integrity: sha512-ddSsCLa4aQ3kI21BthINo4q905/wfhvQ3JL3774AcRjBaiQmfn5v4rw77jQ7T6CmAit9VOQO+FsLyPkwxoB1fw==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + write-pkg@7.0.0: + resolution: {integrity: sha512-wXBOrcEUstxZxfqy2hQO0O+c7wcwuVkZCCmBfaFtFssa5kcFqf7SQGYL6YtxKXt/O41z6reAPFJcumUyyiYnTQ==} + engines: {node: '>=16'} + deprecated: Renamed to write-package + + write-yaml-file@5.0.0: + resolution: {integrity: sha512-FdNA4RyH1L43TlvGG8qOMIfcEczwA5ij+zLXUy3Z83CjxhLvcV7/Q/8pk22wnCgYw7PJhtK+7lhO+qqyT4NdvQ==} + engines: {node: '>=16.14'} + + ws@7.5.10: + resolution: {integrity: sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==} + engines: {node: '>=8.3.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ^5.0.2 + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + + ws@8.17.1: + resolution: {integrity: sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + + ws@8.18.0: + resolution: {integrity: sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + + ws@8.18.3: + resolution: {integrity: sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + + y18n@5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + + yallist@3.1.1: + resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + + yallist@4.0.0: + resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + + yaml@1.10.2: + resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==} + engines: {node: '>= 6'} + + yaml@2.7.0: + resolution: {integrity: sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA==} + engines: {node: '>= 14'} + hasBin: true + + yargs-parser@20.2.4: + resolution: {integrity: sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==} + engines: {node: '>=10'} + + yargs-parser@20.2.9: + resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==} + engines: {node: '>=10'} + + yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + + yargs-unparser@2.0.0: + resolution: {integrity: sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==} + engines: {node: '>=10'} + + yargs@16.2.0: + resolution: {integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==} + engines: {node: '>=10'} + + yargs@17.7.2: + resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} + engines: {node: '>=12'} + + yauzl@2.10.0: + resolution: {integrity: sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==} + + yn@3.1.1: + resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} + engines: {node: '>=6'} + + yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + + yocto-queue@1.1.1: + resolution: {integrity: sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g==} + engines: {node: '>=12.20'} + + yoctocolors@2.1.1: + resolution: {integrity: sha512-GQHQqAopRhwU8Kt1DDM8NjibDXHC8eoh1erhGAJPEyveY9qqVeXvVikNKrDz69sHowPMorbPUrH/mx8c50eiBQ==} + engines: {node: '>=18'} + + zip-stream@4.1.1: + resolution: {integrity: sha512-9qv4rlDiopXg4E69k+vMHjNN63YFMe9sZMrdlvKnCjlCRWeCBswPPMPUfx+ipsAWq1LXHe70RcbaHdJJpS6hyQ==} + engines: {node: '>= 10'} + + zod-validation-error@3.4.0: + resolution: {integrity: sha512-ZOPR9SVY6Pb2qqO5XHt+MkkTRxGXb4EVtnjc9JpXUOtUB1T9Ru7mZOT361AN3MsetVe7R0a1KZshJDZdgp9miQ==} + engines: {node: '>=18.0.0'} + peerDependencies: + zod: ^3.18.0 + + zod@3.23.8: + resolution: {integrity: sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==} + + zod@3.24.1: + resolution: {integrity: sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A==} + + zod@3.25.72: + resolution: {integrity: sha512-Cl+fe4dNL4XumOBNBsr0lHfA80PQiZXHI4xEMTEr8gt6aGz92t3lBA32e71j9+JeF/VAYvdfBnuwJs+BMx/BrA==} + + zx@8.3.2: + resolution: {integrity: sha512-qjTunv1NClO05jDaUjrNZfpqC9yvNCchge/bzOcQevsh1aM5qE3TG6MY24kuQKlOWx+7vNuhqO2wa9nQCIGvZA==} + engines: {node: '>= 12.17.0'} + hasBin: true + +snapshots: + + '@ampproject/remapping@2.3.0': + dependencies: + '@jridgewell/gen-mapping': 0.3.12 + '@jridgewell/trace-mapping': 0.3.29 + + '@babel/code-frame@7.26.2': + dependencies: + '@babel/helper-validator-identifier': 7.27.1 + js-tokens: 4.0.0 + picocolors: 1.1.1 + optional: true + + '@babel/code-frame@7.27.1': + dependencies: + '@babel/helper-validator-identifier': 7.27.1 + js-tokens: 4.0.0 + picocolors: 1.1.1 + + '@babel/compat-data@7.28.0': {} + + '@babel/core@7.26.0': + dependencies: + '@ampproject/remapping': 2.3.0 + '@babel/code-frame': 7.27.1 + '@babel/generator': 7.28.0 + '@babel/helper-compilation-targets': 7.27.2 + '@babel/helper-module-transforms': 7.27.3(@babel/core@7.26.0) + '@babel/helpers': 7.27.6 + '@babel/parser': 7.28.0 + '@babel/template': 7.27.2 + '@babel/traverse': 7.28.0 + '@babel/types': 7.28.0 + convert-source-map: 2.0.0 + debug: 4.4.1(supports-color@8.1.1) + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/generator@7.28.0': + dependencies: + '@babel/parser': 7.28.0 + '@babel/types': 7.28.0 + '@jridgewell/gen-mapping': 0.3.12 + '@jridgewell/trace-mapping': 0.3.29 + jsesc: 3.1.0 + + '@babel/helper-annotate-as-pure@7.27.3': + dependencies: + '@babel/types': 7.28.0 + + '@babel/helper-compilation-targets@7.27.2': + dependencies: + '@babel/compat-data': 7.28.0 + '@babel/helper-validator-option': 7.27.1 + browserslist: 4.25.1 + lru-cache: 5.1.1 + semver: 6.3.1 + + '@babel/helper-create-class-features-plugin@7.27.1(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-annotate-as-pure': 7.27.3 + '@babel/helper-member-expression-to-functions': 7.27.1 + '@babel/helper-optimise-call-expression': 7.27.1 + '@babel/helper-replace-supers': 7.27.1(@babel/core@7.26.0) + '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 + '@babel/traverse': 7.28.0 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/helper-create-regexp-features-plugin@7.27.1(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-annotate-as-pure': 7.27.3 + regexpu-core: 6.2.0 + semver: 6.3.1 + + '@babel/helper-define-polyfill-provider@0.6.5(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-compilation-targets': 7.27.2 + '@babel/helper-plugin-utils': 7.27.1 + debug: 4.4.1(supports-color@8.1.1) + lodash.debounce: 4.0.8 + resolve: 1.22.10 + transitivePeerDependencies: + - supports-color + + '@babel/helper-globals@7.28.0': {} + + '@babel/helper-member-expression-to-functions@7.27.1': + dependencies: + '@babel/traverse': 7.28.0 + '@babel/types': 7.28.0 + transitivePeerDependencies: + - supports-color + + '@babel/helper-module-imports@7.25.9': + dependencies: + '@babel/traverse': 7.28.0 + '@babel/types': 7.28.0 + transitivePeerDependencies: + - supports-color + + '@babel/helper-module-imports@7.27.1': + dependencies: + '@babel/traverse': 7.28.0 + '@babel/types': 7.28.0 + transitivePeerDependencies: + - supports-color + + '@babel/helper-module-transforms@7.27.3(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-module-imports': 7.27.1 + '@babel/helper-validator-identifier': 7.27.1 + '@babel/traverse': 7.28.0 + transitivePeerDependencies: + - supports-color + + '@babel/helper-optimise-call-expression@7.27.1': + dependencies: + '@babel/types': 7.28.0 + + '@babel/helper-plugin-utils@7.27.1': {} + + '@babel/helper-remap-async-to-generator@7.27.1(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-annotate-as-pure': 7.27.3 + '@babel/helper-wrap-function': 7.27.1 + '@babel/traverse': 7.28.0 + transitivePeerDependencies: + - supports-color + + '@babel/helper-replace-supers@7.27.1(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-member-expression-to-functions': 7.27.1 + '@babel/helper-optimise-call-expression': 7.27.1 + '@babel/traverse': 7.28.0 + transitivePeerDependencies: + - supports-color + + '@babel/helper-skip-transparent-expression-wrappers@7.27.1': + dependencies: + '@babel/traverse': 7.28.0 + '@babel/types': 7.28.0 + transitivePeerDependencies: + - supports-color + + '@babel/helper-string-parser@7.27.1': {} + + '@babel/helper-validator-identifier@7.27.1': {} + + '@babel/helper-validator-option@7.27.1': {} + + '@babel/helper-wrap-function@7.27.1': + dependencies: + '@babel/template': 7.27.2 + '@babel/traverse': 7.28.0 + '@babel/types': 7.28.0 + transitivePeerDependencies: + - supports-color + + '@babel/helpers@7.27.6': + dependencies: + '@babel/template': 7.27.2 + '@babel/types': 7.28.0 + + '@babel/parser@7.26.3': + dependencies: + '@babel/types': 7.28.0 + + '@babel/parser@7.28.0': + dependencies: + '@babel/types': 7.28.0 + + '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.27.1(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/traverse': 7.28.0 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-bugfix-safari-class-field-initializer-scope@7.27.1(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.27.1(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.27.1(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 + '@babel/plugin-transform-optional-chaining': 7.27.1(@babel/core@7.26.0) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.27.1(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/traverse': 7.28.0 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + + '@babel/plugin-syntax-dynamic-import@7.8.3(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-syntax-import-assertions@7.27.1(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-syntax-import-attributes@7.27.1(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-syntax-jsx@7.27.1(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-syntax-typescript@7.27.1(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-syntax-unicode-sets-regex@7.18.6(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.26.0) + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-arrow-functions@7.27.1(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-async-generator-functions@7.28.0(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-remap-async-to-generator': 7.27.1(@babel/core@7.26.0) + '@babel/traverse': 7.28.0 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-async-to-generator@7.27.1(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-module-imports': 7.27.1 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-remap-async-to-generator': 7.27.1(@babel/core@7.26.0) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-block-scoped-functions@7.27.1(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-block-scoping@7.28.0(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-class-properties@7.27.1(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-create-class-features-plugin': 7.27.1(@babel/core@7.26.0) + '@babel/helper-plugin-utils': 7.27.1 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-class-static-block@7.27.1(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-create-class-features-plugin': 7.27.1(@babel/core@7.26.0) + '@babel/helper-plugin-utils': 7.27.1 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-classes@7.28.0(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-annotate-as-pure': 7.27.3 + '@babel/helper-compilation-targets': 7.27.2 + '@babel/helper-globals': 7.28.0 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-replace-supers': 7.27.1(@babel/core@7.26.0) + '@babel/traverse': 7.28.0 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-computed-properties@7.27.1(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/template': 7.27.2 + + '@babel/plugin-transform-destructuring@7.28.0(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/traverse': 7.28.0 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-dotall-regex@7.27.1(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.26.0) + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-duplicate-keys@7.27.1(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.27.1(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.26.0) + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-dynamic-import@7.27.1(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-explicit-resource-management@7.28.0(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/plugin-transform-destructuring': 7.28.0(@babel/core@7.26.0) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-exponentiation-operator@7.27.1(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-export-namespace-from@7.27.1(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-for-of@7.27.1(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-function-name@7.27.1(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-compilation-targets': 7.27.2 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/traverse': 7.28.0 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-json-strings@7.27.1(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-literals@7.27.1(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-logical-assignment-operators@7.27.1(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-member-expression-literals@7.27.1(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-modules-amd@7.27.1(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-module-transforms': 7.27.3(@babel/core@7.26.0) + '@babel/helper-plugin-utils': 7.27.1 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-modules-commonjs@7.27.1(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-module-transforms': 7.27.3(@babel/core@7.26.0) + '@babel/helper-plugin-utils': 7.27.1 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-modules-systemjs@7.27.1(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-module-transforms': 7.27.3(@babel/core@7.26.0) + '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-validator-identifier': 7.27.1 + '@babel/traverse': 7.28.0 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-modules-umd@7.27.1(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-module-transforms': 7.27.3(@babel/core@7.26.0) + '@babel/helper-plugin-utils': 7.27.1 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-named-capturing-groups-regex@7.27.1(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.26.0) + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-new-target@7.27.1(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-nullish-coalescing-operator@7.27.1(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-numeric-separator@7.27.1(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-object-rest-spread@7.28.0(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-compilation-targets': 7.27.2 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/plugin-transform-destructuring': 7.28.0(@babel/core@7.26.0) + '@babel/plugin-transform-parameters': 7.27.7(@babel/core@7.26.0) + '@babel/traverse': 7.28.0 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-object-super@7.27.1(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-replace-supers': 7.27.1(@babel/core@7.26.0) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-optional-catch-binding@7.27.1(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-optional-chaining@7.27.1(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-parameters@7.27.7(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-private-methods@7.27.1(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-create-class-features-plugin': 7.27.1(@babel/core@7.26.0) + '@babel/helper-plugin-utils': 7.27.1 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-private-property-in-object@7.27.1(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-annotate-as-pure': 7.27.3 + '@babel/helper-create-class-features-plugin': 7.27.1(@babel/core@7.26.0) + '@babel/helper-plugin-utils': 7.27.1 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-property-literals@7.27.1(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-regenerator@7.28.0(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-regexp-modifiers@7.27.1(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.26.0) + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-reserved-words@7.27.1(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-runtime@7.28.0(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-module-imports': 7.27.1 + '@babel/helper-plugin-utils': 7.27.1 + babel-plugin-polyfill-corejs2: 0.4.14(@babel/core@7.26.0) + babel-plugin-polyfill-corejs3: 0.13.0(@babel/core@7.26.0) + babel-plugin-polyfill-regenerator: 0.6.5(@babel/core@7.26.0) + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-shorthand-properties@7.27.1(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-spread@7.27.1(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-sticky-regex@7.27.1(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-template-literals@7.27.1(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-typeof-symbol@7.27.1(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-typescript@7.28.0(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-annotate-as-pure': 7.27.3 + '@babel/helper-create-class-features-plugin': 7.27.1(@babel/core@7.26.0) + '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 + '@babel/plugin-syntax-typescript': 7.27.1(@babel/core@7.26.0) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-unicode-escapes@7.27.1(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-unicode-property-regex@7.27.1(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.26.0) + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-unicode-regex@7.27.1(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.26.0) + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-unicode-sets-regex@7.27.1(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.26.0) + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/preset-env@7.28.0(@babel/core@7.26.0)': + dependencies: + '@babel/compat-data': 7.28.0 + '@babel/core': 7.26.0 + '@babel/helper-compilation-targets': 7.27.2 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-validator-option': 7.27.1 + '@babel/plugin-bugfix-firefox-class-in-computed-class-key': 7.27.1(@babel/core@7.26.0) + '@babel/plugin-bugfix-safari-class-field-initializer-scope': 7.27.1(@babel/core@7.26.0) + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.27.1(@babel/core@7.26.0) + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.27.1(@babel/core@7.26.0) + '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly': 7.27.1(@babel/core@7.26.0) + '@babel/plugin-proposal-private-property-in-object': 7.21.0-placeholder-for-preset-env.2(@babel/core@7.26.0) + '@babel/plugin-syntax-import-assertions': 7.27.1(@babel/core@7.26.0) + '@babel/plugin-syntax-import-attributes': 7.27.1(@babel/core@7.26.0) + '@babel/plugin-syntax-unicode-sets-regex': 7.18.6(@babel/core@7.26.0) + '@babel/plugin-transform-arrow-functions': 7.27.1(@babel/core@7.26.0) + '@babel/plugin-transform-async-generator-functions': 7.28.0(@babel/core@7.26.0) + '@babel/plugin-transform-async-to-generator': 7.27.1(@babel/core@7.26.0) + '@babel/plugin-transform-block-scoped-functions': 7.27.1(@babel/core@7.26.0) + '@babel/plugin-transform-block-scoping': 7.28.0(@babel/core@7.26.0) + '@babel/plugin-transform-class-properties': 7.27.1(@babel/core@7.26.0) + '@babel/plugin-transform-class-static-block': 7.27.1(@babel/core@7.26.0) + '@babel/plugin-transform-classes': 7.28.0(@babel/core@7.26.0) + '@babel/plugin-transform-computed-properties': 7.27.1(@babel/core@7.26.0) + '@babel/plugin-transform-destructuring': 7.28.0(@babel/core@7.26.0) + '@babel/plugin-transform-dotall-regex': 7.27.1(@babel/core@7.26.0) + '@babel/plugin-transform-duplicate-keys': 7.27.1(@babel/core@7.26.0) + '@babel/plugin-transform-duplicate-named-capturing-groups-regex': 7.27.1(@babel/core@7.26.0) + '@babel/plugin-transform-dynamic-import': 7.27.1(@babel/core@7.26.0) + '@babel/plugin-transform-explicit-resource-management': 7.28.0(@babel/core@7.26.0) + '@babel/plugin-transform-exponentiation-operator': 7.27.1(@babel/core@7.26.0) + '@babel/plugin-transform-export-namespace-from': 7.27.1(@babel/core@7.26.0) + '@babel/plugin-transform-for-of': 7.27.1(@babel/core@7.26.0) + '@babel/plugin-transform-function-name': 7.27.1(@babel/core@7.26.0) + '@babel/plugin-transform-json-strings': 7.27.1(@babel/core@7.26.0) + '@babel/plugin-transform-literals': 7.27.1(@babel/core@7.26.0) + '@babel/plugin-transform-logical-assignment-operators': 7.27.1(@babel/core@7.26.0) + '@babel/plugin-transform-member-expression-literals': 7.27.1(@babel/core@7.26.0) + '@babel/plugin-transform-modules-amd': 7.27.1(@babel/core@7.26.0) + '@babel/plugin-transform-modules-commonjs': 7.27.1(@babel/core@7.26.0) + '@babel/plugin-transform-modules-systemjs': 7.27.1(@babel/core@7.26.0) + '@babel/plugin-transform-modules-umd': 7.27.1(@babel/core@7.26.0) + '@babel/plugin-transform-named-capturing-groups-regex': 7.27.1(@babel/core@7.26.0) + '@babel/plugin-transform-new-target': 7.27.1(@babel/core@7.26.0) + '@babel/plugin-transform-nullish-coalescing-operator': 7.27.1(@babel/core@7.26.0) + '@babel/plugin-transform-numeric-separator': 7.27.1(@babel/core@7.26.0) + '@babel/plugin-transform-object-rest-spread': 7.28.0(@babel/core@7.26.0) + '@babel/plugin-transform-object-super': 7.27.1(@babel/core@7.26.0) + '@babel/plugin-transform-optional-catch-binding': 7.27.1(@babel/core@7.26.0) + '@babel/plugin-transform-optional-chaining': 7.27.1(@babel/core@7.26.0) + '@babel/plugin-transform-parameters': 7.27.7(@babel/core@7.26.0) + '@babel/plugin-transform-private-methods': 7.27.1(@babel/core@7.26.0) + '@babel/plugin-transform-private-property-in-object': 7.27.1(@babel/core@7.26.0) + '@babel/plugin-transform-property-literals': 7.27.1(@babel/core@7.26.0) + '@babel/plugin-transform-regenerator': 7.28.0(@babel/core@7.26.0) + '@babel/plugin-transform-regexp-modifiers': 7.27.1(@babel/core@7.26.0) + '@babel/plugin-transform-reserved-words': 7.27.1(@babel/core@7.26.0) + '@babel/plugin-transform-shorthand-properties': 7.27.1(@babel/core@7.26.0) + '@babel/plugin-transform-spread': 7.27.1(@babel/core@7.26.0) + '@babel/plugin-transform-sticky-regex': 7.27.1(@babel/core@7.26.0) + '@babel/plugin-transform-template-literals': 7.27.1(@babel/core@7.26.0) + '@babel/plugin-transform-typeof-symbol': 7.27.1(@babel/core@7.26.0) + '@babel/plugin-transform-unicode-escapes': 7.27.1(@babel/core@7.26.0) + '@babel/plugin-transform-unicode-property-regex': 7.27.1(@babel/core@7.26.0) + '@babel/plugin-transform-unicode-regex': 7.27.1(@babel/core@7.26.0) + '@babel/plugin-transform-unicode-sets-regex': 7.27.1(@babel/core@7.26.0) + '@babel/preset-modules': 0.1.6-no-external-plugins(@babel/core@7.26.0) + babel-plugin-polyfill-corejs2: 0.4.14(@babel/core@7.26.0) + babel-plugin-polyfill-corejs3: 0.13.0(@babel/core@7.26.0) + babel-plugin-polyfill-regenerator: 0.6.5(@babel/core@7.26.0) + core-js-compat: 3.43.0 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/preset-modules@0.1.6-no-external-plugins(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/types': 7.28.0 + esutils: 2.0.3 + + '@babel/preset-typescript@7.27.1(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-validator-option': 7.27.1 + '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.26.0) + '@babel/plugin-transform-modules-commonjs': 7.27.1(@babel/core@7.26.0) + '@babel/plugin-transform-typescript': 7.28.0(@babel/core@7.26.0) + transitivePeerDependencies: + - supports-color + + '@babel/runtime@7.27.6': {} + + '@babel/template@7.27.2': + dependencies: + '@babel/code-frame': 7.27.1 + '@babel/parser': 7.28.0 + '@babel/types': 7.28.0 + + '@babel/traverse@7.28.0': + dependencies: + '@babel/code-frame': 7.27.1 + '@babel/generator': 7.28.0 + '@babel/helper-globals': 7.28.0 + '@babel/parser': 7.28.0 + '@babel/template': 7.27.2 + '@babel/types': 7.28.0 + debug: 4.4.0 + transitivePeerDependencies: + - supports-color + + '@babel/types@7.28.0': + dependencies: + '@babel/helper-string-parser': 7.27.1 + '@babel/helper-validator-identifier': 7.27.1 + + '@colors/colors@1.5.0': + optional: true + + '@cspotcode/source-map-support@0.8.1': + dependencies: + '@jridgewell/trace-mapping': 0.3.9 + + '@esbuild/aix-ppc64@0.25.5': + optional: true + + '@esbuild/android-arm64@0.25.5': + optional: true + + '@esbuild/android-arm@0.25.5': + optional: true + + '@esbuild/android-x64@0.25.5': + optional: true + + '@esbuild/darwin-arm64@0.25.5': + optional: true + + '@esbuild/darwin-x64@0.25.5': + optional: true + + '@esbuild/freebsd-arm64@0.25.5': + optional: true + + '@esbuild/freebsd-x64@0.25.5': + optional: true + + '@esbuild/linux-arm64@0.25.5': + optional: true + + '@esbuild/linux-arm@0.25.5': + optional: true + + '@esbuild/linux-ia32@0.25.5': + optional: true + + '@esbuild/linux-loong64@0.25.5': + optional: true + + '@esbuild/linux-mips64el@0.25.5': + optional: true + + '@esbuild/linux-ppc64@0.25.5': + optional: true + + '@esbuild/linux-riscv64@0.25.5': + optional: true + + '@esbuild/linux-s390x@0.25.5': + optional: true + + '@esbuild/linux-x64@0.25.5': + optional: true + + '@esbuild/netbsd-arm64@0.25.5': + optional: true + + '@esbuild/netbsd-x64@0.25.5': + optional: true + + '@esbuild/openbsd-arm64@0.25.5': + optional: true + + '@esbuild/openbsd-x64@0.25.5': + optional: true + + '@esbuild/sunos-x64@0.25.5': + optional: true + + '@esbuild/win32-arm64@0.25.5': + optional: true + + '@esbuild/win32-ia32@0.25.5': + optional: true + + '@esbuild/win32-x64@0.25.5': + optional: true + + '@eslint-community/eslint-plugin-eslint-comments@4.5.0(eslint@9.20.1(jiti@2.4.2))': + dependencies: + escape-string-regexp: 4.0.0 + eslint: 9.20.1(jiti@2.4.2) + ignore: 5.3.2 + + '@eslint-community/eslint-utils@4.4.1(eslint@9.20.1(jiti@2.4.2))': + dependencies: + eslint: 9.20.1(jiti@2.4.2) + eslint-visitor-keys: 3.4.3 + + '@eslint-community/eslint-utils@4.7.0(eslint@9.20.1(jiti@2.4.2))': + dependencies: + eslint: 9.20.1(jiti@2.4.2) + eslint-visitor-keys: 3.4.3 + + '@eslint-community/regexpp@4.12.1': {} + + '@eslint/compat@1.2.5(eslint@9.20.1(jiti@2.4.2))': + optionalDependencies: + eslint: 9.20.1(jiti@2.4.2) + + '@eslint/config-array@0.19.1': + dependencies: + '@eslint/object-schema': 2.1.5 + debug: 4.4.0 + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color + + '@eslint/config-inspector@1.1.0(eslint@9.20.1(jiti@2.4.2))': + dependencies: + '@nodelib/fs.walk': 3.0.1 + ansis: 4.1.0 + bundle-require: 5.1.0(esbuild@0.25.5) + cac: 6.7.14 + chokidar: 4.0.3 + debug: 4.4.1(supports-color@8.1.1) + esbuild: 0.25.5 + eslint: 9.20.1(jiti@2.4.2) + find-up: 7.0.0 + get-port-please: 3.1.2 + h3: 1.15.3 + mlly: 1.7.4 + mrmime: 2.0.1 + open: 10.1.2 + tinyglobby: 0.2.14 + ws: 8.18.3 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + '@eslint/core@0.10.0': + dependencies: + '@types/json-schema': 7.0.15 + + '@eslint/core@0.11.0': + dependencies: + '@types/json-schema': 7.0.15 + + '@eslint/eslintrc@3.2.0': + dependencies: + ajv: 6.12.6 + debug: 4.4.0 + espree: 10.3.0 + globals: 14.0.0 + ignore: 5.3.2 + import-fresh: 3.3.0 + js-yaml: 4.1.0 + minimatch: 3.1.2 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + + '@eslint/js@9.20.0': {} + + '@eslint/object-schema@2.1.5': {} + + '@eslint/plugin-kit@0.2.5': + dependencies: + '@eslint/core': 0.10.0 + levn: 0.4.1 + + '@gar/promisify@1.1.3': {} + + '@glimmer/env@0.1.7': {} + + '@gwhitney/detect-indent@7.0.1': {} + + '@handlebars/parser@2.2.0': {} + + '@humanfs/core@0.19.1': {} + + '@humanfs/node@0.16.6': + dependencies: + '@humanfs/core': 0.19.1 + '@humanwhocodes/retry': 0.3.1 + + '@humanwhocodes/module-importer@1.0.1': {} + + '@humanwhocodes/retry@0.3.1': {} + + '@humanwhocodes/retry@0.4.1': {} + + '@isaacs/cliui@8.0.2': + dependencies: + string-width: 5.1.2 + string-width-cjs: string-width@4.2.3 + strip-ansi: 7.1.0 + strip-ansi-cjs: strip-ansi@6.0.1 + wrap-ansi: 8.1.0 + wrap-ansi-cjs: wrap-ansi@7.0.0 + + '@jridgewell/gen-mapping@0.3.12': + dependencies: + '@jridgewell/sourcemap-codec': 1.5.4 + '@jridgewell/trace-mapping': 0.3.29 + + '@jridgewell/gen-mapping@0.3.8': + dependencies: + '@jridgewell/set-array': 1.2.1 + '@jridgewell/sourcemap-codec': 1.5.0 + '@jridgewell/trace-mapping': 0.3.25 + + '@jridgewell/resolve-uri@3.1.2': {} + + '@jridgewell/set-array@1.2.1': {} + + '@jridgewell/source-map@0.3.10': + dependencies: + '@jridgewell/gen-mapping': 0.3.12 + '@jridgewell/trace-mapping': 0.3.29 + + '@jridgewell/source-map@0.3.6': + dependencies: + '@jridgewell/gen-mapping': 0.3.8 + '@jridgewell/trace-mapping': 0.3.25 + + '@jridgewell/sourcemap-codec@1.5.0': {} + + '@jridgewell/sourcemap-codec@1.5.4': {} + + '@jridgewell/trace-mapping@0.3.25': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.0 + + '@jridgewell/trace-mapping@0.3.29': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.4 + + '@jridgewell/trace-mapping@0.3.9': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.4 + + '@manypkg/find-root@2.2.3': + dependencies: + '@manypkg/tools': 1.1.2 + + '@manypkg/get-packages@2.2.2': + dependencies: + '@manypkg/find-root': 2.2.3 + '@manypkg/tools': 1.1.2 + + '@manypkg/tools@1.1.2': + dependencies: + fast-glob: 3.3.3 + jju: 1.4.0 + js-yaml: 4.1.0 + + '@nodelib/fs.scandir@2.1.5': + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + + '@nodelib/fs.scandir@4.0.1': + dependencies: + '@nodelib/fs.stat': 4.0.0 + run-parallel: 1.2.0 + + '@nodelib/fs.stat@2.0.5': {} + + '@nodelib/fs.stat@4.0.0': {} + + '@nodelib/fs.walk@1.2.8': + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.18.0 + + '@nodelib/fs.walk@3.0.1': + dependencies: + '@nodelib/fs.scandir': 4.0.1 + fastq: 1.18.0 + + '@nolyfill/is-core-module@1.0.39': {} + + '@npmcli/fs@1.1.1': + dependencies: + '@gar/promisify': 1.1.3 + semver: 7.7.2 + + '@npmcli/git@6.0.3': + dependencies: + '@npmcli/promise-spawn': 8.0.2 + ini: 5.0.0 + lru-cache: 10.4.3 + npm-pick-manifest: 10.0.0 + proc-log: 5.0.0 + promise-retry: 2.0.1 + semver: 7.7.2 + which: 5.0.0 + + '@npmcli/move-file@1.1.2': + dependencies: + mkdirp: 1.0.4 + rimraf: 3.0.2 + + '@npmcli/package-json@6.1.1': + dependencies: + '@npmcli/git': 6.0.3 + glob: 10.4.5 + hosted-git-info: 8.0.2 + json-parse-even-better-errors: 4.0.0 + proc-log: 5.0.0 + semver: 7.7.2 + validate-npm-package-license: 3.0.4 + + '@npmcli/promise-spawn@8.0.2': + dependencies: + which: 5.0.0 + + '@oclif/command@1.8.36(@oclif/config@1.18.17)': + dependencies: + '@oclif/config': 1.18.17 + '@oclif/errors': 1.3.6 + '@oclif/help': 1.0.15 + '@oclif/parser': 3.8.17 + debug: 4.4.1(supports-color@8.1.1) + semver: 7.7.2 + transitivePeerDependencies: + - supports-color + + '@oclif/config@1.18.16': + dependencies: + '@oclif/errors': 1.3.6 + '@oclif/parser': 3.8.17 + debug: 4.4.1(supports-color@8.1.1) + globby: 11.1.0 + is-wsl: 2.2.0 + tslib: 2.8.1 + transitivePeerDependencies: + - supports-color + + '@oclif/config@1.18.17': + dependencies: + '@oclif/errors': 1.3.6 + '@oclif/parser': 3.8.17 + debug: 4.4.1(supports-color@8.1.1) + globby: 11.1.0 + is-wsl: 2.2.0 + tslib: 2.8.1 + transitivePeerDependencies: + - supports-color + + '@oclif/core@2.16.0(@swc/core@1.9.3)(@types/node@22.13.4)(typescript@5.7.3)': + dependencies: + '@types/cli-progress': 3.11.6 + ansi-escapes: 4.3.2 + ansi-styles: 4.3.0 + cardinal: 2.1.1 + chalk: 4.1.2 + clean-stack: 3.0.1 + cli-progress: 3.12.0 + debug: 4.4.1(supports-color@8.1.1) + ejs: 3.1.10 + get-package-type: 0.1.0 + globby: 11.1.0 + hyperlinker: 1.0.0 + indent-string: 4.0.0 + is-wsl: 2.2.0 + js-yaml: 3.14.1 + natural-orderby: 2.0.3 + object-treeify: 1.1.33 + password-prompt: 1.1.3 + slice-ansi: 4.0.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + supports-color: 8.1.1 + supports-hyperlinks: 2.3.0 + ts-node: 10.9.2(@swc/core@1.9.3)(@types/node@22.13.4)(typescript@5.7.3) + tslib: 2.8.1 + widest-line: 3.1.0 + wordwrap: 1.0.0 + wrap-ansi: 7.0.0 + transitivePeerDependencies: + - '@swc/core' + - '@swc/wasm' + - '@types/node' + - typescript + + '@oclif/core@4.4.1': + dependencies: + ansi-escapes: 4.3.2 + ansis: 3.17.0 + clean-stack: 3.0.1 + cli-spinners: 2.9.2 + debug: 4.4.1(supports-color@8.1.1) + ejs: 3.1.10 + get-package-type: 0.1.0 + indent-string: 4.0.0 + is-wsl: 2.2.0 + lilconfig: 3.1.3 + minimatch: 9.0.5 + semver: 7.7.2 + string-width: 4.2.3 + supports-color: 8.1.1 + tinyglobby: 0.2.14 + widest-line: 3.1.0 + wordwrap: 1.0.0 + wrap-ansi: 7.0.0 + + '@oclif/errors@1.3.6': + dependencies: + clean-stack: 3.0.1 + fs-extra: 8.1.0 + indent-string: 4.0.0 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + + '@oclif/help@1.0.15': + dependencies: + '@oclif/config': 1.18.16 + '@oclif/errors': 1.3.6 + chalk: 4.1.2 + indent-string: 4.0.0 + lodash: 4.17.21 + string-width: 4.2.3 + strip-ansi: 6.0.1 + widest-line: 3.1.0 + wrap-ansi: 6.2.0 + transitivePeerDependencies: + - supports-color + + '@oclif/linewrap@1.0.0': {} + + '@oclif/parser@3.8.17': + dependencies: + '@oclif/errors': 1.3.6 + '@oclif/linewrap': 1.0.0 + chalk: 4.1.2 + tslib: 2.8.1 + + '@oclif/plugin-help@5.2.20(@swc/core@1.9.3)(@types/node@22.13.4)(typescript@5.7.3)': + dependencies: + '@oclif/core': 2.16.0(@swc/core@1.9.3)(@types/node@22.13.4)(typescript@5.7.3) + transitivePeerDependencies: + - '@swc/core' + - '@swc/wasm' + - '@types/node' + - typescript + + '@oclif/plugin-warn-if-update-available@3.1.42': + dependencies: + '@oclif/core': 4.4.1 + ansis: 3.17.0 + debug: 4.4.1(supports-color@8.1.1) + http-call: 5.3.0 + lodash: 4.17.21 + registry-auth-token: 5.1.0 + transitivePeerDependencies: + - supports-color + + '@octokit/auth-token@5.1.2': {} + + '@octokit/core@6.1.4': + dependencies: + '@octokit/auth-token': 5.1.2 + '@octokit/graphql': 8.2.1 + '@octokit/request': 9.2.2 + '@octokit/request-error': 6.1.7 + '@octokit/types': 13.8.0 + before-after-hook: 3.0.2 + universal-user-agent: 7.0.2 + + '@octokit/endpoint@10.1.3': + dependencies: + '@octokit/types': 13.8.0 + universal-user-agent: 7.0.2 + + '@octokit/graphql@8.2.1': + dependencies: + '@octokit/request': 9.2.2 + '@octokit/types': 13.8.0 + universal-user-agent: 7.0.2 + + '@octokit/openapi-types@23.0.1': {} + + '@octokit/plugin-paginate-rest@11.4.3(@octokit/core@6.1.4)': + dependencies: + '@octokit/core': 6.1.4 + '@octokit/types': 13.8.0 + + '@octokit/plugin-request-log@5.3.1(@octokit/core@6.1.4)': + dependencies: + '@octokit/core': 6.1.4 + + '@octokit/plugin-rest-endpoint-methods@13.3.1(@octokit/core@6.1.4)': + dependencies: + '@octokit/core': 6.1.4 + '@octokit/types': 13.8.0 + + '@octokit/request-error@6.1.7': + dependencies: + '@octokit/types': 13.8.0 + + '@octokit/request@9.2.2': + dependencies: + '@octokit/endpoint': 10.1.3 + '@octokit/request-error': 6.1.7 + '@octokit/types': 13.8.0 + fast-content-type-parse: 2.0.1 + universal-user-agent: 7.0.2 + + '@octokit/rest@21.1.1': + dependencies: + '@octokit/core': 6.1.4 + '@octokit/plugin-paginate-rest': 11.4.3(@octokit/core@6.1.4) + '@octokit/plugin-request-log': 5.3.1(@octokit/core@6.1.4) + '@octokit/plugin-rest-endpoint-methods': 13.3.1(@octokit/core@6.1.4) + + '@octokit/types@13.8.0': + dependencies: + '@octokit/openapi-types': 23.0.1 + + '@pkgjs/parseargs@0.11.0': + optional: true + + '@pnpm/catalogs.config@1000.0.2': + dependencies: + '@pnpm/error': 1000.0.2 + + '@pnpm/catalogs.protocol-parser@1000.0.0': {} + + '@pnpm/catalogs.resolver@1000.0.2': + dependencies: + '@pnpm/catalogs.protocol-parser': 1000.0.0 + '@pnpm/error': 1000.0.2 + + '@pnpm/catalogs.types@1000.0.0': {} + + '@pnpm/cli-meta@1000.0.2': + dependencies: + '@pnpm/types': 1000.1.1 + load-json-file: 6.2.0 + + '@pnpm/cli-utils@1000.0.10(@pnpm/logger@1000.0.0)': + dependencies: + '@pnpm/cli-meta': 1000.0.2 + '@pnpm/config': 1002.3.1(@pnpm/logger@1000.0.0) + '@pnpm/default-reporter': 1001.3.1(@pnpm/logger@1000.0.0) + '@pnpm/error': 1000.0.2 + '@pnpm/logger': 1000.0.0 + '@pnpm/manifest-utils': 1000.0.4(@pnpm/logger@1000.0.0) + '@pnpm/package-is-installable': 1000.0.4(@pnpm/logger@1000.0.0) + '@pnpm/read-project-manifest': 1000.0.5 + '@pnpm/types': 1000.1.1 + chalk: 4.1.2 + load-json-file: 6.2.0 + + '@pnpm/config.env-replace@1.1.0': {} + + '@pnpm/config.env-replace@3.0.0': {} + + '@pnpm/config@1002.3.1(@pnpm/logger@1000.0.0)': + dependencies: + '@pnpm/catalogs.config': 1000.0.2 + '@pnpm/catalogs.types': 1000.0.0 + '@pnpm/config.env-replace': 3.0.0 + '@pnpm/constants': 1001.1.0 + '@pnpm/error': 1000.0.2 + '@pnpm/git-utils': 1000.0.0 + '@pnpm/matcher': 1000.0.0 + '@pnpm/npm-conf': 3.0.0 + '@pnpm/pnpmfile': 1001.0.4(@pnpm/logger@1000.0.0) + '@pnpm/read-project-manifest': 1000.0.5 + '@pnpm/types': 1000.1.1 + '@pnpm/workspace.read-manifest': 1000.0.2 + better-path-resolve: 1.0.0 + camelcase: 6.3.0 + camelcase-keys: 6.2.2 + can-write-to-dir: 1.1.1 + is-subdir: 1.2.0 + is-windows: 1.0.2 + normalize-registry-url: 2.0.0 + path-absolute: 1.0.1 + path-name: 1.0.0 + ramda: '@pnpm/ramda@0.28.1' + read-ini-file: 4.0.0 + realpath-missing: 1.1.0 + which: '@pnpm/which@3.0.1' + transitivePeerDependencies: + - '@pnpm/logger' + + '@pnpm/constants@1001.1.0': {} + + '@pnpm/core-loggers@1000.1.2(@pnpm/logger@1000.0.0)': + dependencies: + '@pnpm/logger': 1000.0.0 + '@pnpm/types': 1000.1.1 + + '@pnpm/crypto.hash@1000.0.0': + dependencies: + '@pnpm/crypto.polyfill': 1000.0.0 + + '@pnpm/crypto.polyfill@1000.0.0': {} + + '@pnpm/dedupe.issues-renderer@1000.0.1': + dependencies: + '@pnpm/dedupe.types': 1000.0.0 + archy: 1.0.0 + chalk: 4.1.2 + + '@pnpm/dedupe.types@1000.0.0': {} + + '@pnpm/default-reporter@1001.3.1(@pnpm/logger@1000.0.0)': + dependencies: + '@pnpm/cli-meta': 1000.0.2 + '@pnpm/config': 1002.3.1(@pnpm/logger@1000.0.0) + '@pnpm/core-loggers': 1000.1.2(@pnpm/logger@1000.0.0) + '@pnpm/dedupe.issues-renderer': 1000.0.1 + '@pnpm/dedupe.types': 1000.0.0 + '@pnpm/error': 1000.0.2 + '@pnpm/logger': 1000.0.0 + '@pnpm/render-peer-issues': 1000.0.4 + '@pnpm/types': 1000.1.1 + ansi-diff: 1.2.0 + boxen: 5.1.2 + chalk: 4.1.2 + cli-truncate: 2.1.0 + normalize-path: 3.0.0 + pretty-bytes: 5.6.0 + pretty-ms: 7.0.1 + ramda: '@pnpm/ramda@0.28.1' + rxjs: 7.8.1 + semver: 7.7.2 + stacktracey: 2.1.8 + string-length: 4.0.2 + + '@pnpm/env.system-node-version@1000.0.2': + dependencies: + '@pnpm/cli-meta': 1000.0.2 + execa: safe-execa@0.1.2 + mem: 8.1.1 + + '@pnpm/error@1000.0.2': + dependencies: + '@pnpm/constants': 1001.1.0 + + '@pnpm/fetcher-base@1000.0.3': + dependencies: + '@pnpm/resolver-base': 1000.1.2 + '@pnpm/types': 1000.1.1 + '@types/ssri': 7.1.5 + + '@pnpm/fs.find-packages@1000.0.5': + dependencies: + '@pnpm/read-project-manifest': 1000.0.5 + '@pnpm/types': 1000.1.1 + '@pnpm/util.lex-comparator': 3.0.0 + fast-glob: 3.3.3 + p-filter: 2.1.0 + + '@pnpm/git-utils@1000.0.0': + dependencies: + execa: safe-execa@0.1.2 + + '@pnpm/graceful-fs@1000.0.0': + dependencies: + graceful-fs: 4.2.11 + + '@pnpm/hooks.types@1001.0.2': + dependencies: + '@pnpm/lockfile.types': 1001.0.2 + '@pnpm/types': 1000.1.1 + + '@pnpm/lockfile.types@1001.0.2': + dependencies: + '@pnpm/patching.types': 1000.0.0 + '@pnpm/types': 1000.1.1 + + '@pnpm/logger@1000.0.0': + dependencies: + bole: 5.0.19 + ndjson: 2.0.0 + + '@pnpm/manifest-utils@1000.0.4(@pnpm/logger@1000.0.0)': + dependencies: + '@pnpm/core-loggers': 1000.1.2(@pnpm/logger@1000.0.0) + '@pnpm/error': 1000.0.2 + '@pnpm/types': 1000.1.1 + transitivePeerDependencies: + - '@pnpm/logger' + + '@pnpm/matcher@1000.0.0': + dependencies: + escape-string-regexp: 4.0.0 + + '@pnpm/network.ca-file@1.0.2': + dependencies: + graceful-fs: 4.2.10 + + '@pnpm/npm-conf@2.3.1': + dependencies: + '@pnpm/config.env-replace': 1.1.0 + '@pnpm/network.ca-file': 1.0.2 + config-chain: 1.1.13 + + '@pnpm/npm-conf@3.0.0': + dependencies: + '@pnpm/config.env-replace': 1.1.0 + '@pnpm/network.ca-file': 1.0.2 + config-chain: 1.1.13 + + '@pnpm/package-is-installable@1000.0.4(@pnpm/logger@1000.0.0)': + dependencies: + '@pnpm/cli-meta': 1000.0.2 + '@pnpm/core-loggers': 1000.1.2(@pnpm/logger@1000.0.0) + '@pnpm/env.system-node-version': 1000.0.2 + '@pnpm/error': 1000.0.2 + '@pnpm/logger': 1000.0.0 + '@pnpm/types': 1000.1.1 + detect-libc: 2.0.3 + execa: safe-execa@0.1.2 + mem: 8.1.1 + semver: 7.7.2 + + '@pnpm/parse-overrides@1000.0.2': + dependencies: + '@pnpm/catalogs.resolver': 1000.0.2 + '@pnpm/catalogs.types': 1000.0.0 + '@pnpm/error': 1000.0.2 + '@pnpm/parse-wanted-dependency': 1000.0.0 + + '@pnpm/parse-wanted-dependency@1000.0.0': + dependencies: + validate-npm-package-name: 5.0.0 + + '@pnpm/patching.types@1000.0.0': {} + + '@pnpm/pnpmfile@1001.0.4(@pnpm/logger@1000.0.0)': + dependencies: + '@pnpm/core-loggers': 1000.1.2(@pnpm/logger@1000.0.0) + '@pnpm/crypto.hash': 1000.0.0 + '@pnpm/error': 1000.0.2 + '@pnpm/hooks.types': 1001.0.2 + '@pnpm/lockfile.types': 1001.0.2 + '@pnpm/logger': 1000.0.0 + '@pnpm/store-controller-types': 1001.0.1 + '@pnpm/types': 1000.1.1 + chalk: 4.1.2 + path-absolute: 1.0.1 + + '@pnpm/ramda@0.28.1': {} + + '@pnpm/read-project-manifest@1000.0.5': + dependencies: + '@gwhitney/detect-indent': 7.0.1 + '@pnpm/error': 1000.0.2 + '@pnpm/graceful-fs': 1000.0.0 + '@pnpm/text.comments-parser': 1000.0.0 + '@pnpm/types': 1000.1.1 + '@pnpm/write-project-manifest': 1000.0.2 + fast-deep-equal: 3.1.3 + is-windows: 1.0.2 + json5: 2.2.3 + parse-json: 5.2.0 + read-yaml-file: 2.1.0 + sort-keys: 4.2.0 + strip-bom: 4.0.0 + + '@pnpm/render-peer-issues@1000.0.4': + dependencies: + '@pnpm/error': 1000.0.2 + '@pnpm/matcher': 1000.0.0 + '@pnpm/parse-overrides': 1000.0.2 + '@pnpm/types': 1000.1.1 + archy: 1.0.0 + chalk: 4.1.2 + cli-columns: 4.0.0 + semver: 7.7.2 + + '@pnpm/resolver-base@1000.1.2': + dependencies: + '@pnpm/types': 1000.1.1 + + '@pnpm/store-controller-types@1001.0.1': + dependencies: + '@pnpm/fetcher-base': 1000.0.3 + '@pnpm/resolver-base': 1000.1.2 + '@pnpm/types': 1000.1.1 + + '@pnpm/text.comments-parser@1000.0.0': + dependencies: + strip-comments-strings: 1.2.0 + + '@pnpm/types@1000.1.1': {} + + '@pnpm/util.lex-comparator@3.0.0': {} + + '@pnpm/which@3.0.1': + dependencies: + isexe: 2.0.0 + + '@pnpm/workspace.find-packages@1000.0.10(@pnpm/logger@1000.0.0)': + dependencies: + '@pnpm/cli-utils': 1000.0.10(@pnpm/logger@1000.0.0) + '@pnpm/constants': 1001.1.0 + '@pnpm/fs.find-packages': 1000.0.5 + '@pnpm/logger': 1000.0.0 + '@pnpm/types': 1000.1.1 + '@pnpm/util.lex-comparator': 3.0.0 + + '@pnpm/workspace.read-manifest@1000.0.2': + dependencies: + '@pnpm/constants': 1001.1.0 + '@pnpm/error': 1000.0.2 + read-yaml-file: 2.1.0 + + '@pnpm/write-project-manifest@1000.0.2': + dependencies: + '@pnpm/text.comments-parser': 1000.0.0 + '@pnpm/types': 1000.1.1 + json5: 2.2.3 + write-file-atomic: 5.0.1 + write-yaml-file: 5.0.0 + + '@publint/pack@0.1.1': {} + + '@puppeteer/browsers@2.10.5': + dependencies: + debug: 4.4.1(supports-color@8.1.1) + extract-zip: 2.0.1 + progress: 2.0.3 + proxy-agent: 6.5.0 + semver: 7.7.2 + tar-fs: 3.1.0 + yargs: 17.7.2 + transitivePeerDependencies: + - bare-buffer + - supports-color + + '@puppeteer/browsers@2.6.1': + dependencies: + debug: 4.4.0 + extract-zip: 2.0.1 + progress: 2.0.3 + proxy-agent: 6.5.0 + semver: 7.7.2 + tar-fs: 3.1.0 + unbzip2-stream: 1.4.3 + yargs: 17.7.2 + transitivePeerDependencies: + - bare-buffer + - supports-color + + '@rollup/plugin-babel@6.0.4(@babel/core@7.26.0)(@types/babel__core@7.20.5)(rollup@4.34.8)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-module-imports': 7.25.9 + '@rollup/pluginutils': 5.1.4(rollup@4.34.8) + optionalDependencies: + '@types/babel__core': 7.20.5 + rollup: 4.34.8 + transitivePeerDependencies: + - supports-color + + '@rollup/plugin-commonjs@28.0.2(rollup@4.34.8)': + dependencies: + '@rollup/pluginutils': 5.1.4(rollup@4.34.8) + commondir: 1.0.1 + estree-walker: 2.0.2 + fdir: 6.4.3(picomatch@4.0.2) + is-reference: 1.2.1 + magic-string: 0.30.17 + picomatch: 4.0.2 + optionalDependencies: + rollup: 4.34.8 + + '@rollup/plugin-inject@5.0.5(rollup@4.34.8)': + dependencies: + '@rollup/pluginutils': 5.1.4(rollup@4.34.8) + estree-walker: 2.0.2 + magic-string: 0.30.17 + optionalDependencies: + rollup: 4.34.8 + + '@rollup/plugin-node-resolve@16.0.0(rollup@4.34.8)': + dependencies: + '@rollup/pluginutils': 5.1.4(rollup@4.34.8) + '@types/resolve': 1.20.2 + deepmerge: 4.3.1 + is-module: 1.0.0 + resolve: 1.22.10 + optionalDependencies: + rollup: 4.34.8 + + '@rollup/plugin-replace@6.0.2(rollup@4.34.8)': + dependencies: + '@rollup/pluginutils': 5.1.4(rollup@4.34.8) + magic-string: 0.30.17 + optionalDependencies: + rollup: 4.34.8 + + '@rollup/plugin-sucrase@5.0.2(rollup@4.34.8)': + dependencies: + '@rollup/pluginutils': 5.1.4(rollup@4.34.8) + sucrase: 3.35.0 + optionalDependencies: + rollup: 4.34.8 + + '@rollup/plugin-swc@0.4.0(@swc/core@1.9.3)(rollup@4.34.8)': + dependencies: + '@rollup/pluginutils': 5.1.4(rollup@4.34.8) + '@swc/core': 1.9.3 + smob: 1.5.0 + optionalDependencies: + rollup: 4.34.8 + + '@rollup/plugin-terser@0.4.4(rollup@4.34.8)': + dependencies: + serialize-javascript: 6.0.2 + smob: 1.5.0 + terser: 5.37.0 + optionalDependencies: + rollup: 4.34.8 + + '@rollup/plugin-typescript@12.1.2(rollup@4.34.8)(tslib@2.8.1)(typescript@5.7.3)': + dependencies: + '@rollup/pluginutils': 5.1.4(rollup@4.34.8) + resolve: 1.22.10 + typescript: 5.7.3 + optionalDependencies: + rollup: 4.34.8 + tslib: 2.8.1 + + '@rollup/pluginutils@5.1.4(rollup@4.34.8)': + dependencies: + '@types/estree': 1.0.6 + estree-walker: 2.0.2 + picomatch: 4.0.2 + optionalDependencies: + rollup: 4.34.8 + + '@rollup/rollup-android-arm-eabi@4.34.8': + optional: true + + '@rollup/rollup-android-arm-eabi@4.44.1': + optional: true + + '@rollup/rollup-android-arm64@4.34.8': + optional: true + + '@rollup/rollup-android-arm64@4.44.1': + optional: true + + '@rollup/rollup-darwin-arm64@4.34.8': + optional: true + + '@rollup/rollup-darwin-arm64@4.44.1': + optional: true + + '@rollup/rollup-darwin-x64@4.34.8': + optional: true + + '@rollup/rollup-darwin-x64@4.44.1': + optional: true + + '@rollup/rollup-freebsd-arm64@4.34.8': + optional: true + + '@rollup/rollup-freebsd-arm64@4.44.1': + optional: true + + '@rollup/rollup-freebsd-x64@4.34.8': + optional: true + + '@rollup/rollup-freebsd-x64@4.44.1': + optional: true + + '@rollup/rollup-linux-arm-gnueabihf@4.34.8': + optional: true + + '@rollup/rollup-linux-arm-gnueabihf@4.44.1': + optional: true + + '@rollup/rollup-linux-arm-musleabihf@4.34.8': + optional: true + + '@rollup/rollup-linux-arm-musleabihf@4.44.1': + optional: true + + '@rollup/rollup-linux-arm64-gnu@4.34.8': + optional: true + + '@rollup/rollup-linux-arm64-gnu@4.44.1': + optional: true + + '@rollup/rollup-linux-arm64-musl@4.34.8': + optional: true + + '@rollup/rollup-linux-arm64-musl@4.44.1': + optional: true + + '@rollup/rollup-linux-loongarch64-gnu@4.34.8': + optional: true + + '@rollup/rollup-linux-loongarch64-gnu@4.44.1': + optional: true + + '@rollup/rollup-linux-powerpc64le-gnu@4.34.8': + optional: true + + '@rollup/rollup-linux-powerpc64le-gnu@4.44.1': + optional: true + + '@rollup/rollup-linux-riscv64-gnu@4.34.8': + optional: true + + '@rollup/rollup-linux-riscv64-gnu@4.44.1': + optional: true + + '@rollup/rollup-linux-riscv64-musl@4.44.1': + optional: true + + '@rollup/rollup-linux-s390x-gnu@4.34.8': + optional: true + + '@rollup/rollup-linux-s390x-gnu@4.44.1': + optional: true + + '@rollup/rollup-linux-x64-gnu@4.34.8': + optional: true + + '@rollup/rollup-linux-x64-gnu@4.44.1': + optional: true + + '@rollup/rollup-linux-x64-musl@4.34.8': + optional: true + + '@rollup/rollup-linux-x64-musl@4.44.1': + optional: true + + '@rollup/rollup-win32-arm64-msvc@4.34.8': + optional: true + + '@rollup/rollup-win32-arm64-msvc@4.44.1': + optional: true + + '@rollup/rollup-win32-ia32-msvc@4.34.8': + optional: true + + '@rollup/rollup-win32-ia32-msvc@4.44.1': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.34.8': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.44.1': + optional: true + + '@rtsao/scc@1.1.0': {} + + '@samverschueren/stream-to-observable@0.3.1(rxjs@6.6.7)': + dependencies: + any-observable: 0.3.0(rxjs@6.6.7) + optionalDependencies: + rxjs: 6.6.7 + transitivePeerDependencies: + - zenObservable + + '@sec-ant/readable-stream@0.4.1': {} + + '@simple-dom/document@1.4.0': + dependencies: + '@simple-dom/interface': 1.4.0 + + '@simple-dom/interface@1.4.0': {} + + '@simple-dom/serializer@1.4.0': + dependencies: + '@simple-dom/interface': 1.4.0 + + '@simple-dom/void-map@1.4.0': {} + + '@sindresorhus/is@4.6.0': {} + + '@sindresorhus/merge-streams@2.3.0': {} + + '@sindresorhus/merge-streams@4.0.0': {} + + '@snyk/github-codeowners@1.1.0': + dependencies: + commander: 4.1.1 + ignore: 5.3.2 + p-map: 4.0.0 + + '@socket.io/component-emitter@3.1.2': {} + + '@swc/core-darwin-arm64@1.9.3': + optional: true + + '@swc/core-darwin-x64@1.9.3': + optional: true + + '@swc/core-linux-arm-gnueabihf@1.9.3': + optional: true + + '@swc/core-linux-arm64-gnu@1.9.3': + optional: true + + '@swc/core-linux-arm64-musl@1.9.3': + optional: true + + '@swc/core-linux-x64-gnu@1.9.3': + optional: true + + '@swc/core-linux-x64-musl@1.9.3': + optional: true + + '@swc/core-win32-arm64-msvc@1.9.3': + optional: true + + '@swc/core-win32-ia32-msvc@1.9.3': + optional: true + + '@swc/core-win32-x64-msvc@1.9.3': + optional: true + + '@swc/core@1.9.3': + dependencies: + '@swc/counter': 0.1.3 + '@swc/types': 0.1.23 + optionalDependencies: + '@swc/core-darwin-arm64': 1.9.3 + '@swc/core-darwin-x64': 1.9.3 + '@swc/core-linux-arm-gnueabihf': 1.9.3 + '@swc/core-linux-arm64-gnu': 1.9.3 + '@swc/core-linux-arm64-musl': 1.9.3 + '@swc/core-linux-x64-gnu': 1.9.3 + '@swc/core-linux-x64-musl': 1.9.3 + '@swc/core-win32-arm64-msvc': 1.9.3 + '@swc/core-win32-ia32-msvc': 1.9.3 + '@swc/core-win32-x64-msvc': 1.9.3 + + '@swc/counter@0.1.3': {} + + '@swc/types@0.1.23': + dependencies: + '@swc/counter': 0.1.3 + + '@szmarczak/http-timer@4.0.6': + dependencies: + defer-to-connect: 2.0.1 + + '@tootallnate/once@1.1.2': {} + + '@tootallnate/quickjs-emscripten@0.23.0': {} + + '@tracerbench/core@8.0.1': + dependencies: + '@tracerbench/har': 8.0.0 + '@tracerbench/trace-event': 8.0.0 + '@tracerbench/trace-model': 8.0.0 + '@types/d3-hierarchy': 3.1.7 + '@types/node': 22.13.4 + array-binsearch: 1.0.1 + chalk: 4.1.2 + chrome-debugging-client: 2.0.0(devtools-protocol@0.0.975963) + d3-hierarchy: 3.1.2 + debug: 4.4.1(supports-color@8.1.1) + devtools-protocol: 0.0.975963 + fs-extra: 10.1.0 + handlebars: 4.7.8 + lodash.clonedeep: 4.5.0 + race-cancellation: 0.4.1 + silent-error: 1.1.1 + tmp: 0.2.3 + tslib: 2.8.1 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + '@tracerbench/find-chrome@2.0.0': + dependencies: + chrome-launcher: 0.13.4 + transitivePeerDependencies: + - supports-color + + '@tracerbench/har@8.0.0': {} + + '@tracerbench/message-transport@2.0.0': {} + + '@tracerbench/protocol-connection@2.0.0(devtools-protocol@0.0.975963)': + dependencies: + '@tracerbench/message-transport': 2.0.0 + '@tracerbench/protocol-transport': 2.0.0 + devtools-protocol: 0.0.975963 + race-cancellation: 0.4.1 + + '@tracerbench/protocol-transport@2.0.0': + dependencies: + '@tracerbench/message-transport': 2.0.0 + race-cancellation: 0.4.1 + + '@tracerbench/spawn-chrome@2.0.0': + dependencies: + '@tracerbench/find-chrome': 2.0.0 + '@tracerbench/spawn': 2.0.0 + tmp: 0.2.3 + transitivePeerDependencies: + - supports-color + + '@tracerbench/spawn@2.0.0': + dependencies: + '@tracerbench/message-transport': 2.0.0 + debug: 4.4.1(supports-color@8.1.1) + execa: 4.1.0 + race-cancellation: 0.4.1 + transitivePeerDependencies: + - supports-color + + '@tracerbench/stats@8.0.1': + dependencies: + d3-array: 2.12.1 + d3-scale: 3.3.0 + fs-extra: 10.1.0 + jstat: 1.9.6 + path: 0.12.7 + tmp: 0.2.3 + tslib: 2.8.1 + + '@tracerbench/trace-event@8.0.0': {} + + '@tracerbench/trace-model@8.0.0': + dependencies: + '@tracerbench/trace-event': 8.0.0 + debug: 4.4.1(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + + '@tracerbench/websocket-message-transport@2.0.0': + dependencies: + '@tracerbench/message-transport': 2.0.0 + race-cancellation: 0.4.1 + ws: 7.5.10 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + + '@trysound/sax@0.2.0': {} + + '@tsconfig/node10@1.0.11': {} + + '@tsconfig/node12@1.0.11': {} + + '@tsconfig/node14@1.0.3': {} + + '@tsconfig/node16@1.0.4': {} + + '@tsconfig/strictest@2.0.5': {} + + '@types/babel-plugin-macros@3.1.3': + dependencies: + '@types/babel__core': 7.20.5 + + '@types/babel__core@7.20.5': + dependencies: + '@babel/parser': 7.26.3 + '@babel/types': 7.28.0 + '@types/babel__generator': 7.6.8 + '@types/babel__template': 7.4.4 + '@types/babel__traverse': 7.20.7 + + '@types/babel__generator@7.6.8': + dependencies: + '@babel/types': 7.28.0 + + '@types/babel__template@7.4.4': + dependencies: + '@babel/parser': 7.26.3 + '@babel/types': 7.28.0 + + '@types/babel__traverse@7.20.7': + dependencies: + '@babel/types': 7.28.0 + + '@types/cacheable-request@6.0.3': + dependencies: + '@types/http-cache-semantics': 4.0.4 + '@types/keyv': 3.1.4 + '@types/node': 22.13.4 + '@types/responselike': 1.0.3 + + '@types/cli-progress@3.11.6': + dependencies: + '@types/node': 22.13.4 + + '@types/cookie@0.4.1': {} + + '@types/cors@2.8.17': + dependencies: + '@types/node': 22.13.4 + + '@types/d3-hierarchy@3.1.7': {} + + '@types/doctrine@0.0.9': {} + + '@types/eslint-utils@3.0.5': + dependencies: + '@types/eslint': 9.6.1 + '@types/estree': 1.0.6 + + '@types/eslint@9.6.1': + dependencies: + '@types/estree': 1.0.6 + '@types/json-schema': 7.0.15 + + '@types/eslint__eslintrc@2.1.2': + dependencies: + '@types/eslint': 9.6.1 + + '@types/estree@1.0.6': {} + + '@types/estree@1.0.8': {} + + '@types/fs-extra@11.0.4': + dependencies: + '@types/jsonfile': 6.1.4 + '@types/node': 22.13.4 + + '@types/glob@8.1.0': + dependencies: + '@types/minimatch': 5.1.2 + '@types/node': 22.13.4 + + '@types/handlebars@4.1.0': + dependencies: + handlebars: 4.7.8 + + '@types/http-cache-semantics@4.0.4': {} + + '@types/js-yaml@4.0.9': {} + + '@types/json-schema@7.0.15': {} + + '@types/json5@0.0.29': {} + + '@types/jsonfile@6.1.4': + dependencies: + '@types/node': 22.13.4 + + '@types/keyv@3.1.4': + dependencies: + '@types/node': 22.13.4 + + '@types/minimatch@5.1.2': {} + + '@types/minimist@1.2.5': {} + + '@types/node@22.13.4': + dependencies: + undici-types: 6.20.0 + + '@types/normalize-package-data@2.4.4': {} + + '@types/parse-json@4.0.2': {} + + '@types/preval.macro@3.0.2': {} + + '@types/qunit@2.19.12': {} + + '@types/resolve@1.20.2': {} + + '@types/responselike@1.0.3': + dependencies: + '@types/node': 22.13.4 + + '@types/ssri@7.1.5': + dependencies: + '@types/node': 22.13.4 + + '@types/tar@6.1.13': + dependencies: + '@types/node': 22.13.4 + minipass: 4.2.8 + + '@types/yauzl@2.10.3': + dependencies: + '@types/node': 22.13.4 + optional: true + + '@typescript-eslint/eslint-plugin@8.24.1(@typescript-eslint/parser@8.24.1(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3))(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3)': + dependencies: + '@eslint-community/regexpp': 4.12.1 + '@typescript-eslint/parser': 8.24.1(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3) + '@typescript-eslint/scope-manager': 8.24.1 + '@typescript-eslint/type-utils': 8.24.1(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3) + '@typescript-eslint/utils': 8.24.1(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3) + '@typescript-eslint/visitor-keys': 8.24.1 + eslint: 9.20.1(jiti@2.4.2) + graphemer: 1.4.0 + ignore: 5.3.2 + natural-compare: 1.4.0 + ts-api-utils: 2.0.1(typescript@5.7.3) + typescript: 5.7.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/eslint-plugin@8.24.1(@typescript-eslint/parser@8.35.1(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3))(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3)': + dependencies: + '@eslint-community/regexpp': 4.12.1 + '@typescript-eslint/parser': 8.35.1(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3) + '@typescript-eslint/scope-manager': 8.24.1 + '@typescript-eslint/type-utils': 8.24.1(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3) + '@typescript-eslint/utils': 8.24.1(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3) + '@typescript-eslint/visitor-keys': 8.24.1 + eslint: 9.20.1(jiti@2.4.2) + graphemer: 1.4.0 + ignore: 5.3.2 + natural-compare: 1.4.0 + ts-api-utils: 2.0.1(typescript@5.7.3) + typescript: 5.7.3 + transitivePeerDependencies: + - supports-color + optional: true + + '@typescript-eslint/parser@8.24.1(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3)': + dependencies: + '@typescript-eslint/scope-manager': 8.24.1 + '@typescript-eslint/types': 8.24.1 + '@typescript-eslint/typescript-estree': 8.24.1(typescript@5.7.3) + '@typescript-eslint/visitor-keys': 8.24.1 + debug: 4.4.0 + eslint: 9.20.1(jiti@2.4.2) + typescript: 5.7.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/parser@8.35.1(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3)': + dependencies: + '@typescript-eslint/scope-manager': 8.35.1 + '@typescript-eslint/types': 8.35.1 + '@typescript-eslint/typescript-estree': 8.35.1(typescript@5.7.3) + '@typescript-eslint/visitor-keys': 8.35.1 + debug: 4.4.0 + eslint: 9.20.1(jiti@2.4.2) + typescript: 5.7.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/project-service@8.35.1(typescript@5.7.3)': + dependencies: + '@typescript-eslint/tsconfig-utils': 8.35.1(typescript@5.7.3) + '@typescript-eslint/types': 8.35.1 + debug: 4.4.0 + typescript: 5.7.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/scope-manager@8.19.0': + dependencies: + '@typescript-eslint/types': 8.19.0 + '@typescript-eslint/visitor-keys': 8.19.0 + + '@typescript-eslint/scope-manager@8.24.1': + dependencies: + '@typescript-eslint/types': 8.24.1 + '@typescript-eslint/visitor-keys': 8.24.1 + + '@typescript-eslint/scope-manager@8.35.1': + dependencies: + '@typescript-eslint/types': 8.35.1 + '@typescript-eslint/visitor-keys': 8.35.1 + + '@typescript-eslint/tsconfig-utils@8.35.1(typescript@5.7.3)': + dependencies: + typescript: 5.7.3 + + '@typescript-eslint/type-utils@8.24.1(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3)': + dependencies: + '@typescript-eslint/typescript-estree': 8.24.1(typescript@5.7.3) + '@typescript-eslint/utils': 8.24.1(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3) + debug: 4.4.1(supports-color@8.1.1) + eslint: 9.20.1(jiti@2.4.2) + ts-api-utils: 2.0.1(typescript@5.7.3) + typescript: 5.7.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/types@8.19.0': {} + + '@typescript-eslint/types@8.24.1': {} + + '@typescript-eslint/types@8.35.1': {} + + '@typescript-eslint/typescript-estree@8.24.1(typescript@5.7.3)': + dependencies: + '@typescript-eslint/types': 8.24.1 + '@typescript-eslint/visitor-keys': 8.24.1 + debug: 4.4.0 + fast-glob: 3.3.3 + is-glob: 4.0.3 + minimatch: 9.0.5 + semver: 7.7.2 + ts-api-utils: 2.0.1(typescript@5.7.3) + typescript: 5.7.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/typescript-estree@8.35.1(typescript@5.7.3)': + dependencies: + '@typescript-eslint/project-service': 8.35.1(typescript@5.7.3) + '@typescript-eslint/tsconfig-utils': 8.35.1(typescript@5.7.3) + '@typescript-eslint/types': 8.35.1 + '@typescript-eslint/visitor-keys': 8.35.1 + debug: 4.4.0 + fast-glob: 3.3.3 + is-glob: 4.0.3 + minimatch: 9.0.5 + semver: 7.7.2 + ts-api-utils: 2.1.0(typescript@5.7.3) + typescript: 5.7.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/utils@8.24.1(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3)': + dependencies: + '@eslint-community/eslint-utils': 4.7.0(eslint@9.20.1(jiti@2.4.2)) + '@typescript-eslint/scope-manager': 8.24.1 + '@typescript-eslint/types': 8.24.1 + '@typescript-eslint/typescript-estree': 8.24.1(typescript@5.7.3) + eslint: 9.20.1(jiti@2.4.2) + typescript: 5.7.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/utils@8.35.1(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3)': + dependencies: + '@eslint-community/eslint-utils': 4.7.0(eslint@9.20.1(jiti@2.4.2)) + '@typescript-eslint/scope-manager': 8.35.1 + '@typescript-eslint/types': 8.35.1 + '@typescript-eslint/typescript-estree': 8.35.1(typescript@5.7.3) + eslint: 9.20.1(jiti@2.4.2) + typescript: 5.7.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/visitor-keys@8.19.0': + dependencies: + '@typescript-eslint/types': 8.19.0 + eslint-visitor-keys: 4.2.1 + + '@typescript-eslint/visitor-keys@8.24.1': + dependencies: + '@typescript-eslint/types': 8.24.1 + eslint-visitor-keys: 4.2.0 + + '@typescript-eslint/visitor-keys@8.35.1': + dependencies: + '@typescript-eslint/types': 8.35.1 + eslint-visitor-keys: 4.2.1 + + '@vitest/expect@3.0.6': + dependencies: + '@vitest/spy': 3.0.6 + '@vitest/utils': 3.0.6 + chai: 5.2.0 + tinyrainbow: 2.0.0 + + '@vitest/mocker@3.0.6(vite@6.3.5(@types/node@22.13.4)(jiti@2.4.2)(terser@5.43.1)(tsx@4.19.2)(yaml@2.7.0))': + dependencies: + '@vitest/spy': 3.0.6 + estree-walker: 3.0.3 + magic-string: 0.30.17 + optionalDependencies: + vite: 6.3.5(@types/node@22.13.4)(jiti@2.4.2)(terser@5.43.1)(tsx@4.19.2)(yaml@2.7.0) + + '@vitest/pretty-format@3.0.6': + dependencies: + tinyrainbow: 2.0.0 + + '@vitest/runner@3.0.6': + dependencies: + '@vitest/utils': 3.0.6 + pathe: 2.0.3 + + '@vitest/snapshot@3.0.6': + dependencies: + '@vitest/pretty-format': 3.0.6 + magic-string: 0.30.17 + pathe: 2.0.3 + + '@vitest/spy@3.0.6': + dependencies: + tinyspy: 3.0.2 + + '@vitest/utils@3.0.6': + dependencies: + '@vitest/pretty-format': 3.0.6 + loupe: 3.1.3 + tinyrainbow: 2.0.0 + + '@xmldom/xmldom@0.8.10': {} + + '@zkochan/which@2.0.3': + dependencies: + isexe: 2.0.0 + + accepts@1.3.8: + dependencies: + mime-types: 2.1.35 + negotiator: 0.6.3 + + acorn-jsx@5.3.2(acorn@8.14.0): + dependencies: + acorn: 8.14.0 + + acorn-walk@8.3.4: + dependencies: + acorn: 8.15.0 + + acorn@8.14.0: {} + + acorn@8.15.0: {} + + agent-base@6.0.2: + dependencies: + debug: 4.4.1(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + + agent-base@7.1.3: {} + + agentkeepalive@4.6.0: + dependencies: + humanize-ms: 1.2.1 + + aggregate-error@3.1.0: + dependencies: + clean-stack: 2.2.0 + indent-string: 4.0.0 + + ajv@6.12.6: + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + + ajv@8.17.1: + dependencies: + fast-deep-equal: 3.1.3 + fast-uri: 3.0.5 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + + amd-name-resolver@1.3.1: + dependencies: + ensure-posix-path: 1.1.1 + object-hash: 1.3.1 + + ansi-align@3.0.1: + dependencies: + string-width: 4.2.3 + + ansi-colors@4.1.1: {} + + ansi-diff@1.2.0: + dependencies: + ansi-split: 1.0.1 + wcwidth: 1.0.1 + + ansi-escapes@3.2.0: {} + + ansi-escapes@4.3.2: + dependencies: + type-fest: 0.21.3 + + ansi-escapes@5.0.0: + dependencies: + type-fest: 1.4.0 + + ansi-regex@2.1.1: {} + + ansi-regex@3.0.1: {} + + ansi-regex@5.0.1: {} + + ansi-regex@6.1.0: {} + + ansi-split@1.0.1: + dependencies: + ansi-regex: 3.0.1 + + ansi-styles@2.2.1: {} + + ansi-styles@3.2.1: + dependencies: + color-convert: 1.9.3 + + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + + ansi-styles@6.2.1: {} + + ansicolors@0.3.2: {} + + ansis@3.17.0: {} + + ansis@4.1.0: {} + + any-observable@0.3.0(rxjs@6.6.7): + optionalDependencies: + rxjs: 6.6.7 + + any-promise@1.3.0: {} + + aproba@2.0.0: {} + + archiver-utils@2.1.0: + dependencies: + glob: 7.2.3 + graceful-fs: 4.2.11 + lazystream: 1.0.1 + lodash.defaults: 4.2.0 + lodash.difference: 4.5.0 + lodash.flatten: 4.4.0 + lodash.isplainobject: 4.0.6 + lodash.union: 4.6.0 + normalize-path: 3.0.0 + readable-stream: 2.3.8 + + archiver-utils@3.0.4: + dependencies: + glob: 7.2.3 + graceful-fs: 4.2.11 + lazystream: 1.0.1 + lodash.defaults: 4.2.0 + lodash.difference: 4.5.0 + lodash.flatten: 4.4.0 + lodash.isplainobject: 4.0.6 + lodash.union: 4.6.0 + normalize-path: 3.0.0 + readable-stream: 3.6.2 + + archiver@5.3.2: + dependencies: + archiver-utils: 2.1.0 + async: 3.2.6 + buffer-crc32: 0.2.13 + readable-stream: 3.6.2 + readdir-glob: 1.1.3 + tar-stream: 2.2.0 + zip-stream: 4.1.1 + + archy@1.0.0: {} + + are-we-there-yet@3.0.1: + dependencies: + delegates: 1.0.0 + readable-stream: 3.6.2 + + arg@4.1.3: {} + + argparse@1.0.10: + dependencies: + sprintf-js: 1.0.3 + + argparse@2.0.1: {} + + array-binsearch@1.0.1: {} + + array-buffer-byte-length@1.0.2: + dependencies: + call-bound: 1.0.3 + is-array-buffer: 3.0.5 + + array-flatten@1.1.1: {} + + array-includes@3.1.8: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.23.8 + es-object-atoms: 1.0.0 + get-intrinsic: 1.2.6 + is-string: 1.1.1 + + array-union@2.1.0: {} + + array.prototype.findlastindex@1.2.5: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.23.8 + es-errors: 1.3.0 + es-object-atoms: 1.0.0 + es-shim-unscopables: 1.0.2 + + array.prototype.flat@1.3.3: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.23.8 + es-shim-unscopables: 1.0.2 + + array.prototype.flatmap@1.3.3: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.23.8 + es-shim-unscopables: 1.0.2 + + arraybuffer.prototype.slice@1.0.4: + dependencies: + array-buffer-byte-length: 1.0.2 + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.23.8 + es-errors: 1.3.0 + get-intrinsic: 1.2.6 + is-array-buffer: 3.0.5 + + arrify@1.0.1: {} + + as-table@1.0.55: + dependencies: + printable-characters: 1.0.42 + + assert-never@1.4.0: {} + + assertion-error@2.0.1: {} + + ast-types@0.13.4: + dependencies: + tslib: 2.8.1 + + astral-regex@2.0.0: {} + + async@0.2.10: {} + + async@3.2.6: {} + + at-least-node@1.0.0: {} + + auto-dist-tag@2.1.1: + dependencies: + debug: 4.4.0 + fs-extra: 9.1.0 + meow: 9.0.0 + package-json: 6.5.0 + pkg-up: 3.1.0 + semver: 7.7.2 + transitivePeerDependencies: + - supports-color + + available-typed-arrays@1.0.7: + dependencies: + possible-typed-array-names: 1.0.0 + + b4a@1.6.7: {} + + babel-plugin-debug-macros@0.3.4(@babel/core@7.26.0): + dependencies: + '@babel/core': 7.26.0 + semver: 5.7.2 + + babel-plugin-macros@3.1.0: + dependencies: + '@babel/runtime': 7.27.6 + cosmiconfig: 7.1.0 + resolve: 1.22.10 + + babel-plugin-polyfill-corejs2@0.4.14(@babel/core@7.26.0): + dependencies: + '@babel/compat-data': 7.28.0 + '@babel/core': 7.26.0 + '@babel/helper-define-polyfill-provider': 0.6.5(@babel/core@7.26.0) + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + babel-plugin-polyfill-corejs3@0.13.0(@babel/core@7.26.0): + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-define-polyfill-provider': 0.6.5(@babel/core@7.26.0) + core-js-compat: 3.43.0 + transitivePeerDependencies: + - supports-color + + babel-plugin-polyfill-regenerator@0.6.5(@babel/core@7.26.0): + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-define-polyfill-provider': 0.6.5(@babel/core@7.26.0) + transitivePeerDependencies: + - supports-color + + babel-plugin-preval@5.1.0: + dependencies: + '@babel/runtime': 7.27.6 + '@types/babel__core': 7.20.5 + babel-plugin-macros: 3.1.0 + require-from-string: 2.0.2 + + babel-plugin-strip-glimmer-utils@0.1.1: {} + + babel-plugin-tester@11.0.4(@babel/core@7.26.0): + dependencies: + '@babel/core': 7.26.0 + core-js: 3.39.0 + debug: 4.4.0 + lodash.mergewith: 4.6.2 + prettier: 2.8.8 + strip-indent: 3.0.0 + transitivePeerDependencies: + - supports-color + + backbone@1.6.0: + dependencies: + underscore: 1.13.7 + + balanced-match@1.0.2: {} + + bare-events@2.5.4: + optional: true + + bare-fs@4.1.5: + dependencies: + bare-events: 2.5.4 + bare-path: 3.0.0 + bare-stream: 2.6.5(bare-events@2.5.4) + optional: true + + bare-os@3.6.1: + optional: true + + bare-path@3.0.0: + dependencies: + bare-os: 3.6.1 + optional: true + + bare-stream@2.6.5(bare-events@2.5.4): + dependencies: + streamx: 2.22.1 + optionalDependencies: + bare-events: 2.5.4 + optional: true + + base64-js@1.5.1: {} + + base64id@2.0.0: {} + + basic-ftp@5.0.5: {} + + before-after-hook@3.0.2: {} + + better-path-resolve@1.0.0: + dependencies: + is-windows: 1.0.2 + + bl@4.1.0: + dependencies: + buffer: 5.7.1 + inherits: 2.0.4 + readable-stream: 3.6.2 + + bluebird@3.7.2: {} + + body-parser@1.20.3: + dependencies: + bytes: 3.1.2 + content-type: 1.0.5 + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + on-finished: 2.4.1 + qs: 6.13.0 + raw-body: 2.5.2 + type-is: 1.6.18 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + + bole@5.0.19: + dependencies: + fast-safe-stringify: 2.1.1 + individual: 3.0.0 + + boolbase@1.0.0: {} + + boxen@5.1.2: + dependencies: + ansi-align: 3.0.1 + camelcase: 6.3.0 + chalk: 4.1.2 + cli-boxes: 2.2.1 + string-width: 4.2.3 + type-fest: 0.20.2 + widest-line: 3.1.0 + wrap-ansi: 7.0.0 + + boxen@8.0.1: + dependencies: + ansi-align: 3.0.1 + camelcase: 8.0.0 + chalk: 5.4.1 + cli-boxes: 3.0.0 + string-width: 7.2.0 + type-fest: 4.35.0 + widest-line: 5.0.0 + wrap-ansi: 9.0.0 + + brace-expansion@1.1.12: + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + + brace-expansion@2.0.2: + dependencies: + balanced-match: 1.0.2 + + braces@3.0.3: + dependencies: + fill-range: 7.1.1 + + browser-stdout@1.3.1: {} + + browserslist@4.25.1: + dependencies: + caniuse-lite: 1.0.30001726 + electron-to-chromium: 1.5.178 + node-releases: 2.0.19 + update-browserslist-db: 1.1.3(browserslist@4.25.1) + + buffer-crc32@0.2.13: {} + + buffer-from@1.1.2: {} + + buffer@5.7.1: + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + + builtins@5.1.0: + dependencies: + semver: 7.7.2 + + bundle-name@4.1.0: + dependencies: + run-applescript: 7.0.0 + + bundle-require@5.1.0(esbuild@0.25.5): + dependencies: + esbuild: 0.25.5 + load-tsconfig: 0.2.5 + + bytes@3.1.2: {} + + cac@6.7.14: {} + + cacache@15.3.0: + dependencies: + '@npmcli/fs': 1.1.1 + '@npmcli/move-file': 1.1.2 + chownr: 2.0.0 + fs-minipass: 2.1.0 + glob: 7.2.3 + infer-owner: 1.0.4 + lru-cache: 6.0.0 + minipass: 3.3.6 + minipass-collect: 1.0.2 + minipass-flush: 1.0.5 + minipass-pipeline: 1.2.4 + mkdirp: 1.0.4 + p-map: 4.0.0 + promise-inflight: 1.0.1 + rimraf: 3.0.2 + ssri: 8.0.1 + tar: 6.2.1 + unique-filename: 1.1.1 + transitivePeerDependencies: + - bluebird + + cacheable-lookup@5.0.4: {} + + cacheable-request@7.0.4: + dependencies: + clone-response: 1.0.3 + get-stream: 5.2.0 + http-cache-semantics: 4.1.1 + keyv: 4.5.4 + lowercase-keys: 2.0.0 + normalize-url: 6.1.0 + responselike: 2.0.1 + + call-bind-apply-helpers@1.0.1: + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + + call-bind@1.0.8: + dependencies: + call-bind-apply-helpers: 1.0.1 + es-define-property: 1.0.1 + get-intrinsic: 1.2.6 + set-function-length: 1.2.2 + + call-bound@1.0.3: + dependencies: + call-bind-apply-helpers: 1.0.1 + get-intrinsic: 1.2.6 + + callsites@3.1.0: {} + + camel-case@4.1.2: + dependencies: + pascal-case: 3.1.2 + tslib: 2.8.1 + + camelcase-keys@6.2.2: + dependencies: + camelcase: 5.3.1 + map-obj: 4.3.0 + quick-lru: 4.0.1 + + camelcase@5.3.1: {} + + camelcase@6.3.0: {} + + camelcase@8.0.0: {} + + can-write-to-dir@1.1.1: + dependencies: + path-temp: 2.1.0 + + caniuse-api@3.0.0: + dependencies: + browserslist: 4.25.1 + caniuse-lite: 1.0.30001690 + lodash.memoize: 4.1.2 + lodash.uniq: 4.5.0 + + caniuse-lite@1.0.30001690: {} + + caniuse-lite@1.0.30001726: {} + + cardinal@2.1.1: + dependencies: + ansicolors: 0.3.2 + redeyed: 2.1.1 + + chai@5.2.0: + dependencies: + assertion-error: 2.0.1 + check-error: 2.1.1 + deep-eql: 5.0.2 + loupe: 3.1.2 + pathval: 2.0.0 + + chalk@1.1.3: + dependencies: + ansi-styles: 2.2.1 + escape-string-regexp: 1.0.5 + has-ansi: 2.0.0 + strip-ansi: 3.0.1 + supports-color: 2.0.0 + + chalk@2.4.2: + dependencies: + ansi-styles: 3.2.1 + escape-string-regexp: 1.0.5 + supports-color: 5.5.0 + + chalk@4.1.2: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + chalk@5.4.1: {} + + char-regex@1.0.2: {} + + charm@1.0.2: + dependencies: + inherits: 2.0.4 + + check-error@2.1.1: {} + + chokidar@4.0.3: + dependencies: + readdirp: 4.0.2 + + chownr@2.0.0: {} + + chrome-debugging-client@2.0.0(devtools-protocol@0.0.975963): + dependencies: + '@tracerbench/find-chrome': 2.0.0 + '@tracerbench/message-transport': 2.0.0 + '@tracerbench/protocol-connection': 2.0.0(devtools-protocol@0.0.975963) + '@tracerbench/spawn': 2.0.0 + '@tracerbench/spawn-chrome': 2.0.0 + '@tracerbench/websocket-message-transport': 2.0.0 + debug: 4.4.1(supports-color@8.1.1) + devtools-protocol: 0.0.975963 + race-cancellation: 0.4.1 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + chrome-launcher@0.13.4: + dependencies: + '@types/node': 22.13.4 + escape-string-regexp: 1.0.5 + is-wsl: 2.2.0 + lighthouse-logger: 1.4.2 + mkdirp: 0.5.6 + rimraf: 3.0.2 + transitivePeerDependencies: + - supports-color + + chromium-bidi@0.11.0(devtools-protocol@0.0.1367902): + dependencies: + devtools-protocol: 0.0.1367902 + mitt: 3.0.1 + zod: 3.23.8 + + chromium-bidi@5.1.0(devtools-protocol@0.0.1464554): + dependencies: + devtools-protocol: 0.0.1464554 + mitt: 3.0.1 + zod: 3.25.72 + + clean-css@5.3.3: + dependencies: + source-map: 0.6.1 + + clean-stack@2.2.0: {} + + clean-stack@3.0.1: + dependencies: + escape-string-regexp: 4.0.0 + + cli-boxes@2.2.1: {} + + cli-boxes@3.0.0: {} + + cli-columns@4.0.0: + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + + cli-cursor@2.1.0: + dependencies: + restore-cursor: 2.0.0 + + cli-cursor@5.0.0: + dependencies: + restore-cursor: 5.1.0 + + cli-highlight@2.1.11: + dependencies: + chalk: 4.1.2 + highlight.js: 10.7.3 + mz: 2.7.0 + parse5: 5.1.1 + parse5-htmlparser2-tree-adapter: 6.0.1 + yargs: 16.2.0 + + cli-progress@3.12.0: + dependencies: + string-width: 4.2.3 + + cli-spinners@2.9.2: {} + + cli-table3@0.6.5: + dependencies: + string-width: 4.2.3 + optionalDependencies: + '@colors/colors': 1.5.0 + + cli-truncate@0.2.1: + dependencies: + slice-ansi: 0.0.4 + string-width: 1.0.2 + + cli-truncate@2.1.0: + dependencies: + slice-ansi: 3.0.0 + string-width: 4.2.3 + + cliui@7.0.4: + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + + cliui@8.0.1: + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + + clone-response@1.0.3: + dependencies: + mimic-response: 1.0.1 + + clone@1.0.4: {} + + code-point-at@1.1.0: {} + + color-convert@1.9.3: + dependencies: + color-name: 1.1.3 + + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-name@1.1.3: {} + + color-name@1.1.4: {} + + color-support@1.1.3: {} + + colord@2.9.3: {} + + comlink@4.4.2: {} + + commander@10.0.1: {} + + commander@2.20.3: {} + + commander@4.1.1: {} + + commander@7.2.0: {} + + comment-parser@1.4.1: {} + + common-path-prefix@3.0.0: {} + + commondir@1.0.1: {} + + compress-commons@4.1.2: + dependencies: + buffer-crc32: 0.2.13 + crc32-stream: 4.0.3 + normalize-path: 3.0.0 + readable-stream: 3.6.2 + + compressible@2.0.18: + dependencies: + mime-db: 1.53.0 + + compression@1.7.5: + dependencies: + bytes: 3.1.2 + compressible: 2.0.18 + debug: 2.6.9 + negotiator: 0.6.4 + on-headers: 1.0.2 + safe-buffer: 5.2.1 + vary: 1.1.2 + transitivePeerDependencies: + - supports-color + + concat-map@0.0.1: {} + + concat-with-sourcemaps@1.1.0: + dependencies: + source-map: 0.6.1 + + confbox@0.1.8: {} + + config-chain@1.1.13: + dependencies: + ini: 1.3.8 + proto-list: 1.2.4 + + console-control-strings@1.1.0: {} + + consolidate@0.16.0(ejs@3.1.10)(handlebars@4.7.8)(lodash@4.17.21)(mustache@4.2.0)(underscore@1.13.7): + dependencies: + bluebird: 3.7.2 + optionalDependencies: + ejs: 3.1.10 + handlebars: 4.7.8 + lodash: 4.17.21 + mustache: 4.2.0 + underscore: 1.13.7 + + content-disposition@0.5.4: + dependencies: + safe-buffer: 5.2.1 + + content-type@1.0.5: {} + + convert-source-map@2.0.0: {} + + cookie-es@1.2.2: {} + + cookie-signature@1.0.6: {} + + cookie@0.7.1: {} + + cookie@0.7.2: {} + + core-js-compat@3.43.0: + dependencies: + browserslist: 4.25.1 + + core-js@3.39.0: {} + + core-util-is@1.0.3: {} + + cors@2.8.5: + dependencies: + object-assign: 4.1.1 + vary: 1.1.2 + + cosmiconfig@7.1.0: + dependencies: + '@types/parse-json': 4.0.2 + import-fresh: 3.3.0 + parse-json: 5.2.0 + path-type: 4.0.0 + yaml: 1.10.2 + + cosmiconfig@9.0.0(typescript@5.7.3): + dependencies: + env-paths: 2.2.1 + import-fresh: 3.3.1 + js-yaml: 4.1.0 + parse-json: 5.2.0 + optionalDependencies: + typescript: 5.7.3 + + crc-32@1.2.2: {} + + crc32-stream@4.0.3: + dependencies: + crc-32: 1.2.2 + readable-stream: 3.6.2 + + create-require@1.1.1: {} + + cross-spawn@6.0.6: + dependencies: + nice-try: 1.0.5 + path-key: 2.0.1 + semver: 5.7.2 + shebang-command: 1.2.0 + which: 1.3.1 + + cross-spawn@7.0.6: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + + crossws@0.3.5: + dependencies: + uncrypto: 0.1.3 + + crypto-random-string@2.0.0: {} + + css-declaration-sorter@6.4.1(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + + css-select@4.3.0: + dependencies: + boolbase: 1.0.0 + css-what: 6.1.0 + domhandler: 4.3.1 + domutils: 2.8.0 + nth-check: 2.1.1 + + css-tree@1.1.3: + dependencies: + mdn-data: 2.0.14 + source-map: 0.6.1 + + css-what@6.1.0: {} + + cssesc@3.0.0: {} + + cssnano-preset-default@5.2.14(postcss@8.5.3): + dependencies: + css-declaration-sorter: 6.4.1(postcss@8.5.3) + cssnano-utils: 3.1.0(postcss@8.5.3) + postcss: 8.5.3 + postcss-calc: 8.2.4(postcss@8.5.3) + postcss-colormin: 5.3.1(postcss@8.5.3) + postcss-convert-values: 5.1.3(postcss@8.5.3) + postcss-discard-comments: 5.1.2(postcss@8.5.3) + postcss-discard-duplicates: 5.1.0(postcss@8.5.3) + postcss-discard-empty: 5.1.1(postcss@8.5.3) + postcss-discard-overridden: 5.1.0(postcss@8.5.3) + postcss-merge-longhand: 5.1.7(postcss@8.5.3) + postcss-merge-rules: 5.1.4(postcss@8.5.3) + postcss-minify-font-values: 5.1.0(postcss@8.5.3) + postcss-minify-gradients: 5.1.1(postcss@8.5.3) + postcss-minify-params: 5.1.4(postcss@8.5.3) + postcss-minify-selectors: 5.2.1(postcss@8.5.3) + postcss-normalize-charset: 5.1.0(postcss@8.5.3) + postcss-normalize-display-values: 5.1.0(postcss@8.5.3) + postcss-normalize-positions: 5.1.1(postcss@8.5.3) + postcss-normalize-repeat-style: 5.1.1(postcss@8.5.3) + postcss-normalize-string: 5.1.0(postcss@8.5.3) + postcss-normalize-timing-functions: 5.1.0(postcss@8.5.3) + postcss-normalize-unicode: 5.1.1(postcss@8.5.3) + postcss-normalize-url: 5.1.0(postcss@8.5.3) + postcss-normalize-whitespace: 5.1.1(postcss@8.5.3) + postcss-ordered-values: 5.1.3(postcss@8.5.3) + postcss-reduce-initial: 5.1.2(postcss@8.5.3) + postcss-reduce-transforms: 5.1.0(postcss@8.5.3) + postcss-svgo: 5.1.0(postcss@8.5.3) + postcss-unique-selectors: 5.1.1(postcss@8.5.3) + + cssnano-utils@3.1.0(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + + cssnano@5.1.15(postcss@8.5.3): + dependencies: + cssnano-preset-default: 5.2.14(postcss@8.5.3) + lilconfig: 2.1.0 + postcss: 8.5.3 + yaml: 1.10.2 + + csso@4.2.0: + dependencies: + css-tree: 1.1.3 + + d3-array@2.12.1: + dependencies: + internmap: 1.0.1 + + d3-array@3.2.4: + dependencies: + internmap: 2.0.3 + + d3-color@3.1.0: {} + + d3-format@2.0.0: {} + + d3-hierarchy@3.1.2: {} + + d3-interpolate@2.0.1: + dependencies: + d3-color: 3.1.0 + + d3-scale@3.3.0: + dependencies: + d3-array: 2.12.1 + d3-format: 2.0.0 + d3-interpolate: 2.0.1 + d3-time: 2.1.1 + d3-time-format: 3.0.0 + + d3-time-format@3.0.0: + dependencies: + d3-time: 2.1.1 + + d3-time@2.1.1: + dependencies: + d3-array: 2.12.1 + + dag-map@2.0.2: {} + + data-uri-to-buffer@2.0.2: {} + + data-uri-to-buffer@6.0.2: {} + + data-view-buffer@1.0.2: + dependencies: + call-bound: 1.0.3 + es-errors: 1.3.0 + is-data-view: 1.0.2 + + data-view-byte-length@1.0.2: + dependencies: + call-bound: 1.0.3 + es-errors: 1.3.0 + is-data-view: 1.0.2 + + data-view-byte-offset@1.0.1: + dependencies: + call-bound: 1.0.3 + es-errors: 1.3.0 + is-data-view: 1.0.2 + + date-fns@1.30.1: {} + + debug@2.6.9: + dependencies: + ms: 2.0.0 + + debug@3.2.7: + dependencies: + ms: 2.1.3 + + debug@4.3.7: + dependencies: + ms: 2.1.3 + + debug@4.4.0: + dependencies: + ms: 2.1.3 + + debug@4.4.1: + dependencies: + ms: 2.1.3 + + debug@4.4.1(supports-color@8.1.1): + dependencies: + ms: 2.1.3 + optionalDependencies: + supports-color: 8.1.1 + + decamelize-keys@1.1.1: + dependencies: + decamelize: 1.2.0 + map-obj: 1.0.1 + + decamelize@1.2.0: {} + + decamelize@4.0.0: {} + + decompress-response@6.0.0: + dependencies: + mimic-response: 3.1.0 + + deep-eql@5.0.2: {} + + deep-extend@0.6.0: {} + + deep-is@0.1.4: {} + + deepmerge-ts@5.1.0: {} + + deepmerge@4.3.1: {} + + default-browser-id@5.0.0: {} + + default-browser@5.2.1: + dependencies: + bundle-name: 4.1.0 + default-browser-id: 5.0.0 + + defaults@1.0.4: + dependencies: + clone: 1.0.4 + + defer-to-connect@2.0.1: {} + + define-data-property@1.1.4: + dependencies: + es-define-property: 1.0.1 + es-errors: 1.3.0 + gopd: 1.2.0 + + define-lazy-prop@3.0.0: {} + + define-properties@1.2.1: + dependencies: + define-data-property: 1.1.4 + has-property-descriptors: 1.0.2 + object-keys: 1.1.1 + + defu@6.1.4: {} + + degenerator@5.0.1: + dependencies: + ast-types: 0.13.4 + escodegen: 2.1.0 + esprima: 4.0.1 + + delegates@1.0.0: {} + + depd@2.0.0: {} + + destr@2.0.5: {} + + destroy@1.2.0: {} + + detect-indent@7.0.1: {} + + detect-libc@2.0.3: {} + + devtools-protocol@0.0.1367902: {} + + devtools-protocol@0.0.1464554: {} + + devtools-protocol@0.0.975963: {} + + diff@4.0.2: {} + + diff@7.0.0: {} + + dir-glob@3.0.1: + dependencies: + path-type: 4.0.0 + + doctrine@2.1.0: + dependencies: + esutils: 2.0.3 + + doctrine@3.0.0: + dependencies: + esutils: 2.0.3 + + dom-serializer@1.4.1: + dependencies: + domelementtype: 2.3.0 + domhandler: 4.3.1 + entities: 2.2.0 + + dom-types@1.1.2: {} + + domelementtype@2.3.0: {} + + domhandler@4.3.1: + dependencies: + domelementtype: 2.3.0 + + domutils@2.8.0: + dependencies: + dom-serializer: 1.4.1 + domelementtype: 2.3.0 + domhandler: 4.3.1 + + dot-case@3.0.4: + dependencies: + no-case: 3.0.4 + tslib: 2.8.1 + + dotenv-cli@7.4.4: + dependencies: + cross-spawn: 7.0.6 + dotenv: 16.4.7 + dotenv-expand: 10.0.0 + minimist: 1.2.8 + + dotenv-expand@10.0.0: {} + + dotenv@16.4.7: {} + + dunder-proto@1.0.1: + dependencies: + call-bind-apply-helpers: 1.0.1 + es-errors: 1.3.0 + gopd: 1.2.0 + + eastasianwidth@0.2.0: {} + + easy-table@1.2.0: + dependencies: + ansi-regex: 5.0.1 + optionalDependencies: + wcwidth: 1.0.1 + + ee-first@1.1.1: {} + + eight-colors@1.3.1: {} + + ejs@3.1.10: + dependencies: + jake: 10.9.2 + + electron-to-chromium@1.5.178: {} + + elegant-spinner@1.0.1: {} + + emoji-regex@10.4.0: {} + + emoji-regex@8.0.0: {} + + emoji-regex@9.2.2: {} + + encodeurl@1.0.2: {} + + encodeurl@2.0.0: {} + + encoding@0.1.13: + dependencies: + iconv-lite: 0.6.3 + optional: true + + end-of-stream@1.4.4: + dependencies: + once: 1.4.0 + + end-of-stream@1.4.5: + dependencies: + once: 1.4.0 + + engine.io-parser@5.2.3: {} + + engine.io@6.6.2: + dependencies: + '@types/cookie': 0.4.1 + '@types/cors': 2.8.17 + '@types/node': 22.13.4 + accepts: 1.3.8 + base64id: 2.0.0 + cookie: 0.7.2 + cors: 2.8.5 + debug: 4.3.7 + engine.io-parser: 5.2.3 + ws: 8.17.1 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + enhanced-resolve@5.18.0: + dependencies: + graceful-fs: 4.2.11 + tapable: 2.2.1 + + enquirer@2.4.1: + dependencies: + ansi-colors: 4.1.1 + strip-ansi: 6.0.1 + + ensure-posix-path@1.1.1: {} + + entities@2.2.0: {} + + entities@4.5.0: {} + + env-paths@2.2.1: {} + + err-code@2.0.3: {} + + error-ex@1.3.2: + dependencies: + is-arrayish: 0.2.1 + + es-abstract@1.23.8: + dependencies: + array-buffer-byte-length: 1.0.2 + arraybuffer.prototype.slice: 1.0.4 + available-typed-arrays: 1.0.7 + call-bind: 1.0.8 + call-bound: 1.0.3 + data-view-buffer: 1.0.2 + data-view-byte-length: 1.0.2 + data-view-byte-offset: 1.0.1 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.0.0 + es-set-tostringtag: 2.0.3 + es-to-primitive: 1.3.0 + function.prototype.name: 1.1.8 + get-intrinsic: 1.2.6 + get-symbol-description: 1.1.0 + globalthis: 1.0.4 + gopd: 1.2.0 + has-property-descriptors: 1.0.2 + has-proto: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.2 + internal-slot: 1.1.0 + is-array-buffer: 3.0.5 + is-callable: 1.2.7 + is-data-view: 1.0.2 + is-regex: 1.2.1 + is-shared-array-buffer: 1.0.4 + is-string: 1.1.1 + is-typed-array: 1.1.15 + is-weakref: 1.1.0 + math-intrinsics: 1.1.0 + object-inspect: 1.13.3 + object-keys: 1.1.1 + object.assign: 4.1.7 + own-keys: 1.0.1 + regexp.prototype.flags: 1.5.3 + safe-array-concat: 1.1.3 + safe-push-apply: 1.0.0 + safe-regex-test: 1.1.0 + string.prototype.trim: 1.2.10 + string.prototype.trimend: 1.0.9 + string.prototype.trimstart: 1.0.8 + typed-array-buffer: 1.0.3 + typed-array-byte-length: 1.0.3 + typed-array-byte-offset: 1.0.4 + typed-array-length: 1.0.7 + unbox-primitive: 1.1.0 + which-typed-array: 1.1.18 + + es-define-property@1.0.1: {} + + es-errors@1.3.0: {} + + es-module-lexer@1.6.0: {} + + es-object-atoms@1.0.0: + dependencies: + es-errors: 1.3.0 + + es-set-tostringtag@2.0.3: + dependencies: + get-intrinsic: 1.2.6 + has-tostringtag: 1.0.2 + hasown: 2.0.2 + + es-shim-unscopables@1.0.2: + dependencies: + hasown: 2.0.2 + + es-to-primitive@1.3.0: + dependencies: + is-callable: 1.2.7 + is-date-object: 1.1.0 + is-symbol: 1.1.1 + + esbuild@0.25.5: + optionalDependencies: + '@esbuild/aix-ppc64': 0.25.5 + '@esbuild/android-arm': 0.25.5 + '@esbuild/android-arm64': 0.25.5 + '@esbuild/android-x64': 0.25.5 + '@esbuild/darwin-arm64': 0.25.5 + '@esbuild/darwin-x64': 0.25.5 + '@esbuild/freebsd-arm64': 0.25.5 + '@esbuild/freebsd-x64': 0.25.5 + '@esbuild/linux-arm': 0.25.5 + '@esbuild/linux-arm64': 0.25.5 + '@esbuild/linux-ia32': 0.25.5 + '@esbuild/linux-loong64': 0.25.5 + '@esbuild/linux-mips64el': 0.25.5 + '@esbuild/linux-ppc64': 0.25.5 + '@esbuild/linux-riscv64': 0.25.5 + '@esbuild/linux-s390x': 0.25.5 + '@esbuild/linux-x64': 0.25.5 + '@esbuild/netbsd-arm64': 0.25.5 + '@esbuild/netbsd-x64': 0.25.5 + '@esbuild/openbsd-arm64': 0.25.5 + '@esbuild/openbsd-x64': 0.25.5 + '@esbuild/sunos-x64': 0.25.5 + '@esbuild/win32-arm64': 0.25.5 + '@esbuild/win32-ia32': 0.25.5 + '@esbuild/win32-x64': 0.25.5 + + escalade@3.2.0: {} + + escape-html@1.0.3: {} + + escape-string-regexp@1.0.5: {} + + escape-string-regexp@4.0.0: {} + + escodegen@2.1.0: + dependencies: + esprima: 4.0.1 + estraverse: 5.3.0 + esutils: 2.0.3 + optionalDependencies: + source-map: 0.6.1 + + eslint-compat-utils@0.5.1(eslint@9.20.1(jiti@2.4.2)): + dependencies: + eslint: 9.20.1(jiti@2.4.2) + semver: 7.7.2 + + eslint-compat-utils@0.6.4(eslint@9.20.1(jiti@2.4.2)): + dependencies: + eslint: 9.20.1(jiti@2.4.2) + semver: 7.7.2 + + eslint-config-flat-gitignore@1.0.0(eslint@9.20.1(jiti@2.4.2)): + dependencies: + '@eslint/compat': 1.2.5(eslint@9.20.1(jiti@2.4.2)) + eslint: 9.20.1(jiti@2.4.2) + find-up-simple: 1.0.0 + + eslint-config-prettier@10.0.1(eslint@9.20.1(jiti@2.4.2)): + dependencies: + eslint: 9.20.1(jiti@2.4.2) + + eslint-import-resolver-node@0.3.9: + dependencies: + debug: 3.2.7 + is-core-module: 2.16.1 + resolve: 1.22.10 + transitivePeerDependencies: + - supports-color + + eslint-import-resolver-typescript@3.8.2(eslint-plugin-import-x@4.6.1(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3))(eslint-plugin-import@2.31.0)(eslint@9.20.1(jiti@2.4.2)): + dependencies: + '@nolyfill/is-core-module': 1.0.39 + debug: 4.4.0 + enhanced-resolve: 5.18.0 + eslint: 9.20.1(jiti@2.4.2) + get-tsconfig: 4.10.0 + is-bun-module: 1.3.0 + stable-hash: 0.0.4 + tinyglobby: 0.2.12 + optionalDependencies: + eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.35.1(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3))(eslint-import-resolver-typescript@3.8.2)(eslint@9.20.1(jiti@2.4.2)) + eslint-plugin-import-x: 4.6.1(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3) + transitivePeerDependencies: + - supports-color + + eslint-interactive@11.1.0(eslint@9.20.1(jiti@2.4.2)): + dependencies: + boxen: 8.0.1 + chalk: 5.4.1 + comlink: 4.4.2 + enquirer: 2.4.1 + eslint: 9.20.1(jiti@2.4.2) + estraverse: 5.3.0 + find-cache-dir: 5.0.0 + is-installed-globally: 1.0.0 + ora: 8.1.1 + table: 6.9.0 + terminal-link: 3.0.0 + yargs: 17.7.2 + + eslint-json-compat-utils@0.2.1(eslint@9.20.1(jiti@2.4.2))(jsonc-eslint-parser@2.4.0): + dependencies: + eslint: 9.20.1(jiti@2.4.2) + esquery: 1.6.0 + jsonc-eslint-parser: 2.4.0 + + eslint-module-utils@2.12.0(@typescript-eslint/parser@8.35.1(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.8.2)(eslint@9.20.1(jiti@2.4.2)): + dependencies: + debug: 3.2.7 + optionalDependencies: + '@typescript-eslint/parser': 8.35.1(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3) + eslint: 9.20.1(jiti@2.4.2) + eslint-import-resolver-node: 0.3.9 + eslint-import-resolver-typescript: 3.8.2(eslint-plugin-import-x@4.6.1(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3))(eslint-plugin-import@2.31.0)(eslint@9.20.1(jiti@2.4.2)) + transitivePeerDependencies: + - supports-color + + eslint-plugin-es-x@7.8.0(eslint@9.20.1(jiti@2.4.2)): + dependencies: + '@eslint-community/eslint-utils': 4.4.1(eslint@9.20.1(jiti@2.4.2)) + '@eslint-community/regexpp': 4.12.1 + eslint: 9.20.1(jiti@2.4.2) + eslint-compat-utils: 0.5.1(eslint@9.20.1(jiti@2.4.2)) + + eslint-plugin-import-x@4.6.1(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3): + dependencies: + '@types/doctrine': 0.0.9 + '@typescript-eslint/scope-manager': 8.19.0 + '@typescript-eslint/utils': 8.35.1(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3) + debug: 4.4.0 + doctrine: 3.0.0 + enhanced-resolve: 5.18.0 + eslint: 9.20.1(jiti@2.4.2) + eslint-import-resolver-node: 0.3.9 + get-tsconfig: 4.8.1 + is-glob: 4.0.3 + minimatch: 9.0.5 + semver: 7.7.2 + stable-hash: 0.0.4 + tslib: 2.8.1 + transitivePeerDependencies: + - supports-color + - typescript + + eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.35.1(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3))(eslint-import-resolver-typescript@3.8.2)(eslint@9.20.1(jiti@2.4.2)): + dependencies: + '@rtsao/scc': 1.1.0 + array-includes: 3.1.8 + array.prototype.findlastindex: 1.2.5 + array.prototype.flat: 1.3.3 + array.prototype.flatmap: 1.3.3 + debug: 3.2.7 + doctrine: 2.1.0 + eslint: 9.20.1(jiti@2.4.2) + eslint-import-resolver-node: 0.3.9 + eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.35.1(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.8.2)(eslint@9.20.1(jiti@2.4.2)) + hasown: 2.0.2 + is-core-module: 2.16.1 + is-glob: 4.0.3 + minimatch: 3.1.2 + object.fromentries: 2.0.8 + object.groupby: 1.0.3 + object.values: 1.2.1 + semver: 6.3.1 + string.prototype.trimend: 1.0.9 + tsconfig-paths: 3.15.0 + optionalDependencies: + '@typescript-eslint/parser': 8.35.1(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3) + transitivePeerDependencies: + - eslint-import-resolver-typescript + - eslint-import-resolver-webpack + - supports-color + + eslint-plugin-jsonc@2.19.1(eslint@9.20.1(jiti@2.4.2)): + dependencies: + '@eslint-community/eslint-utils': 4.4.1(eslint@9.20.1(jiti@2.4.2)) + eslint: 9.20.1(jiti@2.4.2) + eslint-compat-utils: 0.6.4(eslint@9.20.1(jiti@2.4.2)) + eslint-json-compat-utils: 0.2.1(eslint@9.20.1(jiti@2.4.2))(jsonc-eslint-parser@2.4.0) + espree: 9.6.1 + graphemer: 1.4.0 + jsonc-eslint-parser: 2.4.0 + natural-compare: 1.4.0 + synckit: 0.6.2 + transitivePeerDependencies: + - '@eslint/json' + + eslint-plugin-n@17.15.1(eslint@9.20.1(jiti@2.4.2)): + dependencies: + '@eslint-community/eslint-utils': 4.4.1(eslint@9.20.1(jiti@2.4.2)) + enhanced-resolve: 5.18.0 + eslint: 9.20.1(jiti@2.4.2) + eslint-plugin-es-x: 7.8.0(eslint@9.20.1(jiti@2.4.2)) + get-tsconfig: 4.8.1 + globals: 15.14.0 + ignore: 5.3.2 + minimatch: 9.0.5 + semver: 7.7.2 + + eslint-plugin-qunit@8.1.2(eslint@9.20.1(jiti@2.4.2)): + dependencies: + eslint-utils: 3.0.0(eslint@9.20.1(jiti@2.4.2)) + requireindex: 1.2.0 + transitivePeerDependencies: + - eslint + + eslint-plugin-regexp@2.7.0(eslint@9.20.1(jiti@2.4.2)): + dependencies: + '@eslint-community/eslint-utils': 4.4.1(eslint@9.20.1(jiti@2.4.2)) + '@eslint-community/regexpp': 4.12.1 + comment-parser: 1.4.1 + eslint: 9.20.1(jiti@2.4.2) + jsdoc-type-pratt-parser: 4.1.0 + refa: 0.12.1 + regexp-ast-analysis: 0.7.1 + scslre: 0.3.0 + + eslint-plugin-simple-import-sort@12.1.1(eslint@9.20.1(jiti@2.4.2)): + dependencies: + eslint: 9.20.1(jiti@2.4.2) + + eslint-plugin-unused-imports@4.1.4(@typescript-eslint/eslint-plugin@8.24.1(@typescript-eslint/parser@8.24.1(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3))(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3))(eslint@9.20.1(jiti@2.4.2)): + dependencies: + eslint: 9.20.1(jiti@2.4.2) + optionalDependencies: + '@typescript-eslint/eslint-plugin': 8.24.1(@typescript-eslint/parser@8.24.1(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3))(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3) + + eslint-plugin-unused-imports@4.1.4(@typescript-eslint/eslint-plugin@8.24.1(@typescript-eslint/parser@8.35.1(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3))(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3))(eslint@9.20.1(jiti@2.4.2)): + dependencies: + eslint: 9.20.1(jiti@2.4.2) + optionalDependencies: + '@typescript-eslint/eslint-plugin': 8.24.1(@typescript-eslint/parser@8.35.1(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3))(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3) + + eslint-scope@8.2.0: + dependencies: + esrecurse: 4.3.0 + estraverse: 5.3.0 + + eslint-utils@3.0.0(eslint@9.20.1(jiti@2.4.2)): + dependencies: + eslint: 9.20.1(jiti@2.4.2) + eslint-visitor-keys: 2.1.0 + + eslint-visitor-keys@2.1.0: {} + + eslint-visitor-keys@3.4.3: {} + + eslint-visitor-keys@4.2.0: {} + + eslint-visitor-keys@4.2.1: {} + + eslint@9.20.1(jiti@2.4.2): + dependencies: + '@eslint-community/eslint-utils': 4.4.1(eslint@9.20.1(jiti@2.4.2)) + '@eslint-community/regexpp': 4.12.1 + '@eslint/config-array': 0.19.1 + '@eslint/core': 0.11.0 + '@eslint/eslintrc': 3.2.0 + '@eslint/js': 9.20.0 + '@eslint/plugin-kit': 0.2.5 + '@humanfs/node': 0.16.6 + '@humanwhocodes/module-importer': 1.0.1 + '@humanwhocodes/retry': 0.4.1 + '@types/estree': 1.0.6 + '@types/json-schema': 7.0.15 + ajv: 6.12.6 + chalk: 4.1.2 + cross-spawn: 7.0.6 + debug: 4.4.0 + escape-string-regexp: 4.0.0 + eslint-scope: 8.2.0 + eslint-visitor-keys: 4.2.0 + espree: 10.3.0 + esquery: 1.6.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 8.0.0 + find-up: 5.0.0 + glob-parent: 6.0.2 + ignore: 5.3.2 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + json-stable-stringify-without-jsonify: 1.0.1 + lodash.merge: 4.6.2 + minimatch: 3.1.2 + natural-compare: 1.4.0 + optionator: 0.9.4 + optionalDependencies: + jiti: 2.4.2 + transitivePeerDependencies: + - supports-color + + esno@0.16.3: + dependencies: + tsx: 3.14.0 + + espree@10.3.0: + dependencies: + acorn: 8.14.0 + acorn-jsx: 5.3.2(acorn@8.14.0) + eslint-visitor-keys: 4.2.0 + + espree@9.6.1: + dependencies: + acorn: 8.14.0 + acorn-jsx: 5.3.2(acorn@8.14.0) + eslint-visitor-keys: 3.4.3 + + esprima@4.0.1: {} + + esquery@1.6.0: + dependencies: + estraverse: 5.3.0 + + esrecurse@4.3.0: + dependencies: + estraverse: 5.3.0 + + estraverse@5.3.0: {} + + estree-walker@0.6.1: {} + + estree-walker@2.0.2: {} + + estree-walker@3.0.3: + dependencies: + '@types/estree': 1.0.6 + + esutils@2.0.3: {} + + etag@1.8.1: {} + + eventemitter3@4.0.7: {} + + events-to-array@1.1.2: {} + + execa@1.0.0: + dependencies: + cross-spawn: 6.0.6 + get-stream: 4.1.0 + is-stream: 1.1.0 + npm-run-path: 2.0.2 + p-finally: 1.0.0 + signal-exit: 3.0.7 + strip-eof: 1.0.0 + + execa@4.1.0: + dependencies: + cross-spawn: 7.0.6 + get-stream: 5.2.0 + human-signals: 1.1.1 + is-stream: 2.0.1 + merge-stream: 2.0.0 + npm-run-path: 4.0.1 + onetime: 5.1.2 + signal-exit: 3.0.7 + strip-final-newline: 2.0.0 + + execa@5.1.1: + dependencies: + cross-spawn: 7.0.6 + get-stream: 6.0.1 + human-signals: 2.1.0 + is-stream: 2.0.1 + merge-stream: 2.0.0 + npm-run-path: 4.0.1 + onetime: 5.1.2 + signal-exit: 3.0.7 + strip-final-newline: 2.0.0 + + execa@6.1.0: + dependencies: + cross-spawn: 7.0.6 + get-stream: 6.0.1 + human-signals: 3.0.1 + is-stream: 3.0.0 + merge-stream: 2.0.0 + npm-run-path: 5.3.0 + onetime: 6.0.0 + signal-exit: 3.0.7 + strip-final-newline: 3.0.0 + + execa@7.1.1: + dependencies: + cross-spawn: 7.0.6 + get-stream: 6.0.1 + human-signals: 4.3.1 + is-stream: 3.0.0 + merge-stream: 2.0.0 + npm-run-path: 5.3.0 + onetime: 6.0.0 + signal-exit: 3.0.7 + strip-final-newline: 3.0.0 + + execa@7.2.0: + dependencies: + cross-spawn: 7.0.6 + get-stream: 6.0.1 + human-signals: 4.3.1 + is-stream: 3.0.0 + merge-stream: 2.0.0 + npm-run-path: 5.3.0 + onetime: 6.0.0 + signal-exit: 3.0.7 + strip-final-newline: 3.0.0 + + execa@9.5.2: + dependencies: + '@sindresorhus/merge-streams': 4.0.0 + cross-spawn: 7.0.6 + figures: 6.1.0 + get-stream: 9.0.1 + human-signals: 8.0.0 + is-plain-obj: 4.1.0 + is-stream: 4.0.1 + npm-run-path: 6.0.0 + pretty-ms: 9.2.0 + signal-exit: 4.1.0 + strip-final-newline: 4.0.0 + yoctocolors: 2.1.1 + + expect-type@1.1.0: {} + + express@4.21.2: + dependencies: + accepts: 1.3.8 + array-flatten: 1.1.1 + body-parser: 1.20.3 + content-disposition: 0.5.4 + content-type: 1.0.5 + cookie: 0.7.1 + cookie-signature: 1.0.6 + debug: 2.6.9 + depd: 2.0.0 + encodeurl: 2.0.0 + escape-html: 1.0.3 + etag: 1.8.1 + finalhandler: 1.3.1 + fresh: 0.5.2 + http-errors: 2.0.0 + merge-descriptors: 1.0.3 + methods: 1.1.2 + on-finished: 2.4.1 + parseurl: 1.3.3 + path-to-regexp: 0.1.12 + proxy-addr: 2.0.7 + qs: 6.13.0 + range-parser: 1.2.1 + safe-buffer: 5.2.1 + send: 0.19.0 + serve-static: 1.16.2 + setprototypeof: 1.2.0 + statuses: 2.0.1 + type-is: 1.6.18 + utils-merge: 1.0.1 + vary: 1.1.2 + transitivePeerDependencies: + - supports-color + + extract-zip@2.0.1: + dependencies: + debug: 4.4.0 + get-stream: 5.2.0 + yauzl: 2.10.0 + optionalDependencies: + '@types/yauzl': 2.10.3 + transitivePeerDependencies: + - supports-color + + fast-content-type-parse@2.0.1: {} + + fast-deep-equal@3.1.3: {} + + fast-fifo@1.3.2: {} + + fast-glob@3.3.3: + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.8 + + fast-json-stable-stringify@2.1.0: {} + + fast-levenshtein@2.0.6: {} + + fast-safe-stringify@2.1.1: {} + + fast-uri@3.0.5: {} + + fastq@1.18.0: + dependencies: + reusify: 1.0.4 + + fd-slicer@1.1.0: + dependencies: + pend: 1.2.0 + + fdir@6.4.3(picomatch@4.0.2): + optionalDependencies: + picomatch: 4.0.2 + + fdir@6.4.6(picomatch@4.0.2): + optionalDependencies: + picomatch: 4.0.2 + + figures@1.7.0: + dependencies: + escape-string-regexp: 1.0.5 + object-assign: 4.1.1 + + figures@2.0.0: + dependencies: + escape-string-regexp: 1.0.5 + + figures@6.1.0: + dependencies: + is-unicode-supported: 2.1.0 + + file-entry-cache@8.0.0: + dependencies: + flat-cache: 4.0.1 + + filelist@1.0.4: + dependencies: + minimatch: 5.1.6 + + fill-range@7.1.1: + dependencies: + to-regex-range: 5.0.1 + + finalhandler@1.3.1: + dependencies: + debug: 2.6.9 + encodeurl: 2.0.0 + escape-html: 1.0.3 + on-finished: 2.4.1 + parseurl: 1.3.3 + statuses: 2.0.1 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + + find-cache-dir@5.0.0: + dependencies: + common-path-prefix: 3.0.0 + pkg-dir: 7.0.0 + + find-up-simple@1.0.0: {} + + find-up@3.0.0: + dependencies: + locate-path: 3.0.0 + + find-up@4.1.0: + dependencies: + locate-path: 5.0.0 + path-exists: 4.0.0 + + find-up@5.0.0: + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 + + find-up@6.3.0: + dependencies: + locate-path: 7.2.0 + path-exists: 5.0.0 + + find-up@7.0.0: + dependencies: + locate-path: 7.2.0 + path-exists: 5.0.0 + unicorn-magic: 0.1.0 + + fireworm@0.7.2: + dependencies: + async: 0.2.10 + is-type: 0.0.1 + lodash.debounce: 3.1.1 + lodash.flatten: 3.0.2 + minimatch: 3.1.2 + + flat-cache@4.0.1: + dependencies: + flatted: 3.3.2 + keyv: 4.5.4 + + flat@5.0.2: {} + + flatted@3.3.2: {} + + follow-redirects@1.15.9: {} + + for-each@0.3.3: + dependencies: + is-callable: 1.2.7 + + foreground-child@3.3.0: + dependencies: + cross-spawn: 7.0.6 + signal-exit: 4.1.0 + + forwarded@0.2.0: {} + + fresh@0.5.2: {} + + fs-constants@1.0.0: {} + + fs-extra@10.1.0: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.1.0 + universalify: 2.0.1 + + fs-extra@11.3.0: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.1.0 + universalify: 2.0.1 + + fs-extra@8.1.0: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 4.0.0 + universalify: 0.1.2 + + fs-extra@9.1.0: + dependencies: + at-least-node: 1.0.0 + graceful-fs: 4.2.11 + jsonfile: 6.1.0 + universalify: 2.0.1 + + fs-minipass@2.1.0: + dependencies: + minipass: 3.3.6 + + fs.realpath@1.0.0: {} + + fsevents@2.3.3: + optional: true + + function-bind@1.1.2: {} + + function.prototype.name@1.1.8: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.3 + define-properties: 1.2.1 + functions-have-names: 1.2.3 + hasown: 2.0.2 + is-callable: 1.2.7 + + functions-have-names@1.2.3: {} + + gauge@4.0.4: + dependencies: + aproba: 2.0.0 + color-support: 1.1.3 + console-control-strings: 1.1.0 + has-unicode: 2.0.1 + signal-exit: 3.0.7 + string-width: 4.2.3 + strip-ansi: 6.0.1 + wide-align: 1.1.5 + + gauge@5.0.2: + dependencies: + aproba: 2.0.0 + color-support: 1.1.3 + console-control-strings: 1.1.0 + has-unicode: 2.0.1 + signal-exit: 4.1.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + wide-align: 1.1.5 + + generic-names@4.0.0: + dependencies: + loader-utils: 3.3.1 + + gensync@1.0.0-beta.2: {} + + get-caller-file@2.0.5: {} + + get-east-asian-width@1.3.0: {} + + get-intrinsic@1.2.6: + dependencies: + call-bind-apply-helpers: 1.0.1 + dunder-proto: 1.0.1 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.0.0 + function-bind: 1.1.2 + gopd: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.2 + math-intrinsics: 1.1.0 + + get-package-type@0.1.0: {} + + get-port-please@3.1.2: {} + + get-source@2.0.12: + dependencies: + data-uri-to-buffer: 2.0.2 + source-map: 0.6.1 + + get-stream@4.1.0: + dependencies: + pump: 3.0.2 + + get-stream@5.2.0: + dependencies: + pump: 3.0.2 + + get-stream@6.0.1: {} + + get-stream@9.0.1: + dependencies: + '@sec-ant/readable-stream': 0.4.1 + is-stream: 4.0.1 + + get-symbol-description@1.1.0: + dependencies: + call-bound: 1.0.3 + es-errors: 1.3.0 + get-intrinsic: 1.2.6 + + get-tsconfig@4.10.0: + dependencies: + resolve-pkg-maps: 1.0.0 + + get-tsconfig@4.10.1: + dependencies: + resolve-pkg-maps: 1.0.0 + optional: true + + get-tsconfig@4.8.1: + dependencies: + resolve-pkg-maps: 1.0.0 + + get-uri@6.0.4: + dependencies: + basic-ftp: 5.0.5 + data-uri-to-buffer: 6.0.2 + debug: 4.4.1 + transitivePeerDependencies: + - supports-color + + github-changelog@1.0.2: + dependencies: + '@manypkg/get-packages': 2.2.2 + chalk: 4.1.2 + cli-highlight: 2.1.11 + execa: 5.1.1 + hosted-git-info: 4.1.0 + make-fetch-happen: 9.1.0 + p-map: 3.0.0 + progress: 2.0.3 + yargs: 17.7.2 + transitivePeerDependencies: + - bluebird + - supports-color + + glob-parent@5.1.2: + dependencies: + is-glob: 4.0.3 + + glob-parent@6.0.2: + dependencies: + is-glob: 4.0.3 + + glob@10.2.3: + dependencies: + foreground-child: 3.3.0 + jackspeak: 2.3.6 + minimatch: 9.0.5 + minipass: 5.0.0 + path-scurry: 1.11.1 + + glob@10.4.5: + dependencies: + foreground-child: 3.3.0 + jackspeak: 3.4.3 + minimatch: 9.0.5 + minipass: 7.1.2 + package-json-from-dist: 1.0.1 + path-scurry: 1.11.1 + + glob@11.0.1: + dependencies: + foreground-child: 3.3.0 + jackspeak: 4.0.2 + minimatch: 10.0.1 + minipass: 7.1.2 + package-json-from-dist: 1.0.1 + path-scurry: 2.0.0 + + glob@7.2.3: + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + + global-directory@4.0.1: + dependencies: + ini: 4.1.1 + + globals@14.0.0: {} + + globals@15.14.0: {} + + globals@15.15.0: {} + + globalthis@1.0.4: + dependencies: + define-properties: 1.2.1 + gopd: 1.2.0 + + globalyzer@0.1.0: {} + + globby@11.1.0: + dependencies: + array-union: 2.1.0 + dir-glob: 3.0.1 + fast-glob: 3.3.3 + ignore: 5.3.2 + merge2: 1.4.1 + slash: 3.0.0 + + globby@14.1.0: + dependencies: + '@sindresorhus/merge-streams': 2.3.0 + fast-glob: 3.3.3 + ignore: 7.0.3 + path-type: 6.0.0 + slash: 5.1.0 + unicorn-magic: 0.3.0 + + globrex@0.1.2: {} + + gopd@1.2.0: {} + + got@11.8.6: + dependencies: + '@sindresorhus/is': 4.6.0 + '@szmarczak/http-timer': 4.0.6 + '@types/cacheable-request': 6.0.3 + '@types/responselike': 1.0.3 + cacheable-lookup: 5.0.4 + cacheable-request: 7.0.4 + decompress-response: 6.0.0 + http2-wrapper: 1.0.3 + lowercase-keys: 2.0.0 + p-cancelable: 2.1.1 + responselike: 2.0.1 + + graceful-fs@4.2.10: {} + + graceful-fs@4.2.11: {} + + graphemer@1.4.0: {} + + growly@1.3.0: {} + + h3@1.15.3: + dependencies: + cookie-es: 1.2.2 + crossws: 0.3.5 + defu: 6.1.4 + destr: 2.0.5 + iron-webcrypto: 1.2.1 + node-mock-http: 1.0.1 + radix3: 1.1.2 + ufo: 1.6.1 + uncrypto: 0.1.3 + + handlebars@4.7.8: + dependencies: + minimist: 1.2.8 + neo-async: 2.6.2 + source-map: 0.6.1 + wordwrap: 1.0.0 + optionalDependencies: + uglify-js: 3.19.3 + + hard-rejection@2.1.0: {} + + has-ansi@2.0.0: + dependencies: + ansi-regex: 2.1.1 + + has-bigints@1.1.0: {} + + has-flag@3.0.0: {} + + has-flag@4.0.0: {} + + has-property-descriptors@1.0.2: + dependencies: + es-define-property: 1.0.1 + + has-proto@1.2.0: + dependencies: + dunder-proto: 1.0.1 + + has-symbols@1.1.0: {} + + has-tostringtag@1.0.2: + dependencies: + has-symbols: 1.1.0 + + has-unicode@2.0.1: {} + + hasown@2.0.2: + dependencies: + function-bind: 1.1.2 + + he@1.2.0: {} + + highlight.js@10.7.3: {} + + hosted-git-info@2.8.9: {} + + hosted-git-info@4.1.0: + dependencies: + lru-cache: 6.0.0 + + hosted-git-info@7.0.2: + dependencies: + lru-cache: 10.4.3 + + hosted-git-info@8.0.2: + dependencies: + lru-cache: 10.4.3 + + html-minifier-terser@7.2.0: + dependencies: + camel-case: 4.1.2 + clean-css: 5.3.3 + commander: 10.0.1 + entities: 4.5.0 + param-case: 3.0.4 + relateurl: 0.2.7 + terser: 5.43.1 + + http-cache-semantics@4.1.1: {} + + http-call@5.3.0: + dependencies: + content-type: 1.0.5 + debug: 4.4.1(supports-color@8.1.1) + is-retry-allowed: 1.2.0 + is-stream: 2.0.1 + parse-json: 4.0.0 + tunnel-agent: 0.6.0 + transitivePeerDependencies: + - supports-color + + http-errors@2.0.0: + dependencies: + depd: 2.0.0 + inherits: 2.0.4 + setprototypeof: 1.2.0 + statuses: 2.0.1 + toidentifier: 1.0.1 + + http-proxy-agent@4.0.1: + dependencies: + '@tootallnate/once': 1.1.2 + agent-base: 6.0.2 + debug: 4.4.1(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + + http-proxy-agent@7.0.2: + dependencies: + agent-base: 7.1.3 + debug: 4.4.1 + transitivePeerDependencies: + - supports-color + + http-proxy@1.18.1: + dependencies: + eventemitter3: 4.0.7 + follow-redirects: 1.15.9 + requires-port: 1.0.0 + transitivePeerDependencies: + - debug + + http2-wrapper@1.0.3: + dependencies: + quick-lru: 5.1.1 + resolve-alpn: 1.2.1 + + https-proxy-agent@5.0.1: + dependencies: + agent-base: 6.0.2 + debug: 4.4.1(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + + https-proxy-agent@7.0.6: + dependencies: + agent-base: 7.1.3 + debug: 4.4.1 + transitivePeerDependencies: + - supports-color + + human-signals@1.1.1: {} + + human-signals@2.1.0: {} + + human-signals@3.0.1: {} + + human-signals@4.3.1: {} + + human-signals@8.0.0: {} + + humanize-ms@1.2.1: + dependencies: + ms: 2.1.3 + + hyperlinker@1.0.0: {} + + iconv-lite@0.4.24: + dependencies: + safer-buffer: 2.1.2 + + iconv-lite@0.6.3: + dependencies: + safer-buffer: 2.1.2 + optional: true + + icss-replace-symbols@1.1.0: {} + + icss-utils@5.1.0(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + + ieee754@1.2.1: {} + + ignore@5.3.2: {} + + ignore@7.0.3: {} + + import-cwd@3.0.0: + dependencies: + import-from: 3.0.0 + + import-fresh@3.3.0: + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + + import-fresh@3.3.1: + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + + import-from@3.0.0: + dependencies: + resolve-from: 5.0.0 + + imurmurhash@0.1.4: {} + + indent-string@3.2.0: {} + + indent-string@4.0.0: {} + + index-to-position@1.1.0: {} + + individual@3.0.0: {} + + infer-owner@1.0.4: {} + + inflight@1.0.6: + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + + inherits@2.0.3: {} + + inherits@2.0.4: {} + + ini@1.3.8: {} + + ini@3.0.1: {} + + ini@4.1.1: {} + + ini@5.0.0: {} + + internal-slot@1.1.0: + dependencies: + es-errors: 1.3.0 + hasown: 2.0.2 + side-channel: 1.1.0 + + internmap@1.0.1: {} + + internmap@2.0.3: {} + + ip-address@9.0.5: + dependencies: + jsbn: 1.1.0 + sprintf-js: 1.1.3 + + ipaddr.js@1.9.1: {} + + iron-webcrypto@1.2.1: {} + + is-array-buffer@3.0.5: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.3 + get-intrinsic: 1.2.6 + + is-arrayish@0.2.1: {} + + is-async-function@2.0.0: + dependencies: + has-tostringtag: 1.0.2 + + is-bigint@1.1.0: + dependencies: + has-bigints: 1.1.0 + + is-boolean-object@1.2.1: + dependencies: + call-bound: 1.0.3 + has-tostringtag: 1.0.2 + + is-bun-module@1.3.0: + dependencies: + semver: 7.7.2 + + is-callable@1.2.7: {} + + is-core-module@2.16.1: + dependencies: + hasown: 2.0.2 + + is-data-view@1.0.2: + dependencies: + call-bound: 1.0.3 + get-intrinsic: 1.2.6 + is-typed-array: 1.1.15 + + is-date-object@1.1.0: + dependencies: + call-bound: 1.0.3 + has-tostringtag: 1.0.2 + + is-docker@2.2.1: {} + + is-docker@3.0.0: {} + + is-extglob@2.1.1: {} + + is-finalizationregistry@1.1.1: + dependencies: + call-bound: 1.0.3 + + is-fullwidth-code-point@1.0.0: + dependencies: + number-is-nan: 1.0.1 + + is-fullwidth-code-point@2.0.0: {} + + is-fullwidth-code-point@3.0.0: {} + + is-generator-function@1.0.10: + dependencies: + has-tostringtag: 1.0.2 + + is-glob@4.0.3: + dependencies: + is-extglob: 2.1.1 + + is-inside-container@1.0.0: + dependencies: + is-docker: 3.0.0 + + is-installed-globally@1.0.0: + dependencies: + global-directory: 4.0.1 + is-path-inside: 4.0.0 + + is-interactive@2.0.0: {} + + is-lambda@1.0.1: {} + + is-map@2.0.3: {} + + is-module@1.0.0: {} + + is-number-object@1.1.1: + dependencies: + call-bound: 1.0.3 + has-tostringtag: 1.0.2 + + is-number@7.0.0: {} + + is-observable@1.1.0: + dependencies: + symbol-observable: 1.2.0 + + is-path-inside@4.0.0: {} + + is-plain-obj@1.1.0: {} + + is-plain-obj@2.1.0: {} + + is-plain-obj@4.1.0: {} + + is-promise@2.2.2: {} + + is-reference@1.2.1: + dependencies: + '@types/estree': 1.0.6 + + is-regex@1.2.1: + dependencies: + call-bound: 1.0.3 + gopd: 1.2.0 + has-tostringtag: 1.0.2 + hasown: 2.0.2 + + is-retry-allowed@1.2.0: {} + + is-set@2.0.3: {} + + is-shared-array-buffer@1.0.4: + dependencies: + call-bound: 1.0.3 + + is-stream@1.1.0: {} + + is-stream@2.0.1: {} + + is-stream@3.0.0: {} + + is-stream@4.0.1: {} + + is-string@1.1.1: + dependencies: + call-bound: 1.0.3 + has-tostringtag: 1.0.2 + + is-subdir@1.2.0: + dependencies: + better-path-resolve: 1.0.0 + + is-symbol@1.1.1: + dependencies: + call-bound: 1.0.3 + has-symbols: 1.1.0 + safe-regex-test: 1.1.0 + + is-type@0.0.1: + dependencies: + core-util-is: 1.0.3 + + is-typed-array@1.1.15: + dependencies: + which-typed-array: 1.1.18 + + is-typedarray@1.0.0: {} + + is-unicode-supported@0.1.0: {} + + is-unicode-supported@1.3.0: {} + + is-unicode-supported@2.1.0: {} + + is-weakmap@2.0.2: {} + + is-weakref@1.1.0: + dependencies: + call-bound: 1.0.3 + + is-weakset@2.0.4: + dependencies: + call-bound: 1.0.3 + get-intrinsic: 1.2.6 + + is-windows@1.0.2: {} + + is-wsl@2.2.0: + dependencies: + is-docker: 2.2.1 + + is-wsl@3.1.0: + dependencies: + is-inside-container: 1.0.0 + + isarray@1.0.0: {} + + isarray@2.0.5: {} + + isexe@2.0.0: {} + + isexe@3.1.1: {} + + jackspeak@2.3.6: + dependencies: + '@isaacs/cliui': 8.0.2 + optionalDependencies: + '@pkgjs/parseargs': 0.11.0 + + jackspeak@3.4.3: + dependencies: + '@isaacs/cliui': 8.0.2 + optionalDependencies: + '@pkgjs/parseargs': 0.11.0 + + jackspeak@4.0.2: + dependencies: + '@isaacs/cliui': 8.0.2 + + jake@10.9.2: + dependencies: + async: 3.2.6 + chalk: 4.1.2 + filelist: 1.0.4 + minimatch: 3.1.2 + + jiti@2.4.2: {} + + jju@1.4.0: {} + + js-reporters@2.1.0: {} + + js-tokens@4.0.0: {} + + js-yaml@3.14.1: + dependencies: + argparse: 1.0.10 + esprima: 4.0.1 + + js-yaml@4.1.0: + dependencies: + argparse: 2.0.1 + + jsbn@1.1.0: {} + + jsdoc-type-pratt-parser@4.1.0: {} + + jsesc@3.0.2: {} + + jsesc@3.1.0: {} + + json-buffer@3.0.1: {} + + json-parse-better-errors@1.0.2: {} + + json-parse-even-better-errors@2.3.1: {} + + json-parse-even-better-errors@3.0.2: {} + + json-parse-even-better-errors@4.0.0: {} + + json-query@2.2.2: {} + + json-schema-traverse@0.4.1: {} + + json-schema-traverse@1.0.0: {} + + json-stable-stringify-without-jsonify@1.0.1: {} + + json-stringify-safe@5.0.1: {} + + json5@1.0.2: + dependencies: + minimist: 1.2.8 + + json5@2.2.3: {} + + jsonc-eslint-parser@2.4.0: + dependencies: + acorn: 8.14.0 + eslint-visitor-keys: 3.4.3 + espree: 9.6.1 + semver: 7.7.2 + + jsonfile@4.0.0: + optionalDependencies: + graceful-fs: 4.2.11 + + jsonfile@6.1.0: + dependencies: + universalify: 2.0.1 + optionalDependencies: + graceful-fs: 4.2.11 + + jstat@1.9.6: {} + + keyv@4.5.4: + dependencies: + json-buffer: 3.0.1 + + kind-of@6.0.3: {} + + knip@5.44.4(@types/node@22.13.4)(typescript@5.7.3): + dependencies: + '@nodelib/fs.walk': 3.0.1 + '@snyk/github-codeowners': 1.1.0 + '@types/node': 22.13.4 + easy-table: 1.2.0 + enhanced-resolve: 5.18.0 + fast-glob: 3.3.3 + jiti: 2.4.2 + js-yaml: 4.1.0 + minimist: 1.2.8 + picocolors: 1.1.1 + picomatch: 4.0.2 + pretty-ms: 9.2.0 + smol-toml: 1.3.1 + strip-json-comments: 5.0.1 + summary: 2.1.0 + typescript: 5.7.3 + zod: 3.24.1 + zod-validation-error: 3.4.0(zod@3.24.1) + + ky@1.7.4: {} + + latest-version@9.0.0: + dependencies: + package-json: 10.0.1 + + lazystream@1.0.1: + dependencies: + readable-stream: 2.3.8 + + levn@0.4.1: + dependencies: + prelude-ls: 1.2.1 + type-check: 0.4.0 + + lighthouse-logger@1.4.2: + dependencies: + debug: 2.6.9 + marky: 1.3.0 + transitivePeerDependencies: + - supports-color + + lilconfig@2.1.0: {} + + lilconfig@3.1.3: {} + + lines-and-columns@1.2.4: {} + + lines-and-columns@2.0.4: {} + + listr-silent-renderer@1.1.1: {} + + listr-update-renderer@0.5.0(listr@0.14.3): + dependencies: + chalk: 1.1.3 + cli-truncate: 0.2.1 + elegant-spinner: 1.0.1 + figures: 1.7.0 + indent-string: 3.2.0 + listr: 0.14.3 + log-symbols: 1.0.2 + log-update: 2.3.0 + strip-ansi: 3.0.1 + + listr-verbose-renderer@0.5.0: + dependencies: + chalk: 2.4.2 + cli-cursor: 2.1.0 + date-fns: 1.30.1 + figures: 2.0.0 + + listr@0.14.3: + dependencies: + '@samverschueren/stream-to-observable': 0.3.1(rxjs@6.6.7) + is-observable: 1.1.0 + is-promise: 2.2.2 + is-stream: 1.1.0 + listr-silent-renderer: 1.1.1 + listr-update-renderer: 0.5.0(listr@0.14.3) + listr-verbose-renderer: 0.5.0 + p-map: 2.1.0 + rxjs: 6.6.7 + transitivePeerDependencies: + - zen-observable + - zenObservable + + load-json-file@6.2.0: + dependencies: + graceful-fs: 4.2.11 + parse-json: 5.2.0 + strip-bom: 4.0.0 + type-fest: 0.6.0 + + load-tsconfig@0.2.5: {} + + loader-utils@3.3.1: {} + + loader.js@4.7.0: {} + + locate-path@3.0.0: + dependencies: + p-locate: 3.0.0 + path-exists: 3.0.0 + + locate-path@5.0.0: + dependencies: + p-locate: 4.1.0 + + locate-path@6.0.0: + dependencies: + p-locate: 5.0.0 + + locate-path@7.2.0: + dependencies: + p-locate: 6.0.0 + + lodash._baseflatten@3.1.4: + dependencies: + lodash.isarguments: 3.1.0 + lodash.isarray: 3.0.4 + + lodash._getnative@3.9.1: {} + + lodash._isiterateecall@3.0.9: {} + + lodash.camelcase@4.3.0: {} + + lodash.clonedeep@4.5.0: {} + + lodash.debounce@3.1.1: + dependencies: + lodash._getnative: 3.9.1 + + lodash.debounce@4.0.8: {} + + lodash.defaults@4.2.0: {} + + lodash.difference@4.5.0: {} + + lodash.flatten@3.0.2: + dependencies: + lodash._baseflatten: 3.1.4 + lodash._isiterateecall: 3.0.9 + + lodash.flatten@4.4.0: {} + + lodash.isarguments@3.1.0: {} + + lodash.isarray@3.0.4: {} + + lodash.isplainobject@4.0.6: {} + + lodash.memoize@4.1.2: {} + + lodash.merge@4.6.2: {} + + lodash.mergewith@4.6.2: {} + + lodash.truncate@4.4.2: {} + + lodash.union@4.6.0: {} + + lodash.uniq@4.5.0: {} + + lodash@4.17.21: {} + + log-symbols@1.0.2: + dependencies: + chalk: 1.1.3 + + log-symbols@4.1.0: + dependencies: + chalk: 4.1.2 + is-unicode-supported: 0.1.0 + + log-symbols@6.0.0: + dependencies: + chalk: 5.4.1 + is-unicode-supported: 1.3.0 + + log-update@2.3.0: + dependencies: + ansi-escapes: 3.2.0 + cli-cursor: 2.1.0 + wrap-ansi: 3.0.1 + + loupe@3.1.2: {} + + loupe@3.1.3: {} + + lower-case@2.0.2: + dependencies: + tslib: 2.8.1 + + lowercase-keys@2.0.0: {} + + lru-cache@10.4.3: {} + + lru-cache@11.0.2: {} + + lru-cache@5.1.1: + dependencies: + yallist: 3.1.1 + + lru-cache@6.0.0: + dependencies: + yallist: 4.0.0 + + lru-cache@7.18.3: {} + + magic-string@0.25.9: + dependencies: + sourcemap-codec: 1.4.8 + + magic-string@0.30.0: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.0 + + magic-string@0.30.17: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.0 + + make-error@1.3.6: {} + + make-fetch-happen@9.1.0: + dependencies: + agentkeepalive: 4.6.0 + cacache: 15.3.0 + http-cache-semantics: 4.1.1 + http-proxy-agent: 4.0.1 + https-proxy-agent: 5.0.1 + is-lambda: 1.0.1 + lru-cache: 6.0.0 + minipass: 3.3.6 + minipass-collect: 1.0.2 + minipass-fetch: 1.4.1 + minipass-flush: 1.0.5 + minipass-pipeline: 1.2.4 + negotiator: 0.6.4 + promise-retry: 2.0.1 + socks-proxy-agent: 6.2.1 + ssri: 8.0.1 + transitivePeerDependencies: + - bluebird + - supports-color + + map-age-cleaner@0.1.3: + dependencies: + p-defer: 1.0.0 + + map-obj@1.0.1: {} + + map-obj@4.3.0: {} + + marky@1.3.0: {} + + math-intrinsics@1.1.0: {} + + mdn-data@2.0.14: {} + + media-typer@0.3.0: {} + + mem@8.1.1: + dependencies: + map-age-cleaner: 0.1.3 + mimic-fn: 3.1.0 + + meow@9.0.0: + dependencies: + '@types/minimist': 1.2.5 + camelcase-keys: 6.2.2 + decamelize: 1.2.0 + decamelize-keys: 1.1.1 + hard-rejection: 2.1.0 + minimist-options: 4.1.0 + normalize-package-data: 3.0.3 + read-pkg-up: 7.0.1 + redent: 3.0.0 + trim-newlines: 3.0.1 + type-fest: 0.18.1 + yargs-parser: 20.2.9 + + merge-descriptors@1.0.3: {} + + merge-stream@2.0.0: {} + + merge2@1.4.1: {} + + methods@1.1.2: {} + + micromatch@4.0.8: + dependencies: + braces: 3.0.3 + picomatch: 2.3.1 + + mime-db@1.52.0: {} + + mime-db@1.53.0: {} + + mime-types@2.1.35: + dependencies: + mime-db: 1.52.0 + + mime@1.6.0: {} + + mimic-fn@1.2.0: {} + + mimic-fn@2.1.0: {} + + mimic-fn@3.1.0: {} + + mimic-fn@4.0.0: {} + + mimic-function@5.0.1: {} + + mimic-response@1.0.1: {} + + mimic-response@3.1.0: {} + + min-indent@1.0.1: {} + + minimatch@10.0.1: + dependencies: + brace-expansion: 2.0.2 + + minimatch@3.1.2: + dependencies: + brace-expansion: 1.1.12 + + minimatch@5.1.6: + dependencies: + brace-expansion: 2.0.2 + + minimatch@9.0.5: + dependencies: + brace-expansion: 2.0.2 + + minimist-options@4.1.0: + dependencies: + arrify: 1.0.1 + is-plain-obj: 1.1.0 + kind-of: 6.0.3 + + minimist@1.2.8: {} + + minipass-collect@1.0.2: + dependencies: + minipass: 3.3.6 + + minipass-fetch@1.4.1: + dependencies: + minipass: 3.3.6 + minipass-sized: 1.0.3 + minizlib: 2.1.2 + optionalDependencies: + encoding: 0.1.13 + + minipass-flush@1.0.5: + dependencies: + minipass: 3.3.6 + + minipass-pipeline@1.2.4: + dependencies: + minipass: 3.3.6 + + minipass-sized@1.0.3: + dependencies: + minipass: 3.3.6 + + minipass@2.9.0: + dependencies: + safe-buffer: 5.2.1 + yallist: 3.1.1 + + minipass@3.3.6: + dependencies: + yallist: 4.0.0 + + minipass@4.2.8: {} + + minipass@5.0.0: {} + + minipass@7.1.2: {} + + minizlib@2.1.2: + dependencies: + minipass: 3.3.6 + yallist: 4.0.0 + + mitt@3.0.1: {} + + mkdirp@0.5.6: + dependencies: + minimist: 1.2.8 + + mkdirp@1.0.4: {} + + mkdirp@3.0.1: {} + + mlly@1.7.4: + dependencies: + acorn: 8.14.0 + pathe: 2.0.2 + pkg-types: 1.3.0 + ufo: 1.5.4 + + mocha@11.7.1: + dependencies: + browser-stdout: 1.3.1 + chokidar: 4.0.3 + debug: 4.4.1(supports-color@8.1.1) + diff: 7.0.0 + escape-string-regexp: 4.0.0 + find-up: 5.0.0 + glob: 10.4.5 + he: 1.2.0 + js-yaml: 4.1.0 + log-symbols: 4.1.0 + minimatch: 9.0.5 + ms: 2.1.3 + picocolors: 1.1.1 + serialize-javascript: 6.0.2 + strip-json-comments: 3.1.1 + supports-color: 8.1.1 + workerpool: 9.3.3 + yargs: 17.7.2 + yargs-parser: 21.1.1 + yargs-unparser: 2.0.0 + + mri@1.2.0: {} + + mrmime@2.0.1: {} + + ms@2.0.0: {} + + ms@2.1.3: {} + + mustache@4.2.0: {} + + mz@2.7.0: + dependencies: + any-promise: 1.3.0 + object-assign: 4.1.1 + thenify-all: 1.6.0 + + nanoid@3.3.11: {} + + nanoid@3.3.8: {} + + natural-compare@1.4.0: {} + + natural-orderby@2.0.3: {} + + ndjson@2.0.0: + dependencies: + json-stringify-safe: 5.0.1 + minimist: 1.2.8 + readable-stream: 3.6.2 + split2: 3.2.2 + through2: 4.0.2 + + negotiator@0.6.3: {} + + negotiator@0.6.4: {} + + neo-async@2.6.2: {} + + netmask@2.0.2: {} + + nice-try@1.0.5: {} + + no-case@3.0.4: + dependencies: + lower-case: 2.0.2 + tslib: 2.8.1 + + node-mock-http@1.0.1: {} + + node-notifier@10.0.1: + dependencies: + growly: 1.3.0 + is-wsl: 2.2.0 + semver: 7.7.2 + shellwords: 0.1.1 + uuid: 8.3.2 + which: 2.0.2 + + node-releases@2.0.19: {} + + node-watch@0.7.3: {} + + normalize-package-data@2.5.0: + dependencies: + hosted-git-info: 2.8.9 + resolve: 1.22.10 + semver: 5.7.2 + validate-npm-package-license: 3.0.4 + + normalize-package-data@3.0.3: + dependencies: + hosted-git-info: 4.1.0 + is-core-module: 2.16.1 + semver: 7.7.2 + validate-npm-package-license: 3.0.4 + + normalize-package-data@6.0.2: + dependencies: + hosted-git-info: 7.0.2 + semver: 7.7.2 + validate-npm-package-license: 3.0.4 + + normalize-path@3.0.0: {} + + normalize-registry-url@2.0.0: {} + + normalize-url@6.1.0: {} + + npm-install-checks@7.1.1: + dependencies: + semver: 7.7.2 + + npm-normalize-package-bin@4.0.0: {} + + npm-package-arg@12.0.2: + dependencies: + hosted-git-info: 8.0.2 + proc-log: 5.0.0 + semver: 7.7.2 + validate-npm-package-name: 6.0.0 + + npm-pick-manifest@10.0.0: + dependencies: + npm-install-checks: 7.1.1 + npm-normalize-package-bin: 4.0.0 + npm-package-arg: 12.0.2 + semver: 7.7.2 + + npm-run-path@2.0.2: + dependencies: + path-key: 2.0.1 + + npm-run-path@4.0.1: + dependencies: + path-key: 3.1.1 + + npm-run-path@5.3.0: + dependencies: + path-key: 4.0.0 + + npm-run-path@6.0.0: + dependencies: + path-key: 4.0.0 + unicorn-magic: 0.3.0 + + npmlog@6.0.2: + dependencies: + are-we-there-yet: 3.0.1 + console-control-strings: 1.1.0 + gauge: 4.0.4 + set-blocking: 2.0.0 + + nth-check@2.1.1: + dependencies: + boolbase: 1.0.0 + + number-is-nan@1.0.1: {} + + object-assign@4.1.1: {} + + object-hash@1.3.1: {} + + object-inspect@1.13.3: {} + + object-keys@1.1.1: {} + + object-treeify@1.1.33: {} + + object.assign@4.1.7: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.3 + define-properties: 1.2.1 + es-object-atoms: 1.0.0 + has-symbols: 1.1.0 + object-keys: 1.1.1 + + object.fromentries@2.0.8: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.23.8 + es-object-atoms: 1.0.0 + + object.groupby@1.0.3: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.23.8 + + object.values@1.2.1: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.3 + define-properties: 1.2.1 + es-object-atoms: 1.0.0 + + on-finished@2.4.1: + dependencies: + ee-first: 1.1.1 + + on-headers@1.0.2: {} + + once@1.4.0: + dependencies: + wrappy: 1.0.2 + + onetime@2.0.1: + dependencies: + mimic-fn: 1.2.0 + + onetime@5.1.2: + dependencies: + mimic-fn: 2.1.0 + + onetime@6.0.0: + dependencies: + mimic-fn: 4.0.0 + + onetime@7.0.0: + dependencies: + mimic-function: 5.0.1 + + open@10.1.2: + dependencies: + default-browser: 5.2.1 + define-lazy-prop: 3.0.0 + is-inside-container: 1.0.0 + is-wsl: 3.1.0 + + optionator@0.9.4: + dependencies: + deep-is: 0.1.4 + fast-levenshtein: 2.0.6 + levn: 0.4.1 + prelude-ls: 1.2.1 + type-check: 0.4.0 + word-wrap: 1.2.5 + + ora@8.1.1: + dependencies: + chalk: 5.4.1 + cli-cursor: 5.0.0 + cli-spinners: 2.9.2 + is-interactive: 2.0.0 + is-unicode-supported: 2.1.0 + log-symbols: 6.0.0 + stdin-discarder: 0.2.2 + string-width: 7.2.0 + strip-ansi: 7.1.0 + + os-tmpdir@1.0.2: {} + + own-keys@1.0.1: + dependencies: + get-intrinsic: 1.2.6 + object-keys: 1.1.1 + safe-push-apply: 1.0.0 + + p-cancelable@2.1.1: {} + + p-defer@1.0.0: {} + + p-filter@2.1.0: + dependencies: + p-map: 2.1.0 + + p-finally@1.0.0: {} + + p-limit@2.3.0: + dependencies: + p-try: 2.2.0 + + p-limit@3.1.0: + dependencies: + yocto-queue: 0.1.0 + + p-limit@4.0.0: + dependencies: + yocto-queue: 1.1.1 + + p-locate@3.0.0: + dependencies: + p-limit: 2.3.0 + + p-locate@4.1.0: + dependencies: + p-limit: 2.3.0 + + p-locate@5.0.0: + dependencies: + p-limit: 3.1.0 + + p-locate@6.0.0: + dependencies: + p-limit: 4.0.0 + + p-map@2.1.0: {} + + p-map@3.0.0: + dependencies: + aggregate-error: 3.1.0 + + p-map@4.0.0: + dependencies: + aggregate-error: 3.1.0 + + p-map@7.0.3: {} + + p-queue@6.6.2: + dependencies: + eventemitter3: 4.0.7 + p-timeout: 3.2.0 + + p-timeout@3.2.0: + dependencies: + p-finally: 1.0.0 + + p-try@2.2.0: {} + + pac-proxy-agent@7.1.0: + dependencies: + '@tootallnate/quickjs-emscripten': 0.23.0 + agent-base: 7.1.3 + debug: 4.4.1 + get-uri: 6.0.4 + http-proxy-agent: 7.0.2 + https-proxy-agent: 7.0.6 + pac-resolver: 7.0.1 + socks-proxy-agent: 8.0.5 + transitivePeerDependencies: + - supports-color + + pac-resolver@7.0.1: + dependencies: + degenerator: 5.0.1 + netmask: 2.0.2 + + package-json-from-dist@1.0.1: {} + + package-json@10.0.1: + dependencies: + ky: 1.7.4 + registry-auth-token: 5.0.3 + registry-url: 6.0.1 + semver: 7.7.2 + + package-json@6.5.0: + dependencies: + got: 11.8.6 + registry-auth-token: 4.2.2 + registry-url: 5.1.0 + semver: 6.3.1 + + package-manager-detector@0.2.8: {} + + param-case@3.0.4: + dependencies: + dot-case: 3.0.4 + tslib: 2.8.1 + + parent-module@1.0.1: + dependencies: + callsites: 3.1.0 + + parse-github-repo-url@1.4.1: {} + + parse-json@4.0.0: + dependencies: + error-ex: 1.3.2 + json-parse-better-errors: 1.0.2 + + parse-json@5.2.0: + dependencies: + '@babel/code-frame': 7.27.1 + error-ex: 1.3.2 + json-parse-even-better-errors: 2.3.1 + lines-and-columns: 1.2.4 + + parse-json@7.1.1: + dependencies: + '@babel/code-frame': 7.27.1 + error-ex: 1.3.2 + json-parse-even-better-errors: 3.0.2 + lines-and-columns: 2.0.4 + type-fest: 3.13.1 + + parse-json@8.3.0: + dependencies: + '@babel/code-frame': 7.27.1 + index-to-position: 1.1.0 + type-fest: 4.41.0 + + parse-ms@2.1.0: {} + + parse-ms@4.0.0: {} + + parse5-htmlparser2-tree-adapter@6.0.1: + dependencies: + parse5: 6.0.1 + + parse5@5.1.1: {} + + parse5@6.0.1: {} + + parseurl@1.3.3: {} + + pascal-case@3.1.2: + dependencies: + no-case: 3.0.4 + tslib: 2.8.1 + + password-prompt@1.1.3: + dependencies: + ansi-escapes: 4.3.2 + cross-spawn: 7.0.6 + + path-absolute@1.0.1: {} + + path-exists@3.0.0: {} + + path-exists@4.0.0: {} + + path-exists@5.0.0: {} + + path-is-absolute@1.0.1: {} + + path-key@2.0.1: {} + + path-key@3.1.1: {} + + path-key@4.0.0: {} + + path-name@1.0.0: {} + + path-parse@1.0.7: {} + + path-scurry@1.11.1: + dependencies: + lru-cache: 10.4.3 + minipass: 7.1.2 + + path-scurry@2.0.0: + dependencies: + lru-cache: 11.0.2 + minipass: 7.1.2 + + path-temp@2.1.0: + dependencies: + unique-string: 2.0.0 + + path-to-regexp@0.1.12: {} + + path-type@4.0.0: {} + + path-type@6.0.0: {} + + path@0.12.7: + dependencies: + process: 0.11.10 + util: 0.10.4 + + pathe@1.1.2: {} + + pathe@2.0.2: {} + + pathe@2.0.3: {} + + pathval@2.0.0: {} + + pend@1.2.0: {} + + picocolors@1.1.1: {} + + picomatch@2.3.1: {} + + picomatch@4.0.2: {} + + pify@5.0.0: {} + + pirates@4.0.6: {} + + pkg-dir@7.0.0: + dependencies: + find-up: 6.3.0 + + pkg-entry-points@1.1.1: {} + + pkg-types@1.3.0: + dependencies: + confbox: 0.1.8 + mlly: 1.7.4 + pathe: 1.1.2 + + pkg-up@3.1.0: + dependencies: + find-up: 3.0.0 + + possible-typed-array-names@1.0.0: {} + + postcss-calc@8.2.4(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-selector-parser: 6.1.2 + postcss-value-parser: 4.2.0 + + postcss-colormin@5.3.1(postcss@8.5.3): + dependencies: + browserslist: 4.25.1 + caniuse-api: 3.0.0 + colord: 2.9.3 + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + postcss-convert-values@5.1.3(postcss@8.5.3): + dependencies: + browserslist: 4.25.1 + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + postcss-discard-comments@5.1.2(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + + postcss-discard-duplicates@5.1.0(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + + postcss-discard-empty@5.1.1(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + + postcss-discard-overridden@5.1.0(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + + postcss-load-config@3.1.4(postcss@8.5.3)(ts-node@10.9.2(@swc/core@1.9.3)(@types/node@22.13.4)(typescript@5.7.3)): + dependencies: + lilconfig: 2.1.0 + yaml: 1.10.2 + optionalDependencies: + postcss: 8.5.3 + ts-node: 10.9.2(@swc/core@1.9.3)(@types/node@22.13.4)(typescript@5.7.3) + + postcss-merge-longhand@5.1.7(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + stylehacks: 5.1.1(postcss@8.5.3) + + postcss-merge-rules@5.1.4(postcss@8.5.3): + dependencies: + browserslist: 4.25.1 + caniuse-api: 3.0.0 + cssnano-utils: 3.1.0(postcss@8.5.3) + postcss: 8.5.3 + postcss-selector-parser: 6.1.2 + + postcss-minify-font-values@5.1.0(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + postcss-minify-gradients@5.1.1(postcss@8.5.3): + dependencies: + colord: 2.9.3 + cssnano-utils: 3.1.0(postcss@8.5.3) + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + postcss-minify-params@5.1.4(postcss@8.5.3): + dependencies: + browserslist: 4.25.1 + cssnano-utils: 3.1.0(postcss@8.5.3) + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + postcss-minify-selectors@5.2.1(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-selector-parser: 6.1.2 + + postcss-modules-extract-imports@3.1.0(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + + postcss-modules-local-by-default@4.0.5(postcss@8.5.3): + dependencies: + icss-utils: 5.1.0(postcss@8.5.3) + postcss: 8.5.3 + postcss-selector-parser: 6.1.2 + postcss-value-parser: 4.2.0 + + postcss-modules-scope@3.2.0(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-selector-parser: 6.1.2 + + postcss-modules-values@4.0.0(postcss@8.5.3): + dependencies: + icss-utils: 5.1.0(postcss@8.5.3) + postcss: 8.5.3 + + postcss-modules@4.3.1(postcss@8.5.3): + dependencies: + generic-names: 4.0.0 + icss-replace-symbols: 1.1.0 + lodash.camelcase: 4.3.0 + postcss: 8.5.3 + postcss-modules-extract-imports: 3.1.0(postcss@8.5.3) + postcss-modules-local-by-default: 4.0.5(postcss@8.5.3) + postcss-modules-scope: 3.2.0(postcss@8.5.3) + postcss-modules-values: 4.0.0(postcss@8.5.3) + string-hash: 1.1.3 + + postcss-normalize-charset@5.1.0(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + + postcss-normalize-display-values@5.1.0(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + postcss-normalize-positions@5.1.1(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + postcss-normalize-repeat-style@5.1.1(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + postcss-normalize-string@5.1.0(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + postcss-normalize-timing-functions@5.1.0(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + postcss-normalize-unicode@5.1.1(postcss@8.5.3): + dependencies: + browserslist: 4.25.1 + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + postcss-normalize-url@5.1.0(postcss@8.5.3): + dependencies: + normalize-url: 6.1.0 + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + postcss-normalize-whitespace@5.1.1(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + postcss-ordered-values@5.1.3(postcss@8.5.3): + dependencies: + cssnano-utils: 3.1.0(postcss@8.5.3) + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + postcss-reduce-initial@5.1.2(postcss@8.5.3): + dependencies: + browserslist: 4.25.1 + caniuse-api: 3.0.0 + postcss: 8.5.3 + + postcss-reduce-transforms@5.1.0(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + postcss-selector-parser@6.1.2: + dependencies: + cssesc: 3.0.0 + util-deprecate: 1.0.2 + + postcss-svgo@5.1.0(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + svgo: 2.8.0 + + postcss-unique-selectors@5.1.1(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-selector-parser: 6.1.2 + + postcss-value-parser@4.2.0: {} + + postcss@8.5.3: + dependencies: + nanoid: 3.3.8 + picocolors: 1.1.1 + source-map-js: 1.2.1 + + postcss@8.5.6: + dependencies: + nanoid: 3.3.11 + picocolors: 1.1.1 + source-map-js: 1.2.1 + + prelude-ls@1.2.1: {} + + prettier@2.8.8: {} + + prettier@3.5.1: {} + + pretty-bytes@5.6.0: {} + + pretty-ms@7.0.1: + dependencies: + parse-ms: 2.1.0 + + pretty-ms@9.2.0: + dependencies: + parse-ms: 4.0.0 + + preval.macro@5.0.0: + dependencies: + babel-plugin-preval: 5.1.0 + + printable-characters@1.0.42: {} + + printf@0.6.1: {} + + proc-log@5.0.0: {} + + process-nextick-args@2.0.1: {} + + process@0.11.10: {} + + progress@2.0.3: {} + + promise-inflight@1.0.1: {} + + promise-retry@2.0.1: + dependencies: + err-code: 2.0.3 + retry: 0.12.0 + + promise.series@0.2.0: {} + + proto-list@1.2.4: {} + + proxy-addr@2.0.7: + dependencies: + forwarded: 0.2.0 + ipaddr.js: 1.9.1 + + proxy-agent@6.5.0: + dependencies: + agent-base: 7.1.3 + debug: 4.4.0 + http-proxy-agent: 7.0.2 + https-proxy-agent: 7.0.6 + lru-cache: 7.18.3 + pac-proxy-agent: 7.1.0 + proxy-from-env: 1.1.0 + socks-proxy-agent: 8.0.5 + transitivePeerDependencies: + - supports-color + + proxy-from-env@1.1.0: {} + + psl@1.15.0: + dependencies: + punycode: 2.3.1 + + publint@0.3.2: + dependencies: + '@publint/pack': 0.1.1 + package-manager-detector: 0.2.8 + picocolors: 1.1.1 + sade: 1.8.1 + + pump@3.0.2: + dependencies: + end-of-stream: 1.4.4 + once: 1.4.0 + + pump@3.0.3: + dependencies: + end-of-stream: 1.4.5 + once: 1.4.0 + + punycode@2.3.1: {} + + puppeteer-chromium-resolver@23.0.0: + dependencies: + '@puppeteer/browsers': 2.6.1 + eight-colors: 1.3.1 + gauge: 5.0.2 + puppeteer-core: 23.11.1 + transitivePeerDependencies: + - bare-buffer + - bufferutil + - supports-color + - utf-8-validate + + puppeteer-chromium-resolver@24.0.1: + dependencies: + '@puppeteer/browsers': 2.10.5 + eight-colors: 1.3.1 + gauge: 5.0.2 + puppeteer-core: 24.11.2 + transitivePeerDependencies: + - bare-buffer + - bufferutil + - supports-color + - utf-8-validate + + puppeteer-core@23.11.1: + dependencies: + '@puppeteer/browsers': 2.6.1 + chromium-bidi: 0.11.0(devtools-protocol@0.0.1367902) + debug: 4.4.0 + devtools-protocol: 0.0.1367902 + typed-query-selector: 2.12.0 + ws: 8.18.0 + transitivePeerDependencies: + - bare-buffer + - bufferutil + - supports-color + - utf-8-validate + + puppeteer-core@24.11.2: + dependencies: + '@puppeteer/browsers': 2.10.5 + chromium-bidi: 5.1.0(devtools-protocol@0.0.1464554) + debug: 4.4.1(supports-color@8.1.1) + devtools-protocol: 0.0.1464554 + typed-query-selector: 2.12.0 + ws: 8.18.3 + transitivePeerDependencies: + - bare-buffer + - bufferutil + - supports-color + - utf-8-validate + + puppeteer@23.11.1(typescript@5.7.3): + dependencies: + '@puppeteer/browsers': 2.6.1 + chromium-bidi: 0.11.0(devtools-protocol@0.0.1367902) + cosmiconfig: 9.0.0(typescript@5.7.3) + devtools-protocol: 0.0.1367902 + puppeteer-core: 23.11.1 + typed-query-selector: 2.12.0 + transitivePeerDependencies: + - bare-buffer + - bufferutil + - supports-color + - typescript + - utf-8-validate + + puppeteer@24.11.2(typescript@5.7.3): + dependencies: + '@puppeteer/browsers': 2.10.5 + chromium-bidi: 5.1.0(devtools-protocol@0.0.1464554) + cosmiconfig: 9.0.0(typescript@5.7.3) + devtools-protocol: 0.0.1464554 + puppeteer-core: 24.11.2 + typed-query-selector: 2.12.0 + transitivePeerDependencies: + - bare-buffer + - bufferutil + - supports-color + - typescript + - utf-8-validate + + qs@6.13.0: + dependencies: + side-channel: 1.1.0 + + querystringify@2.2.0: {} + + queue-microtask@1.2.3: {} + + quick-lru@4.0.1: {} + + quick-lru@5.1.1: {} + + qunit@2.24.1: + dependencies: + commander: 7.2.0 + node-watch: 0.7.3 + tiny-glob: 0.2.9 + + race-cancellation@0.4.1: {} + + radix3@1.1.2: {} + + randombytes@2.1.0: + dependencies: + safe-buffer: 5.2.1 + + range-parser@1.2.1: {} + + raw-body@2.5.2: + dependencies: + bytes: 3.1.2 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + unpipe: 1.0.0 + + rc@1.2.8: + dependencies: + deep-extend: 0.6.0 + ini: 1.3.8 + minimist: 1.2.8 + strip-json-comments: 2.0.1 + + read-ini-file@4.0.0: + dependencies: + ini: 3.0.1 + strip-bom: 4.0.0 + + read-pkg-up@7.0.1: + dependencies: + find-up: 4.1.0 + read-pkg: 5.2.0 + type-fest: 0.8.1 + + read-pkg@5.2.0: + dependencies: + '@types/normalize-package-data': 2.4.4 + normalize-package-data: 2.5.0 + parse-json: 5.2.0 + type-fest: 0.6.0 + + read-pkg@8.1.0: + dependencies: + '@types/normalize-package-data': 2.4.4 + normalize-package-data: 6.0.2 + parse-json: 7.1.1 + type-fest: 4.35.0 + + read-pkg@9.0.1: + dependencies: + '@types/normalize-package-data': 2.4.4 + normalize-package-data: 6.0.2 + parse-json: 8.3.0 + type-fest: 4.35.0 + unicorn-magic: 0.1.0 + + read-yaml-file@2.1.0: + dependencies: + js-yaml: 4.1.0 + strip-bom: 4.0.0 + + readable-stream@2.3.8: + dependencies: + core-util-is: 1.0.3 + inherits: 2.0.4 + isarray: 1.0.0 + process-nextick-args: 2.0.1 + safe-buffer: 5.1.2 + string_decoder: 1.1.1 + util-deprecate: 1.0.2 + + readable-stream@3.6.2: + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + + readdir-glob@1.1.3: + dependencies: + minimatch: 5.1.6 + + readdirp@4.0.2: {} + + realpath-missing@1.1.0: {} + + redent@3.0.0: + dependencies: + indent-string: 4.0.0 + strip-indent: 3.0.0 + + redeyed@2.1.1: + dependencies: + esprima: 4.0.1 + + refa@0.12.1: + dependencies: + '@eslint-community/regexpp': 4.12.1 + + reflect.getprototypeof@1.0.9: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + dunder-proto: 1.0.1 + es-abstract: 1.23.8 + es-errors: 1.3.0 + get-intrinsic: 1.2.6 + gopd: 1.2.0 + which-builtin-type: 1.2.1 + + regenerate-unicode-properties@10.2.0: + dependencies: + regenerate: 1.4.2 + + regenerate@1.4.2: {} + + regexp-ast-analysis@0.7.1: + dependencies: + '@eslint-community/regexpp': 4.12.1 + refa: 0.12.1 + + regexp.prototype.flags@1.5.3: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-errors: 1.3.0 + set-function-name: 2.0.2 + + regexpu-core@6.2.0: + dependencies: + regenerate: 1.4.2 + regenerate-unicode-properties: 10.2.0 + regjsgen: 0.8.0 + regjsparser: 0.12.0 + unicode-match-property-ecmascript: 2.0.0 + unicode-match-property-value-ecmascript: 2.2.0 + + registry-auth-token@4.2.2: + dependencies: + rc: 1.2.8 + + registry-auth-token@5.0.3: + dependencies: + '@pnpm/npm-conf': 2.3.1 + + registry-auth-token@5.1.0: + dependencies: + '@pnpm/npm-conf': 2.3.1 + + registry-url@5.1.0: + dependencies: + rc: 1.2.8 + + registry-url@6.0.1: + dependencies: + rc: 1.2.8 + + regjsgen@0.8.0: {} + + regjsparser@0.12.0: + dependencies: + jsesc: 3.0.2 + + relateurl@0.2.7: {} + + release-plan@0.13.1: + dependencies: + '@manypkg/get-packages': 2.2.2 + '@npmcli/package-json': 6.1.1 + '@octokit/rest': 21.1.1 + assert-never: 1.4.0 + chalk: 4.1.2 + cli-highlight: 2.1.11 + execa: 4.1.0 + fs-extra: 11.3.0 + github-changelog: 1.0.2 + js-yaml: 4.1.0 + latest-version: 9.0.0 + parse-github-repo-url: 1.4.1 + semver: 7.7.2 + yargs: 17.7.2 + transitivePeerDependencies: + - bluebird + - supports-color + + require-directory@2.1.1: {} + + require-from-string@2.0.2: {} + + requireindex@1.2.0: {} + + requires-port@1.0.0: {} + + resolve-alpn@1.2.1: {} + + resolve-from@4.0.0: {} + + resolve-from@5.0.0: {} + + resolve-pkg-maps@1.0.0: {} + + resolve@1.22.10: + dependencies: + is-core-module: 2.16.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + + responselike@2.0.1: + dependencies: + lowercase-keys: 2.0.0 + + restore-cursor@2.0.0: + dependencies: + onetime: 2.0.1 + signal-exit: 3.0.7 + + restore-cursor@5.1.0: + dependencies: + onetime: 7.0.0 + signal-exit: 4.1.0 + + retry@0.12.0: {} + + reusify@1.0.4: {} + + rimraf@3.0.2: + dependencies: + glob: 7.2.3 + + rimraf@5.0.10: + dependencies: + glob: 10.4.5 + + rimraf@6.0.1: + dependencies: + glob: 11.0.1 + package-json-from-dist: 1.0.1 + + rollup-plugin-dts@6.1.1(rollup@4.34.8)(typescript@5.7.3): + dependencies: + magic-string: 0.30.17 + rollup: 4.34.8 + typescript: 5.7.3 + optionalDependencies: + '@babel/code-frame': 7.26.2 + + rollup-plugin-insert@1.3.2(rollup@4.34.8): + dependencies: + magic-string: 0.25.9 + rollup: 4.34.8 + rollup-pluginutils: 2.8.2 + + rollup-plugin-polyfill-node@0.13.0(rollup@4.34.8): + dependencies: + '@rollup/plugin-inject': 5.0.5(rollup@4.34.8) + rollup: 4.34.8 + + rollup-plugin-postcss@4.0.2(postcss@8.5.3)(ts-node@10.9.2(@swc/core@1.9.3)(@types/node@22.13.4)(typescript@5.7.3)): + dependencies: + chalk: 4.1.2 + concat-with-sourcemaps: 1.1.0 + cssnano: 5.1.15(postcss@8.5.3) + import-cwd: 3.0.0 + p-queue: 6.6.2 + pify: 5.0.0 + postcss: 8.5.3 + postcss-load-config: 3.1.4(postcss@8.5.3)(ts-node@10.9.2(@swc/core@1.9.3)(@types/node@22.13.4)(typescript@5.7.3)) + postcss-modules: 4.3.1(postcss@8.5.3) + promise.series: 0.2.0 + resolve: 1.22.10 + rollup-pluginutils: 2.8.2 + safe-identifier: 0.4.2 + style-inject: 0.3.0 + transitivePeerDependencies: + - ts-node + + rollup-pluginutils@2.8.2: + dependencies: + estree-walker: 0.6.1 + + rollup@4.34.8: + dependencies: + '@types/estree': 1.0.6 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.34.8 + '@rollup/rollup-android-arm64': 4.34.8 + '@rollup/rollup-darwin-arm64': 4.34.8 + '@rollup/rollup-darwin-x64': 4.34.8 + '@rollup/rollup-freebsd-arm64': 4.34.8 + '@rollup/rollup-freebsd-x64': 4.34.8 + '@rollup/rollup-linux-arm-gnueabihf': 4.34.8 + '@rollup/rollup-linux-arm-musleabihf': 4.34.8 + '@rollup/rollup-linux-arm64-gnu': 4.34.8 + '@rollup/rollup-linux-arm64-musl': 4.34.8 + '@rollup/rollup-linux-loongarch64-gnu': 4.34.8 + '@rollup/rollup-linux-powerpc64le-gnu': 4.34.8 + '@rollup/rollup-linux-riscv64-gnu': 4.34.8 + '@rollup/rollup-linux-s390x-gnu': 4.34.8 + '@rollup/rollup-linux-x64-gnu': 4.34.8 + '@rollup/rollup-linux-x64-musl': 4.34.8 + '@rollup/rollup-win32-arm64-msvc': 4.34.8 + '@rollup/rollup-win32-ia32-msvc': 4.34.8 + '@rollup/rollup-win32-x64-msvc': 4.34.8 + fsevents: 2.3.3 + + rollup@4.44.1: + dependencies: + '@types/estree': 1.0.8 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.44.1 + '@rollup/rollup-android-arm64': 4.44.1 + '@rollup/rollup-darwin-arm64': 4.44.1 + '@rollup/rollup-darwin-x64': 4.44.1 + '@rollup/rollup-freebsd-arm64': 4.44.1 + '@rollup/rollup-freebsd-x64': 4.44.1 + '@rollup/rollup-linux-arm-gnueabihf': 4.44.1 + '@rollup/rollup-linux-arm-musleabihf': 4.44.1 + '@rollup/rollup-linux-arm64-gnu': 4.44.1 + '@rollup/rollup-linux-arm64-musl': 4.44.1 + '@rollup/rollup-linux-loongarch64-gnu': 4.44.1 + '@rollup/rollup-linux-powerpc64le-gnu': 4.44.1 + '@rollup/rollup-linux-riscv64-gnu': 4.44.1 + '@rollup/rollup-linux-riscv64-musl': 4.44.1 + '@rollup/rollup-linux-s390x-gnu': 4.44.1 + '@rollup/rollup-linux-x64-gnu': 4.44.1 + '@rollup/rollup-linux-x64-musl': 4.44.1 + '@rollup/rollup-win32-arm64-msvc': 4.44.1 + '@rollup/rollup-win32-ia32-msvc': 4.44.1 + '@rollup/rollup-win32-x64-msvc': 4.44.1 + fsevents: 2.3.3 + + run-applescript@7.0.0: {} + + run-parallel@1.2.0: + dependencies: + queue-microtask: 1.2.3 + + rxjs@6.6.7: + dependencies: + tslib: 1.14.1 + + rxjs@7.8.1: + dependencies: + tslib: 2.8.1 + + sade@1.8.1: + dependencies: + mri: 1.2.0 + + safe-array-concat@1.1.3: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.3 + get-intrinsic: 1.2.6 + has-symbols: 1.1.0 + isarray: 2.0.5 + + safe-buffer@5.1.2: {} + + safe-buffer@5.2.1: {} + + safe-execa@0.1.2: + dependencies: + '@zkochan/which': 2.0.3 + execa: 5.1.1 + path-name: 1.0.0 + + safe-identifier@0.4.2: {} + + safe-push-apply@1.0.0: + dependencies: + es-errors: 1.3.0 + isarray: 2.0.5 + + safe-regex-test@1.1.0: + dependencies: + call-bound: 1.0.3 + es-errors: 1.3.0 + is-regex: 1.2.1 + + safer-buffer@2.1.2: {} + + scslre@0.3.0: + dependencies: + '@eslint-community/regexpp': 4.12.1 + refa: 0.12.1 + regexp-ast-analysis: 0.7.1 + + semver@5.7.2: {} + + semver@6.3.1: {} + + semver@7.7.2: {} + + send@0.19.0: + dependencies: + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + encodeurl: 1.0.2 + escape-html: 1.0.3 + etag: 1.8.1 + fresh: 0.5.2 + http-errors: 2.0.0 + mime: 1.6.0 + ms: 2.1.3 + on-finished: 2.4.1 + range-parser: 1.2.1 + statuses: 2.0.1 + transitivePeerDependencies: + - supports-color + + serialize-javascript@6.0.2: + dependencies: + randombytes: 2.1.0 + + serve-static@1.16.2: + dependencies: + encodeurl: 2.0.0 + escape-html: 1.0.3 + parseurl: 1.3.3 + send: 0.19.0 + transitivePeerDependencies: + - supports-color + + set-blocking@2.0.0: {} + + set-function-length@1.2.2: + dependencies: + define-data-property: 1.1.4 + es-errors: 1.3.0 + function-bind: 1.1.2 + get-intrinsic: 1.2.6 + gopd: 1.2.0 + has-property-descriptors: 1.0.2 + + set-function-name@2.0.2: + dependencies: + define-data-property: 1.1.4 + es-errors: 1.3.0 + functions-have-names: 1.2.3 + has-property-descriptors: 1.0.2 + + setprototypeof@1.2.0: {} + + shebang-command@1.2.0: + dependencies: + shebang-regex: 1.0.0 + + shebang-command@2.0.0: + dependencies: + shebang-regex: 3.0.0 + + shebang-regex@1.0.0: {} + + shebang-regex@3.0.0: {} + + shellwords@0.1.1: {} + + side-channel-list@1.0.0: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.3 + + side-channel-map@1.0.1: + dependencies: + call-bound: 1.0.3 + es-errors: 1.3.0 + get-intrinsic: 1.2.6 + object-inspect: 1.13.3 + + side-channel-weakmap@1.0.2: + dependencies: + call-bound: 1.0.3 + es-errors: 1.3.0 + get-intrinsic: 1.2.6 + object-inspect: 1.13.3 + side-channel-map: 1.0.1 + + side-channel@1.1.0: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.3 + side-channel-list: 1.0.0 + side-channel-map: 1.0.1 + side-channel-weakmap: 1.0.2 + + siginfo@2.0.0: {} + + signal-exit@3.0.7: {} + + signal-exit@4.1.0: {} + + silent-error@1.1.1: + dependencies: + debug: 2.6.9 + transitivePeerDependencies: + - supports-color + + simple-html-tokenizer@0.5.11: {} + + slash@3.0.0: {} + + slash@5.1.0: {} + + slice-ansi@0.0.4: {} + + slice-ansi@3.0.0: + dependencies: + ansi-styles: 4.3.0 + astral-regex: 2.0.0 + is-fullwidth-code-point: 3.0.0 + + slice-ansi@4.0.0: + dependencies: + ansi-styles: 4.3.0 + astral-regex: 2.0.0 + is-fullwidth-code-point: 3.0.0 + + smart-buffer@4.2.0: {} + + smob@1.5.0: {} + + smol-toml@1.3.1: {} + + socket.io-adapter@2.5.5: + dependencies: + debug: 4.3.7 + ws: 8.17.1 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + socket.io-parser@4.2.4: + dependencies: + '@socket.io/component-emitter': 3.1.2 + debug: 4.3.7 + transitivePeerDependencies: + - supports-color + + socket.io@4.8.1: + dependencies: + accepts: 1.3.8 + base64id: 2.0.0 + cors: 2.8.5 + debug: 4.3.7 + engine.io: 6.6.2 + socket.io-adapter: 2.5.5 + socket.io-parser: 4.2.4 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + socks-proxy-agent@6.2.1: + dependencies: + agent-base: 6.0.2 + debug: 4.4.1(supports-color@8.1.1) + socks: 2.8.3 + transitivePeerDependencies: + - supports-color + + socks-proxy-agent@8.0.5: + dependencies: + agent-base: 7.1.3 + debug: 4.4.1 + socks: 2.8.3 + transitivePeerDependencies: + - supports-color + + socks@2.8.3: + dependencies: + ip-address: 9.0.5 + smart-buffer: 4.2.0 + + sort-keys@4.2.0: + dependencies: + is-plain-obj: 2.1.0 + + sort-keys@5.1.0: + dependencies: + is-plain-obj: 4.1.0 + + source-map-js@1.2.1: {} + + source-map-support@0.5.21: + dependencies: + buffer-from: 1.1.2 + source-map: 0.6.1 + + source-map@0.6.1: {} + + sourcemap-codec@1.4.8: {} + + spawn-args@0.2.0: {} + + spdx-correct@3.2.0: + dependencies: + spdx-expression-parse: 3.0.1 + spdx-license-ids: 3.0.20 + + spdx-exceptions@2.5.0: {} + + spdx-expression-parse@3.0.1: + dependencies: + spdx-exceptions: 2.5.0 + spdx-license-ids: 3.0.20 + + spdx-license-ids@3.0.20: {} + + split2@3.2.2: + dependencies: + readable-stream: 3.6.2 + + sprintf-js@1.0.3: {} + + sprintf-js@1.1.3: {} + + ssri@8.0.1: + dependencies: + minipass: 3.3.6 + + stable-hash@0.0.4: {} + + stable@0.1.8: {} + + stackback@0.0.2: {} + + stacktracey@2.1.8: + dependencies: + as-table: 1.0.55 + get-source: 2.0.12 + + statuses@2.0.1: {} + + std-env@3.8.0: {} + + stdin-discarder@0.2.2: {} + + streamx@2.22.1: + dependencies: + fast-fifo: 1.3.2 + text-decoder: 1.2.3 + optionalDependencies: + bare-events: 2.5.4 + + string-hash@1.1.3: {} + + string-length@4.0.2: + dependencies: + char-regex: 1.0.2 + strip-ansi: 6.0.1 + + string-width@1.0.2: + dependencies: + code-point-at: 1.1.0 + is-fullwidth-code-point: 1.0.0 + strip-ansi: 3.0.1 + + string-width@2.1.1: + dependencies: + is-fullwidth-code-point: 2.0.0 + strip-ansi: 4.0.0 + + string-width@4.2.3: + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + + string-width@5.1.2: + dependencies: + eastasianwidth: 0.2.0 + emoji-regex: 9.2.2 + strip-ansi: 7.1.0 + + string-width@7.2.0: + dependencies: + emoji-regex: 10.4.0 + get-east-asian-width: 1.3.0 + strip-ansi: 7.1.0 + + string.prototype.trim@1.2.10: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.3 + define-data-property: 1.1.4 + define-properties: 1.2.1 + es-abstract: 1.23.8 + es-object-atoms: 1.0.0 + has-property-descriptors: 1.0.2 + + string.prototype.trimend@1.0.9: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.3 + define-properties: 1.2.1 + es-object-atoms: 1.0.0 + + string.prototype.trimstart@1.0.8: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-object-atoms: 1.0.0 + + string_decoder@1.1.1: + dependencies: + safe-buffer: 5.1.2 + + string_decoder@1.3.0: + dependencies: + safe-buffer: 5.2.1 + + strip-ansi@3.0.1: + dependencies: + ansi-regex: 2.1.1 + + strip-ansi@4.0.0: + dependencies: + ansi-regex: 3.0.1 + + strip-ansi@6.0.1: + dependencies: + ansi-regex: 5.0.1 + + strip-ansi@7.1.0: + dependencies: + ansi-regex: 6.1.0 + + strip-bom@3.0.0: {} + + strip-bom@4.0.0: {} + + strip-comments-strings@1.2.0: {} + + strip-eof@1.0.0: {} + + strip-final-newline@2.0.0: {} + + strip-final-newline@3.0.0: {} + + strip-final-newline@4.0.0: {} + + strip-indent@3.0.0: + dependencies: + min-indent: 1.0.1 + + strip-json-comments@2.0.1: {} + + strip-json-comments@3.1.1: {} + + strip-json-comments@5.0.1: {} + + style-inject@0.3.0: {} + + styled_string@0.0.1: {} + + stylehacks@5.1.1(postcss@8.5.3): + dependencies: + browserslist: 4.25.1 + postcss: 8.5.3 + postcss-selector-parser: 6.1.2 + + sucrase@3.35.0: + dependencies: + '@jridgewell/gen-mapping': 0.3.8 + commander: 4.1.1 + glob: 10.4.5 + lines-and-columns: 1.2.4 + mz: 2.7.0 + pirates: 4.0.6 + ts-interface-checker: 0.1.13 + + summary@2.1.0: {} + + supports-color@2.0.0: {} + + supports-color@5.5.0: + dependencies: + has-flag: 3.0.0 + + supports-color@7.2.0: + dependencies: + has-flag: 4.0.0 + + supports-color@8.1.1: + dependencies: + has-flag: 4.0.0 + + supports-hyperlinks@2.3.0: + dependencies: + has-flag: 4.0.0 + supports-color: 7.2.0 + + supports-preserve-symlinks-flag@1.0.0: {} + + svgo@2.8.0: + dependencies: + '@trysound/sax': 0.2.0 + commander: 7.2.0 + css-select: 4.3.0 + css-tree: 1.1.3 + csso: 4.2.0 + picocolors: 1.1.1 + stable: 0.1.8 + + symbol-observable@1.2.0: {} + + synckit@0.6.2: + dependencies: + tslib: 2.8.1 + + table@6.9.0: + dependencies: + ajv: 8.17.1 + lodash.truncate: 4.4.2 + slice-ansi: 4.0.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + tap-parser@7.0.0: + dependencies: + events-to-array: 1.1.2 + js-yaml: 3.14.1 + minipass: 2.9.0 + + tapable@2.2.1: {} + + tar-fs@3.1.0: + dependencies: + pump: 3.0.3 + tar-stream: 3.1.7 + optionalDependencies: + bare-fs: 4.1.5 + bare-path: 3.0.0 + transitivePeerDependencies: + - bare-buffer + + tar-stream@2.2.0: + dependencies: + bl: 4.1.0 + end-of-stream: 1.4.5 + fs-constants: 1.0.0 + inherits: 2.0.4 + readable-stream: 3.6.2 + + tar-stream@3.1.7: + dependencies: + b4a: 1.6.7 + fast-fifo: 1.3.2 + streamx: 2.22.1 + + tar@6.2.1: + dependencies: + chownr: 2.0.0 + fs-minipass: 2.1.0 + minipass: 5.0.0 + minizlib: 2.1.2 + mkdirp: 1.0.4 + yallist: 4.0.0 + + terminal-link@3.0.0: + dependencies: + ansi-escapes: 5.0.0 + supports-hyperlinks: 2.3.0 + + terser@5.37.0: + dependencies: + '@jridgewell/source-map': 0.3.6 + acorn: 8.14.0 + commander: 2.20.3 + source-map-support: 0.5.21 + + terser@5.43.1: + dependencies: + '@jridgewell/source-map': 0.3.10 + acorn: 8.15.0 + commander: 2.20.3 + source-map-support: 0.5.21 + + testem-failure-only-reporter@1.0.0(ejs@3.1.10)(handlebars@4.7.8)(underscore@1.13.7): + dependencies: + testem: 3.15.2(ejs@3.1.10)(handlebars@4.7.8)(underscore@1.13.7) + transitivePeerDependencies: + - arc-templates + - atpl + - babel-core + - bracket-template + - bufferutil + - coffee-script + - debug + - dot + - dust + - dustjs-helpers + - dustjs-linkedin + - eco + - ect + - ejs + - haml-coffee + - hamlet + - hamljs + - handlebars + - hogan.js + - htmling + - jade + - jazz + - jqtpl + - just + - liquid-node + - liquor + - marko + - mote + - nunjucks + - plates + - pug + - qejs + - ractive + - razor-tmpl + - react + - react-dom + - slm + - squirrelly + - supports-color + - swig + - swig-templates + - teacup + - templayed + - then-jade + - then-pug + - tinyliquid + - toffee + - twig + - twing + - underscore + - utf-8-validate + - vash + - velocityjs + - walrus + - whiskers + + testem@3.15.2(ejs@3.1.10)(handlebars@4.7.8)(underscore@1.13.7): + dependencies: + '@xmldom/xmldom': 0.8.10 + backbone: 1.6.0 + bluebird: 3.7.2 + charm: 1.0.2 + commander: 2.20.3 + compression: 1.7.5 + consolidate: 0.16.0(ejs@3.1.10)(handlebars@4.7.8)(lodash@4.17.21)(mustache@4.2.0)(underscore@1.13.7) + execa: 1.0.0 + express: 4.21.2 + fireworm: 0.7.2 + glob: 7.2.3 + http-proxy: 1.18.1 + js-yaml: 3.14.1 + lodash: 4.17.21 + mkdirp: 3.0.1 + mustache: 4.2.0 + node-notifier: 10.0.1 + npmlog: 6.0.2 + printf: 0.6.1 + rimraf: 3.0.2 + socket.io: 4.8.1 + spawn-args: 0.2.0 + styled_string: 0.0.1 + tap-parser: 7.0.0 + tmp: 0.0.33 + transitivePeerDependencies: + - arc-templates + - atpl + - babel-core + - bracket-template + - bufferutil + - coffee-script + - debug + - dot + - dust + - dustjs-helpers + - dustjs-linkedin + - eco + - ect + - ejs + - haml-coffee + - hamlet + - hamljs + - handlebars + - hogan.js + - htmling + - jade + - jazz + - jqtpl + - just + - liquid-node + - liquor + - marko + - mote + - nunjucks + - plates + - pug + - qejs + - ractive + - razor-tmpl + - react + - react-dom + - slm + - squirrelly + - supports-color + - swig + - swig-templates + - teacup + - templayed + - then-jade + - then-pug + - tinyliquid + - toffee + - twig + - twing + - underscore + - utf-8-validate + - vash + - velocityjs + - walrus + - whiskers + + text-decoder@1.2.3: + dependencies: + b4a: 1.6.7 + + thenify-all@1.6.0: + dependencies: + thenify: 3.3.1 + + thenify@3.3.1: + dependencies: + any-promise: 1.3.0 + + through2@4.0.2: + dependencies: + readable-stream: 3.6.2 + + through@2.3.8: {} + + tiny-glob@0.2.9: + dependencies: + globalyzer: 0.1.0 + globrex: 0.1.2 + + tinybench@2.9.0: {} + + tinyexec@0.3.2: {} + + tinyglobby@0.2.12: + dependencies: + fdir: 6.4.3(picomatch@4.0.2) + picomatch: 4.0.2 + + tinyglobby@0.2.14: + dependencies: + fdir: 6.4.6(picomatch@4.0.2) + picomatch: 4.0.2 + + tinypool@1.0.2: {} + + tinyrainbow@2.0.0: {} + + tinyspy@3.0.2: {} + + tmp@0.0.33: + dependencies: + os-tmpdir: 1.0.2 + + tmp@0.2.3: {} + + to-regex-range@5.0.1: + dependencies: + is-number: 7.0.0 + + toidentifier@1.0.1: {} + + toml@3.0.0: {} + + tough-cookie@4.1.4: + dependencies: + psl: 1.15.0 + punycode: 2.3.1 + universalify: 0.2.0 + url-parse: 1.5.10 + + tracerbench@8.0.1(@swc/core@1.9.3)(@types/node@22.13.4)(typescript@5.7.3): + dependencies: + '@oclif/command': 1.8.36(@oclif/config@1.18.17) + '@oclif/config': 1.18.17 + '@oclif/errors': 1.3.6 + '@oclif/parser': 3.8.17 + '@oclif/plugin-help': 5.2.20(@swc/core@1.9.3)(@types/node@22.13.4)(typescript@5.7.3) + '@oclif/plugin-warn-if-update-available': 3.1.42 + '@tracerbench/core': 8.0.1 + '@tracerbench/stats': 8.0.1 + '@tracerbench/trace-event': 8.0.0 + archiver: 5.3.2 + chalk: 4.1.2 + chrome-debugging-client: 2.0.0(devtools-protocol@0.0.975963) + cli-table3: 0.6.5 + d3-array: 3.2.4 + devtools-protocol: 0.0.975963 + execa: 6.1.0 + fs-extra: 10.1.0 + handlebars: 4.7.8 + html-minifier-terser: 7.2.0 + json-query: 2.2.2 + json5: 2.2.3 + listr: 0.14.3 + path: 0.12.7 + tmp: 0.2.3 + tough-cookie: 4.1.4 + tslib: 2.8.1 + transitivePeerDependencies: + - '@swc/core' + - '@swc/wasm' + - '@types/node' + - bufferutil + - supports-color + - typescript + - utf-8-validate + - zen-observable + - zenObservable + + trim-newlines@3.0.1: {} + + ts-api-utils@2.0.1(typescript@5.7.3): + dependencies: + typescript: 5.7.3 + + ts-api-utils@2.1.0(typescript@5.7.3): + dependencies: + typescript: 5.7.3 + + ts-interface-checker@0.1.13: {} + + ts-node@10.9.2(@swc/core@1.9.3)(@types/node@22.13.4)(typescript@5.7.3): + dependencies: + '@cspotcode/source-map-support': 0.8.1 + '@tsconfig/node10': 1.0.11 + '@tsconfig/node12': 1.0.11 + '@tsconfig/node14': 1.0.3 + '@tsconfig/node16': 1.0.4 + '@types/node': 22.13.4 + acorn: 8.15.0 + acorn-walk: 8.3.4 + arg: 4.1.3 + create-require: 1.1.1 + diff: 4.0.2 + make-error: 1.3.6 + typescript: 5.7.3 + v8-compile-cache-lib: 3.0.1 + yn: 3.1.1 + optionalDependencies: + '@swc/core': 1.9.3 + + tsconfig-paths@3.15.0: + dependencies: + '@types/json5': 0.0.29 + json5: 1.0.2 + minimist: 1.2.8 + strip-bom: 3.0.0 + + tslib@1.14.1: {} + + tslib@2.8.1: {} + + tsx@3.14.0: + dependencies: + esbuild: 0.25.5 + get-tsconfig: 4.8.1 + source-map-support: 0.5.21 + optionalDependencies: + fsevents: 2.3.3 + + tsx@4.19.2: + dependencies: + esbuild: 0.25.5 + get-tsconfig: 4.10.1 + optionalDependencies: + fsevents: 2.3.3 + optional: true + + tunnel-agent@0.6.0: + dependencies: + safe-buffer: 5.2.1 + + turbo-darwin-64@2.4.2: + optional: true + + turbo-darwin-arm64@2.4.2: + optional: true + + turbo-linux-64@2.4.2: + optional: true + + turbo-linux-arm64@2.4.2: + optional: true + + turbo-windows-64@2.4.2: + optional: true + + turbo-windows-arm64@2.4.2: + optional: true + + turbo@2.4.2: + optionalDependencies: + turbo-darwin-64: 2.4.2 + turbo-darwin-arm64: 2.4.2 + turbo-linux-64: 2.4.2 + turbo-linux-arm64: 2.4.2 + turbo-windows-64: 2.4.2 + turbo-windows-arm64: 2.4.2 + + type-check@0.4.0: + dependencies: + prelude-ls: 1.2.1 + + type-fest@0.18.1: {} + + type-fest@0.20.2: {} + + type-fest@0.21.3: {} + + type-fest@0.6.0: {} + + type-fest@0.8.1: {} + + type-fest@1.4.0: {} + + type-fest@3.13.1: {} + + type-fest@4.35.0: {} + + type-fest@4.41.0: {} + + type-is@1.6.18: + dependencies: + media-typer: 0.3.0 + mime-types: 2.1.35 + + typed-array-buffer@1.0.3: + dependencies: + call-bound: 1.0.3 + es-errors: 1.3.0 + is-typed-array: 1.1.15 + + typed-array-byte-length@1.0.3: + dependencies: + call-bind: 1.0.8 + for-each: 0.3.3 + gopd: 1.2.0 + has-proto: 1.2.0 + is-typed-array: 1.1.15 + + typed-array-byte-offset@1.0.4: + dependencies: + available-typed-arrays: 1.0.7 + call-bind: 1.0.8 + for-each: 0.3.3 + gopd: 1.2.0 + has-proto: 1.2.0 + is-typed-array: 1.1.15 + reflect.getprototypeof: 1.0.9 + + typed-array-length@1.0.7: + dependencies: + call-bind: 1.0.8 + for-each: 0.3.3 + gopd: 1.2.0 + is-typed-array: 1.1.15 + possible-typed-array-names: 1.0.0 + reflect.getprototypeof: 1.0.9 + + typed-query-selector@2.12.0: {} + + typedarray-to-buffer@3.1.5: + dependencies: + is-typedarray: 1.0.0 + + typescript-eslint@8.24.1(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3): + dependencies: + '@typescript-eslint/eslint-plugin': 8.24.1(@typescript-eslint/parser@8.24.1(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3))(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3) + '@typescript-eslint/parser': 8.24.1(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3) + '@typescript-eslint/utils': 8.24.1(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3) + eslint: 9.20.1(jiti@2.4.2) + typescript: 5.7.3 + transitivePeerDependencies: + - supports-color + + typescript@5.7.3: {} + + ufo@1.5.4: {} + + ufo@1.6.1: {} + + uglify-js@3.19.3: + optional: true + + unbox-primitive@1.1.0: + dependencies: + call-bound: 1.0.3 + has-bigints: 1.1.0 + has-symbols: 1.1.0 + which-boxed-primitive: 1.1.1 + + unbzip2-stream@1.4.3: + dependencies: + buffer: 5.7.1 + through: 2.3.8 + + uncrypto@0.1.3: {} + + underscore@1.13.7: {} + + undici-types@6.20.0: {} + + unicode-canonical-property-names-ecmascript@2.0.1: {} + + unicode-match-property-ecmascript@2.0.0: + dependencies: + unicode-canonical-property-names-ecmascript: 2.0.1 + unicode-property-aliases-ecmascript: 2.1.0 + + unicode-match-property-value-ecmascript@2.2.0: {} + + unicode-property-aliases-ecmascript@2.1.0: {} + + unicorn-magic@0.1.0: {} + + unicorn-magic@0.3.0: {} + + unique-filename@1.1.1: + dependencies: + unique-slug: 2.0.2 + + unique-slug@2.0.2: + dependencies: + imurmurhash: 0.1.4 + + unique-string@2.0.0: + dependencies: + crypto-random-string: 2.0.0 + + universal-user-agent@7.0.2: {} + + universalify@0.1.2: {} + + universalify@0.2.0: {} + + universalify@2.0.1: {} + + unpipe@1.0.0: {} + + unplugin-fonts@1.3.1(vite@6.3.5(@types/node@22.13.4)(jiti@2.4.2)(terser@5.43.1)(tsx@4.19.2)(yaml@2.7.0)): + dependencies: + fast-glob: 3.3.3 + unplugin: 2.0.0-beta.1 + vite: 6.3.5(@types/node@22.13.4)(jiti@2.4.2)(terser@5.43.1)(tsx@4.19.2)(yaml@2.7.0) + + unplugin@2.0.0-beta.1: + dependencies: + acorn: 8.14.0 + webpack-virtual-modules: 0.6.2 + + update-browserslist-db@1.1.3(browserslist@4.25.1): + dependencies: + browserslist: 4.25.1 + escalade: 3.2.0 + picocolors: 1.1.1 + + uri-js@4.4.1: + dependencies: + punycode: 2.3.1 + + url-parse@1.5.10: + dependencies: + querystringify: 2.2.0 + requires-port: 1.0.0 + + util-deprecate@1.0.2: {} + + util@0.10.4: + dependencies: + inherits: 2.0.3 + + utils-merge@1.0.1: {} + + uuid@8.3.2: {} + + v8-compile-cache-lib@3.0.1: {} + + validate-npm-package-license@3.0.4: + dependencies: + spdx-correct: 3.2.0 + spdx-expression-parse: 3.0.1 + + validate-npm-package-name@5.0.0: + dependencies: + builtins: 5.1.0 + + validate-npm-package-name@6.0.0: {} + + vary@1.1.2: {} + + vite-node@3.0.6(@types/node@22.13.4)(jiti@2.4.2)(terser@5.43.1)(tsx@4.19.2)(yaml@2.7.0): + dependencies: + cac: 6.7.14 + debug: 4.4.0 + es-module-lexer: 1.6.0 + pathe: 2.0.3 + vite: 6.3.5(@types/node@22.13.4)(jiti@2.4.2)(terser@5.43.1)(tsx@4.19.2)(yaml@2.7.0) + transitivePeerDependencies: + - '@types/node' + - jiti + - less + - lightningcss + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + - tsx + - yaml + + vite@6.3.5(@types/node@22.13.4)(jiti@2.4.2)(terser@5.43.1)(tsx@4.19.2)(yaml@2.7.0): + dependencies: + esbuild: 0.25.5 + fdir: 6.4.6(picomatch@4.0.2) + picomatch: 4.0.2 + postcss: 8.5.6 + rollup: 4.44.1 + tinyglobby: 0.2.14 + optionalDependencies: + '@types/node': 22.13.4 + fsevents: 2.3.3 + jiti: 2.4.2 + terser: 5.43.1 + tsx: 4.19.2 + yaml: 2.7.0 + + vite@7.0.2(@types/node@22.13.4)(jiti@2.4.2)(terser@5.43.1)(tsx@4.19.2)(yaml@2.7.0): + dependencies: + esbuild: 0.25.5 + fdir: 6.4.6(picomatch@4.0.2) + picomatch: 4.0.2 + postcss: 8.5.6 + rollup: 4.44.1 + tinyglobby: 0.2.14 + optionalDependencies: + '@types/node': 22.13.4 + fsevents: 2.3.3 + jiti: 2.4.2 + terser: 5.43.1 + tsx: 4.19.2 + yaml: 2.7.0 + + vitest@3.0.6(@types/node@22.13.4)(jiti@2.4.2)(terser@5.43.1)(tsx@4.19.2)(yaml@2.7.0): + dependencies: + '@vitest/expect': 3.0.6 + '@vitest/mocker': 3.0.6(vite@6.3.5(@types/node@22.13.4)(jiti@2.4.2)(terser@5.43.1)(tsx@4.19.2)(yaml@2.7.0)) + '@vitest/pretty-format': 3.0.6 + '@vitest/runner': 3.0.6 + '@vitest/snapshot': 3.0.6 + '@vitest/spy': 3.0.6 + '@vitest/utils': 3.0.6 + chai: 5.2.0 + debug: 4.4.0 + expect-type: 1.1.0 + magic-string: 0.30.17 + pathe: 2.0.3 + std-env: 3.8.0 + tinybench: 2.9.0 + tinyexec: 0.3.2 + tinypool: 1.0.2 + tinyrainbow: 2.0.0 + vite: 6.3.5(@types/node@22.13.4)(jiti@2.4.2)(terser@5.43.1)(tsx@4.19.2)(yaml@2.7.0) + vite-node: 3.0.6(@types/node@22.13.4)(jiti@2.4.2)(terser@5.43.1)(tsx@4.19.2)(yaml@2.7.0) + why-is-node-running: 2.3.0 + optionalDependencies: + '@types/node': 22.13.4 + transitivePeerDependencies: + - jiti + - less + - lightningcss + - msw + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + - tsx + - yaml + + wcwidth@1.0.1: + dependencies: + defaults: 1.0.4 + + webpack-virtual-modules@0.6.2: {} + + which-boxed-primitive@1.1.1: + dependencies: + is-bigint: 1.1.0 + is-boolean-object: 1.2.1 + is-number-object: 1.1.1 + is-string: 1.1.1 + is-symbol: 1.1.1 + + which-builtin-type@1.2.1: + dependencies: + call-bound: 1.0.3 + function.prototype.name: 1.1.8 + has-tostringtag: 1.0.2 + is-async-function: 2.0.0 + is-date-object: 1.1.0 + is-finalizationregistry: 1.1.1 + is-generator-function: 1.0.10 + is-regex: 1.2.1 + is-weakref: 1.1.0 + isarray: 2.0.5 + which-boxed-primitive: 1.1.1 + which-collection: 1.0.2 + which-typed-array: 1.1.18 + + which-collection@1.0.2: + dependencies: + is-map: 2.0.3 + is-set: 2.0.3 + is-weakmap: 2.0.2 + is-weakset: 2.0.4 + + which-typed-array@1.1.18: + dependencies: + available-typed-arrays: 1.0.7 + call-bind: 1.0.8 + call-bound: 1.0.3 + for-each: 0.3.3 + gopd: 1.2.0 + has-tostringtag: 1.0.2 + + which@1.3.1: + dependencies: + isexe: 2.0.0 + + which@2.0.2: + dependencies: + isexe: 2.0.0 + + which@5.0.0: + dependencies: + isexe: 3.1.1 + + why-is-node-running@2.3.0: + dependencies: + siginfo: 2.0.0 + stackback: 0.0.2 + + wide-align@1.1.5: + dependencies: + string-width: 4.2.3 + + widest-line@3.1.0: + dependencies: + string-width: 4.2.3 + + widest-line@5.0.0: + dependencies: + string-width: 7.2.0 + + word-wrap@1.2.5: {} + + wordwrap@1.0.0: {} + + workerpool@9.3.3: {} + + wrap-ansi@3.0.1: + dependencies: + string-width: 2.1.1 + strip-ansi: 4.0.0 + + wrap-ansi@6.2.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + wrap-ansi@7.0.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + wrap-ansi@8.1.0: + dependencies: + ansi-styles: 6.2.1 + string-width: 5.1.2 + strip-ansi: 7.1.0 + + wrap-ansi@9.0.0: + dependencies: + ansi-styles: 6.2.1 + string-width: 7.2.0 + strip-ansi: 7.1.0 + + wrappy@1.0.2: {} + + write-file-atomic@3.0.3: + dependencies: + imurmurhash: 0.1.4 + is-typedarray: 1.0.0 + signal-exit: 3.0.7 + typedarray-to-buffer: 3.1.5 + + write-file-atomic@5.0.1: + dependencies: + imurmurhash: 0.1.4 + signal-exit: 4.1.0 + + write-json-file@5.0.0: + dependencies: + detect-indent: 7.0.1 + is-plain-obj: 4.1.0 + sort-keys: 5.1.0 + write-file-atomic: 3.0.3 + + write-pkg@7.0.0: + dependencies: + deepmerge-ts: 5.1.0 + read-pkg: 8.1.0 + sort-keys: 5.1.0 + type-fest: 4.35.0 + write-json-file: 5.0.0 + + write-yaml-file@5.0.0: + dependencies: + js-yaml: 4.1.0 + write-file-atomic: 5.0.1 + + ws@7.5.10: {} + + ws@8.17.1: {} + + ws@8.18.0: {} + + ws@8.18.3: {} + + y18n@5.0.8: {} + + yallist@3.1.1: {} + + yallist@4.0.0: {} + + yaml@1.10.2: {} + + yaml@2.7.0: {} + + yargs-parser@20.2.4: {} + + yargs-parser@20.2.9: {} + + yargs-parser@21.1.1: {} + + yargs-unparser@2.0.0: + dependencies: + camelcase: 6.3.0 + decamelize: 4.0.0 + flat: 5.0.2 + is-plain-obj: 2.1.0 + + yargs@16.2.0: + dependencies: + cliui: 7.0.4 + escalade: 3.2.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 20.2.4 + + yargs@17.7.2: + dependencies: + cliui: 8.0.1 + escalade: 3.2.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 21.1.1 + + yauzl@2.10.0: + dependencies: + buffer-crc32: 0.2.13 + fd-slicer: 1.1.0 + + yn@3.1.1: {} + + yocto-queue@0.1.0: {} + + yocto-queue@1.1.1: {} + + yoctocolors@2.1.1: {} + + zip-stream@4.1.1: + dependencies: + archiver-utils: 3.0.4 + compress-commons: 4.1.2 + readable-stream: 3.6.2 + + zod-validation-error@3.4.0(zod@3.24.1): + dependencies: + zod: 3.24.1 + + zod@3.23.8: {} + + zod@3.24.1: {} + + zod@3.25.72: {} + + zx@8.3.2: + optionalDependencies: + '@types/fs-extra': 11.0.4 + '@types/node': 22.13.4 diff --git a/glimmer-vm/pnpm-workspace.yaml b/glimmer-vm/pnpm-workspace.yaml new file mode 100644 index 00000000000..52a16047f13 --- /dev/null +++ b/glimmer-vm/pnpm-workspace.yaml @@ -0,0 +1,6 @@ +packages: + - '.meta-updater' + - 'bin' + - 'repo-metadata' + - 'packages/*/*' + - 'packages/*/*/test' \ No newline at end of file diff --git a/glimmer-vm/repo-metadata/index.d.ts b/glimmer-vm/repo-metadata/index.d.ts new file mode 100644 index 00000000000..7ad4f985e47 --- /dev/null +++ b/glimmer-vm/repo-metadata/index.d.ts @@ -0,0 +1,25 @@ +import type { PackageInfo, RepoMeta } from './lib/types'; +export type * from './lib/types'; +declare const DEFAULT: RepoMeta; +export default DEFAULT; + +/** + * This is the root directory of the workspace as an _absolute_ path. + * It's not included in `metadata.json` because it's different on each + * computer, while the contents of `metadata.json` are _relative_ to the + * workspace root, and therefore the same across machines. + */ +export const WORKSPACE_ROOT: string; + +export type { PackageEntryPoints } from 'pkg-entry-points'; + +/** + * This package is not a workspace package, since it's used as a standalone + * benchmark in both the current (experiment) scenario and the control (`main`) + * scenario. + */ +export const BENCHMARK_ROOT: string; + +export function getPackageInfo(packageName: string): PackageInfo | undefined; + +export function isRoot(pkg: PackageInfo): boolean; diff --git a/glimmer-vm/repo-metadata/index.js b/glimmer-vm/repo-metadata/index.js new file mode 100644 index 00000000000..d93f46a5c36 --- /dev/null +++ b/glimmer-vm/repo-metadata/index.js @@ -0,0 +1,25 @@ +/** @import { PackageInfo, RepoMeta } from './lib/types'; */ +import { resolve } from 'node:path'; + +import metadata from './metadata.json' with { type: 'json' }; + +export { default } from './metadata.json' with { type: 'json' }; + +export const WORKSPACE_ROOT = resolve(import.meta.dirname, '..'); +export const BENCHMARK_ROOT = resolve(WORKSPACE_ROOT, 'benchmark/benchmarks/krausest'); + +/** + * @param {string} packageName + * @returns {PackageInfo | undefined} + */ +export function getPackageInfo(packageName) { + return /** @type {RepoMeta} */ (metadata).packages.find((pkg) => pkg.name === packageName); +} + +/** + * @param {PackageInfo} pkg + * @returns {boolean} + */ +export function isRoot(pkg) { + return pkg.root === ''; +} diff --git a/glimmer-vm/repo-metadata/lib/package-updater.ts b/glimmer-vm/repo-metadata/lib/package-updater.ts new file mode 100644 index 00000000000..d3b8976a0e7 --- /dev/null +++ b/glimmer-vm/repo-metadata/lib/package-updater.ts @@ -0,0 +1,337 @@ +/* eslint-disable no-console */ +import { existsSync, readFileSync, writeFileSync } from 'node:fs'; +import { join } from 'node:path'; + +import chalk from 'chalk'; +import deepmerge from 'deepmerge'; +import { globby } from 'globby'; +import Handlebars from 'handlebars'; +import { readPackage } from 'read-pkg'; +import { writePackage } from 'write-pkg'; + +import type { PackageInfo } from './types.js'; + +import { getPackageInfo, WORKSPACE_ROOT } from '../index.js'; +import metadata from '../metadata.json' with { type: 'json' }; + +interface PackageManifest { + name?: string; + version?: string; + private?: boolean; + type?: 'module' | 'commonjs'; + repository?: { + type: string; + url: string; + directory?: string; + }; + publishConfig?: { + access?: string; + exports?: Record; + types?: string; + }; + scripts?: Record; + files?: string[]; + dependencies?: Record; + devDependencies?: Record; + [key: string]: unknown; +} + +interface UpdateContext { + manifest: PackageManifest; + packageInfo: PackageInfo; + isPublished: boolean; + isRoot: boolean; + isBuilt: boolean; +} + +// Catalog of devDependencies to sync +const CATALOG = { + devDependencies: { + rollup: '^4.34.8', + }, +}; + +// Handlebars template for rollup.config.mjs +const ROLLUP_CONFIG_TEMPLATE = + Handlebars.compile(`import { Package } from '@glimmer-workspace/build-support'; + +export default Package.config(import.meta); +`); + +export class PackageUpdater { + private workspaceRoot: string; + + constructor(workspaceRoot: string = WORKSPACE_ROOT) { + this.workspaceRoot = workspaceRoot; + } + + async updateAllPackages(): Promise { + console.log(chalk.blue('Updating package conventions...')); + + // Discover all packages using globby (replacing @pnpm/workspace.find-packages) + const packagePaths = await globby( + [ + 'packages/@glimmer/*/package.json', + 'packages/@glimmer-workspace/*/package.json', + 'packages/@types/*/package.json', + ], + { + cwd: this.workspaceRoot, + absolute: true, + } + ); + + let updatedCount = 0; + + console.log(chalk.gray(`Found ${packagePaths.length} packages to check`)); + + for (const packagePath of packagePaths) { + const updated = await this.updatePackage(packagePath); + if (updated) { + updatedCount++; + } + } + + console.log(chalk.green(`Updated ${updatedCount} packages`)); + } + + private async updatePackage(packagePath: string): Promise { + try { + // Read package.json using read-pkg for normalization + const manifest = await readPackage({ cwd: packagePath.replace('/package.json', '') }); + + if (!manifest.name) { + return false; + } + + const packageInfo = getPackageInfo(manifest.name); + if (!packageInfo) { + console.log(chalk.yellow(`No metadata found for ${manifest.name}`)); + return false; + } + + const context: UpdateContext = { + manifest, + packageInfo, + isPublished: !packageInfo.private, + isRoot: packageInfo.name === 'glimmer-engine', + isBuilt: packageInfo['repo-meta']?.built === true, + }; + + // Update package.json + const updatedManifest = this.updatePackageManifest(context); + const manifestChanged = JSON.stringify(manifest) !== JSON.stringify(updatedManifest); + + // Generate rollup.config.mjs if needed + const rollupConfigPath = join(packagePath.replace('/package.json', ''), 'rollup.config.mjs'); + const rollupConfigChanged = this.updateRollupConfig(context, rollupConfigPath); + + if (manifestChanged) { + await writePackage(packagePath.replace('/package.json', ''), updatedManifest); + this.logUpdate(packageInfo.root, 'package.json'); + } + + // Log status for packages that are already up to date + if (!manifestChanged && !rollupConfigChanged) { + console.log(chalk.gray(` ✓ ${packageInfo.name} is up to date`)); + } + + return manifestChanged || rollupConfigChanged; + } catch (error) { + console.error(chalk.red(`Failed to update package at ${packagePath}:`), error); + return false; + } + } + + private updatePackageManifest(context: UpdateContext): PackageManifest { + const { manifest, packageInfo, isPublished, isRoot, isBuilt } = context; + + // Start with a deep copy + const updated = deepmerge({}, manifest) as PackageManifest; + + // Initialize required objects + updated.publishConfig = updated.publishConfig || {}; + updated.scripts = updated.scripts || {}; + + // Clean up legacy scripts (replaced with prepack) + delete updated.scripts['test:types']; + delete updated.scripts['test:lint']; + + // Repository configuration + if (isPublished || isRoot) { + updated.repository = { + type: 'git', + url: 'git+https://github.com/glimmerjs/glimmer-vm.git', + ...(packageInfo.root ? { directory: packageInfo.root } : {}), + }; + } else { + delete updated.repository; + } + + // Published package configuration + if (isPublished) { + updated.publishConfig.access = 'public'; + } + + // Private package configuration + if (!isPublished && !isBuilt) { + // Reset publishConfig for private non-built packages + updated.publishConfig = {}; + updated.version = metadata.workspace.version; // Use workspace version + + // Root package special handling + if (isRoot) { + // Only add test:lint if it doesn't already exist + if (!updated.scripts['test:lint']) { + updated.scripts['test:lint'] = 'eslint . --quiet'; + } + } else { + delete updated.repository; + } + + delete updated.scripts['test:publint']; + this.cleanup(updated, 'publishConfig'); + return updated; + } + + // Built packages and published packages + updated.scripts['test:publint'] = 'publint'; + + // Sync devDependencies from catalog + updated.devDependencies = updated.devDependencies || {}; + for (const [name, version] of Object.entries(CATALOG.devDependencies)) { + if (name in updated.devDependencies) { + updated.devDependencies[name] = version; + } + } + + // Built package configuration + if (isBuilt) { + updated.devDependencies['@glimmer-workspace/env'] = 'workspace:*'; + updated.scripts['prepack'] = 'rollup -c rollup.config.mjs'; + updated.files = ['dist']; + + // Configure exports + if (packageInfo.name === '@glimmer/vm-babel-plugins') { + // Special case for babel plugins + updated.publishConfig.exports = { + '.': { + development: { + default: './dist/dev/index.js', + }, + ...(packageInfo['repo-meta']?.supportcjs + ? { + require: { + default: './dist/dev/index.cjs', + }, + } + : {}), + default: { + default: './dist/prod/index.js', + }, + }, + }; + } else { + // Standard built package exports + updated.publishConfig.types = 'dist/dev/index.d.ts'; + updated.publishConfig.exports = { + '.': { + development: { + types: './dist/dev/index.d.ts', + default: './dist/dev/index.js', + }, + ...(packageInfo['repo-meta']?.supportcjs + ? { + require: { + default: './dist/dev/index.cjs', + }, + } + : {}), + default: { + types: './dist/prod/index.d.ts', + default: './dist/prod/index.js', + }, + }, + }; + } + } else { + // Non-built packages + delete updated.publishConfig.exports; + delete updated.scripts['prepack']; + } + + // Cleanup empty objects + this.cleanup(updated, 'publishConfig'); + this.cleanup(updated, 'devDependencies'); + + return updated; + } + + private updateRollupConfig(context: UpdateContext, rollupConfigPath: string): boolean { + const { packageInfo, isBuilt, isRoot } = context; + + if (isRoot) { + // Root package doesn't get a rollup config + if (existsSync(rollupConfigPath)) { + // Remove existing rollup config if present + writeFileSync(rollupConfigPath, ''); + this.logUpdate(packageInfo.root, 'rollup.config.mjs (removed)'); + return true; + } + return false; + } + + if (isBuilt) { + // Generate rollup config for built packages + const configContent = ROLLUP_CONFIG_TEMPLATE({}); + const existingContent = existsSync(rollupConfigPath) + ? readFileSync(rollupConfigPath, 'utf8') + : ''; + + if (existingContent !== configContent) { + writeFileSync(rollupConfigPath, configContent); + this.logUpdate(packageInfo.root, 'rollup.config.mjs'); + return true; + } + } else { + // Remove rollup config for non-built packages + if (existsSync(rollupConfigPath)) { + writeFileSync(rollupConfigPath, ''); + this.logUpdate(packageInfo.root, 'rollup.config.mjs (removed)'); + return true; + } + } + + return false; + } + + private cleanup(obj: Record, key: string): void { + const value = obj[key]; + if (value !== null && typeof value === 'object' && Object.keys(value).length === 0) { + obj[key] = undefined; + } + } + + private logUpdate(packageRoot: string, file: string): void { + const [prefix, rest] = packageRoot.startsWith('packages/') + ? ['packages/', packageRoot.slice('packages/'.length)] + : ['', packageRoot || '{root}']; + + console.log( + `${chalk.green.bold('updating')} ${chalk.gray.dim(prefix)}${chalk.magenta.underline( + rest + )}${chalk.gray('/')}${chalk.cyanBright(file)}` + ); + } +} + +// CLI execution +if (import.meta.url === `file://${process.argv[1]}`) { + const updater = new PackageUpdater(); + try { + await updater.updateAllPackages(); + } catch (error: unknown) { + console.error(chalk.red('Failed to update packages:'), error); + process.exit(1); + } +} diff --git a/glimmer-vm/repo-metadata/lib/types.d.ts b/glimmer-vm/repo-metadata/lib/types.d.ts new file mode 100644 index 00000000000..aab71fefbb4 --- /dev/null +++ b/glimmer-vm/repo-metadata/lib/types.d.ts @@ -0,0 +1,92 @@ +/* eslint-disable no-irregular-whitespace */ +import type { PackageEntryPoints } from 'pkg-entry-points'; + +export interface RepoMeta { + /** + * Information about the workspace from `pnpm-workspace.yaml`. + */ + workspace: { + /** + * The version of the root package, which is used as the version of non-published packages. In + * principle, there is no reason why private packages **need** a version, but tooling sometimes + * doesn't behave properly without one, and it's not a big deal to add one. + * + * > Even if a specific bug is fixed in the future, we should give the private packages a + * > version unless we're very confident that the ecosystem works properly without one. + * + * @see https://github.com/pnpm/pnpm/issues/4164 + */ + version: string; + packages: string[]; + }; + + /** + * A list of packages in the repository, in the `RepoMetaForPackage` format. + */ + packages: PackageInfo[]; +} + +export interface RepoMetaForPackage { + /** + * The TypeScript profile to use. This field controls the linting + * configuration for this package. + * + * Currently, the `tsconfig.json` is the same for all packages. This is + * intentional, as it allows us to avoid project references, which + * significantly compilate matters. + * + * - `strict` enables `strictTypeChecked`. + * - `loose` enables `recommendedTypeChecked`, but disables some safety rules, + * such as `no-explicit-any` and many `unsafe-*` rules. This is meant to be + * a temporary measure while we work on the strict mode migration. + */ + strictness?: 'strict' | 'loose'; + /** + * The list of file patterns to lint (without the extension). + * + * The default is: + * + * - for test packages, `**​/*` + * - for other packages, `['index', 'src/**​/*']` + * + * Some special packages (such as `bin`) specify their own list. + */ + lint?: string | string[]; + /** + * The list of special environments used by this package. + * + * - `node`: this package will be used in a Node.js environment. + * - `console`: this package will use console globals. + * - `qunit`: this package will use QUnit globals. + * - `decorator:classic`: this package will use classic decorators. + */ + env?: RepoMetaEnv[]; + + /** + * Whether this package has buildable entry points and therefore needs to be built. + */ + built?: true; + + /** + * Whether this package has to support CJS (usually for legacy reasons) + */ + supportcjs?: true; +} + +type RepoMetaEnv = 'node' | 'console' | 'qunit' | 'decorator:classic'; + +export interface PackageInfo { + name: string; + version: string | undefined; + root: string; + type: 'module' | 'commonjs'; + private: boolean; + entryPoints?: PackageEntryPoints; + 'repo-meta'?: { + strictness?: 'strict' | 'loose'; + supportcjs?: boolean; + env?: RepoMetaEnv[]; + lint?: string[]; + built: boolean; + }; +} diff --git a/glimmer-vm/repo-metadata/lib/update.ts b/glimmer-vm/repo-metadata/lib/update.ts new file mode 100644 index 00000000000..89526d2b961 --- /dev/null +++ b/glimmer-vm/repo-metadata/lib/update.ts @@ -0,0 +1,227 @@ +/* eslint-disable no-console */ +import assert from 'node:assert'; +import { existsSync, readFileSync, writeFileSync } from 'node:fs'; +import { readFile } from 'node:fs/promises'; +import { join, relative, resolve } from 'node:path'; + +import type { PackageEntryPoints } from 'pkg-entry-points'; +import chalk from 'chalk'; +import { execa } from 'execa'; +import { getPackageEntryPointsSync } from 'pkg-entry-points'; +import YAML from 'yaml'; + +import type { PackageInfo, RepoMetaForPackage } from './types'; + +interface PnpmPackage { + name: string; + version: string; + path: string; + private?: boolean; + dependencies?: Record; + devDependencies?: Record; +} + +interface WorkspacePackage { + rootDir: string; + manifest: ManifestExt; +} + +const workspaceRoot = new URL('../..', import.meta.url).pathname; +const metadataRoot = new URL('..', import.meta.url).pathname; + +const workspaceFile = await readFile(join(workspaceRoot, 'pnpm-workspace.yaml'), 'utf8'); +const workspaceInfo = YAML.parse(workspaceFile) as { packages: string[] }; + +// Get workspace packages using pnpm list instead of @pnpm/workspace.find-packages +// to avoid peer dependency issues with @pnpm/* internal packages +let pnpmPackages: PnpmPackage[]; +try { + const { stdout } = await execa('pnpm', ['list', '--recursive', '--json', '--depth=0'], { + cwd: workspaceRoot, + }); + pnpmPackages = JSON.parse(stdout) as PnpmPackage[]; +} catch (error) { + console.error(chalk.red('Failed to get workspace packages with pnpm list:'), error); + throw new Error('Failed to get workspace packages'); +} + +const packages: WorkspacePackage[] = pnpmPackages.map((pkg) => { + // Read the actual package.json to get all fields including repo-meta + const packageJsonPath = join(pkg.path, 'package.json'); + if (!existsSync(packageJsonPath)) { + console.error(chalk.red(`Missing package.json at ${packageJsonPath}`)); + throw new Error(`Missing package.json at ${packageJsonPath}`); + } + + try { + const fullManifest = JSON.parse(readFileSync(packageJsonPath, 'utf8')) as ManifestExt; + return { + rootDir: pkg.path, + manifest: fullManifest, + }; + } catch (error) { + console.error(chalk.red(`Failed to read/parse package.json at ${packageJsonPath}:`), error); + throw new Error(`Failed to read/parse package.json at ${packageJsonPath}`); + } +}); + +if (process.argv.includes('--print-list')) { + for (const pkg of packages.sort()) { + console.log( + `${chalk.gray('-')} ${chalk.magenta(relative(workspaceRoot, pkg.rootDir) || '{root}')}` + ); + } + + // eslint-disable-next-line n/no-process-exit + process.exit(0); +} + +interface ManifestExt { + name?: string; + version?: string; + private?: boolean; + type?: 'module' | 'commonjs'; + 'repo-meta'?: RepoMetaForPackage; +} + +const WARNINGS: Record< + string, + { + name: string | undefined; + problems: Record; + } +> = {}; + +function warn(pkg: WorkspacePackage, code: string, field: string, expected?: string) { + const pkgRoot = relative(workspaceRoot, pkg.rootDir); + let { problems } = (WARNINGS[pkgRoot] ??= { name: pkg.manifest.name, problems: {} }); + problems[field] = { code, expected }; +} + +const packagesMetadata = packages.map((pkg) => { + const manifest = pkg.manifest; + const { name, type, private: isPrivate = false } = manifest; + + assert(name, `Missing name in ${relative(workspaceRoot, pkg.rootDir)}/package.json`); + + if (!type) { + warn(pkg, 'missing', 'type', 'module | commonjs'); + } + + const entryPoints = getPackageEntryPointsSync(pkg.rootDir); + + const metadata: PackageInfo = { + root: relative(workspaceRoot, pkg.rootDir), + name, + version: manifest.version, + type: manifest.type ?? 'commonjs', + private: isPrivate, + }; + + const repoMeta = (pkg.manifest as Record)['repo-meta'] as + | RepoMetaForPackage + | undefined; + + const meta = (metadata['repo-meta'] ??= { built: false }); + + if (repoMeta) { + assert( + typeof repoMeta === 'object', + `repo-meta in ${relative(workspaceRoot, pkg.rootDir)}/package.json must be an object` + ); + + if (repoMeta.strictness) meta.strictness = repoMeta.strictness; + if (repoMeta.lint) meta.lint = Array.isArray(repoMeta.lint) ? repoMeta.lint : [repoMeta.lint]; + if (repoMeta.env) meta.env = repoMeta.env; + if (repoMeta.built) meta.built = repoMeta.built; + if (repoMeta.supportcjs) meta.supportcjs = repoMeta.supportcjs; + } + + if (Object.keys(entryPoints).length > 0) { + metadata.entryPoints = entryPoints; + } + + // Public packages with buildable entry points are considered built by default. Other packages are + // only considered built if they specify `"built": true` in their `repo-meta` field. + // + // This is because private packages with `.ts` files are typically built as part of another build + // process. The only exception right now is `@glimmer-workspace/benchmark-env`, which is built + // like a published package so that it can be used in the isolated benchmark environment. + if (!manifest.private && hasBuildableEntryPoint(entryPoints)) { + meta.built = true; + } + + return metadata; +}); + +const rootPackage = packagesMetadata.find((pkg) => pkg.root === ''); + +if (!rootPackage) { + throw new Error( + `Could not find root package. The code in repo-metadata/lib/update.ts expects the metadata returned by findWorkspacePackages to include the root package with a root key of '', but no such package was found.` + ); +} + +if (!rootPackage.version) { + throw new Error( + `Could not find 'version' in the root package.json. This version is used as the version of non-published packages, and is required.` + ); +} + +const outFile = resolve(metadataRoot, 'metadata.json'); +const next = JSON.stringify( + { + workspace: { + packages: workspaceInfo.packages, + version: rootPackage.version, + }, + packages: packagesMetadata, + }, + null, + 2 +); +const prev = existsSync(outFile) ? readFileSync(outFile, 'utf-8') : null; + +if (prev && next === JSON.stringify(JSON.parse(prev), null, 2)) { + console.error(`No changes in ${relative(workspaceRoot, outFile)}`); +} else { + writeFileSync(outFile, next, 'utf-8'); + try { + await execa({ cwd: workspaceRoot })`pnpm prettier --write ${outFile}`; + } catch (error) { + console.error(chalk.yellow('Warning: Failed to format metadata.json with prettier:'), error); + } + console.error(`Updated ${relative(workspaceRoot, outFile)}`); +} + +if (process.env['VERBOSE_WARNINGS']) { + for (const [pkgRoot, { name, problems }] of Object.entries(WARNINGS)) { + const packageJSON = `${pkgRoot}/package.json`; + console.error(name ? `${name} (${packageJSON})` : packageJSON); + + for (const [field, { code, expected }] of Object.entries(problems)) { + const problem = `${code} ${field}`; + console.error(expected ? ` ${problem}: expected ${expected}` : ` ${problem}`); + } + + console.groupEnd(); + } +} + +function hasBuildableEntryPoint(entryPoints: PackageEntryPoints): boolean { + return Object.entries(entryPoints).some(([_name, mappings]) => + mappings.some(([_conditions, path]) => isBuildableEntryPoint(path)) + ); +} + +function isBuildableEntryPoint(path: string): boolean { + if (path.endsWith('.ts')) { + return !path.endsWith('.d.ts'); + } + + if (path.endsWith('.mts')) { + return !path.endsWith('.d.mts'); + } + + return false; +} diff --git a/glimmer-vm/repo-metadata/metadata.json b/glimmer-vm/repo-metadata/metadata.json new file mode 100644 index 00000000000..ef4d7fada09 --- /dev/null +++ b/glimmer-vm/repo-metadata/metadata.json @@ -0,0 +1,685 @@ +{ + "workspace": { + "packages": [".meta-updater", "bin", "repo-metadata", "packages/*/*", "packages/*/*/test"], + "version": "0.92.0" + }, + "packages": [ + { + "root": "", + "name": "glimmer-engine", + "version": "0.92.0", + "type": "module", + "private": true, + "repo-meta": { + "built": false + } + }, + { + "root": "bin", + "name": "@glimmer-workspace/bin", + "version": "0.92.0", + "type": "module", + "private": true, + "repo-meta": { + "built": false, + "strictness": "loose", + "lint": ["*"], + "env": ["node", "console"] + }, + "entryPoints": { + "./clean.mjs": [[["default"], "./clean.mjs"]], + "./opcodes/opcodes.schema.json": [[["default"], "./opcodes/opcodes.schema.json"]], + "./opcodes.json": [[["default"], "./opcodes.json"]], + "./package.json": [[["default"], "./package.json"]], + "./patch-all.mjs": [[["default"], "./patch-all.mjs"]], + "./run-tests.mjs": [[["default"], "./run-tests.mjs"]], + "./run-types-tests.mjs": [[["default"], "./run-types-tests.mjs"]], + "./sync-npm-owners.mjs": [[["default"], "./sync-npm-owners.mjs"]] + } + }, + { + "root": "packages/@glimmer-workspace/benchmark-env", + "name": "@glimmer-workspace/benchmark-env", + "version": "0.92.0", + "type": "module", + "private": true, + "repo-meta": { + "built": true, + "strictness": "loose" + }, + "entryPoints": { + ".": [[["default"], "./index.ts"]] + } + }, + { + "root": "packages/@glimmer-workspace/build", + "name": "@glimmer-workspace/build-support", + "version": "0.92.0", + "type": "module", + "private": true, + "repo-meta": { + "built": false, + "strictness": "loose", + "env": ["console"] + }, + "entryPoints": { + ".": [[["default"], "./index.js"]] + } + }, + { + "root": "packages/@glimmer-workspace/env", + "name": "@glimmer-workspace/env", + "version": "0.92.0", + "type": "module", + "private": true, + "repo-meta": { + "built": false + }, + "entryPoints": { + ".": [[["default"], "./index.d.ts"]] + } + }, + { + "root": "packages/@glimmer-workspace/eslint-plugin", + "name": "@glimmer-workspace/eslint-plugin", + "version": "0.92.0", + "type": "module", + "private": true, + "repo-meta": { + "built": false + }, + "entryPoints": { + ".": [[["default"], "./index.js"]] + } + }, + { + "root": "packages/@glimmer-workspace/integration-tests", + "name": "@glimmer-workspace/integration-tests", + "version": "0.92.0", + "type": "module", + "private": true, + "repo-meta": { + "built": false, + "strictness": "loose", + "lint": ["index", "lib/**/*", "test/**/*"] + }, + "entryPoints": { + ".": [[["default"], "./index.ts"]] + } + }, + { + "root": "packages/@glimmer-workspace/integration-tests/test", + "name": "@glimmer-test/integration-tests", + "version": "0.92.0", + "type": "commonjs", + "private": true, + "repo-meta": { + "built": false + }, + "entryPoints": { + "./package.json": [[["default"], "./package.json"]] + } + }, + { + "root": "packages/@glimmer-workspace/test-utils", + "name": "@glimmer-workspace/test-utils", + "version": "0.92.0", + "type": "module", + "private": true, + "repo-meta": { + "built": false + }, + "entryPoints": { + "./package.json": [[["default"], "./package.json"]], + ".": [[["default"], "./index.ts"]], + "./index.ts": [[["default"], "./index.ts"]] + } + }, + { + "root": "packages/@glimmer/compiler", + "name": "@glimmer/compiler", + "version": "0.94.11", + "type": "module", + "private": false, + "repo-meta": { + "built": true, + "supportcjs": true + }, + "entryPoints": { + ".": [[["default"], "./index.ts"]] + } + }, + { + "root": "packages/@glimmer/compiler/test", + "name": "@glimmer-test/compiler", + "version": "0.92.0", + "type": "commonjs", + "private": true, + "repo-meta": { + "built": false + }, + "entryPoints": { + "./package.json": [[["default"], "./package.json"]] + } + }, + { + "root": "packages/@glimmer/constants", + "name": "@glimmer/constants", + "version": "0.92.0", + "type": "module", + "private": true, + "repo-meta": { + "built": false + }, + "entryPoints": { + "./package.json": [[["default"], "./package.json"]], + "./test/package.json": [[["default"], "./test/package.json"]], + ".": [[["default"], "./index.ts"]], + "./index.ts": [[["default"], "./index.ts"]] + } + }, + { + "root": "packages/@glimmer/constants/test", + "name": "@glimmer-test/constants", + "version": "0.92.0", + "type": "commonjs", + "private": true, + "repo-meta": { + "built": false + }, + "entryPoints": { + "./package.json": [[["default"], "./package.json"]] + } + }, + { + "root": "packages/@glimmer/debug", + "name": "@glimmer/debug", + "version": "0.92.0", + "type": "module", + "private": true, + "repo-meta": { + "built": false + }, + "entryPoints": { + ".": [[["default"], "./index.ts"]] + } + }, + { + "root": "packages/@glimmer/debug-util", + "name": "@glimmer/debug-util", + "version": "0.92.0", + "type": "module", + "private": true, + "repo-meta": { + "built": false + }, + "entryPoints": { + ".": [[["default"], "./index.ts"]] + } + }, + { + "root": "packages/@glimmer/debug-util/test", + "name": "@glimmer-test/debug-util", + "version": "0.92.0", + "type": "commonjs", + "private": true, + "repo-meta": { + "built": false + }, + "entryPoints": { + "./package.json": [[["default"], "./package.json"]] + } + }, + { + "root": "packages/@glimmer/debug/test", + "name": "@glimmer-test/debug", + "version": "0.92.0", + "type": "commonjs", + "private": true, + "repo-meta": { + "built": false + }, + "entryPoints": { + "./package.json": [[["default"], "./package.json"]] + } + }, + { + "root": "packages/@glimmer/destroyable", + "name": "@glimmer/destroyable", + "version": "0.94.8", + "type": "module", + "private": false, + "repo-meta": { + "built": true + }, + "entryPoints": { + ".": [[["default"], "./index.ts"]] + } + }, + { + "root": "packages/@glimmer/destroyable/test", + "name": "@glimmer-test/destroyable", + "version": "0.92.0", + "type": "commonjs", + "private": true, + "repo-meta": { + "built": false + }, + "entryPoints": { + "./package.json": [[["default"], "./package.json"]] + } + }, + { + "root": "packages/@glimmer/encoder", + "name": "@glimmer/encoder", + "version": "0.93.8", + "type": "module", + "private": false, + "repo-meta": { + "built": true + }, + "entryPoints": { + ".": [[["default"], "./index.ts"]] + } + }, + { + "root": "packages/@glimmer/global-context", + "name": "@glimmer/global-context", + "version": "0.93.4", + "type": "module", + "private": false, + "repo-meta": { + "built": true + }, + "entryPoints": { + ".": [[["default"], "./index.ts"]] + } + }, + { + "root": "packages/@glimmer/interfaces", + "name": "@glimmer/interfaces", + "version": "0.94.6", + "type": "module", + "private": false, + "repo-meta": { + "built": false + }, + "entryPoints": { + ".": [[["default"], "./index.d.ts"]] + } + }, + { + "root": "packages/@glimmer/local-debug-babel-plugin", + "name": "@glimmer/local-debug-babel-plugin", + "version": "0.92.0", + "type": "module", + "private": true, + "repo-meta": { + "built": false, + "strictness": "loose" + }, + "entryPoints": { + ".": [[["default"], "./index.js"]] + } + }, + { + "root": "packages/@glimmer/local-debug-flags", + "name": "@glimmer/local-debug-flags", + "version": "0.92.0", + "type": "module", + "private": true, + "repo-meta": { + "built": false + }, + "entryPoints": { + ".": [[["default"], "./index.ts"]] + } + }, + { + "root": "packages/@glimmer/manager", + "name": "@glimmer/manager", + "version": "0.94.10", + "type": "module", + "private": false, + "repo-meta": { + "built": true + }, + "entryPoints": { + ".": [[["default"], "./index.ts"]] + } + }, + { + "root": "packages/@glimmer/manager/test", + "name": "@glimmer-test/manager", + "version": "0.92.0", + "type": "commonjs", + "private": true, + "repo-meta": { + "built": false, + "strictness": "loose" + }, + "entryPoints": { + "./package.json": [[["default"], "./package.json"]] + } + }, + { + "root": "packages/@glimmer/node", + "name": "@glimmer/node", + "version": "0.94.10", + "type": "module", + "private": false, + "repo-meta": { + "built": true + }, + "entryPoints": { + ".": [[["default"], "./index.ts"]] + } + }, + { + "root": "packages/@glimmer/opcode-compiler", + "name": "@glimmer/opcode-compiler", + "version": "0.94.10", + "type": "module", + "private": false, + "repo-meta": { + "built": true + }, + "entryPoints": { + ".": [[["default"], "./index.ts"]] + } + }, + { + "root": "packages/@glimmer/owner", + "name": "@glimmer/owner", + "version": "0.93.4", + "type": "module", + "private": false, + "repo-meta": { + "built": true + }, + "entryPoints": { + ".": [[["default"], "./index.ts"]] + } + }, + { + "root": "packages/@glimmer/owner/test", + "name": "@glimmer-test/owner", + "version": "0.92.0", + "type": "commonjs", + "private": true, + "repo-meta": { + "built": false + }, + "entryPoints": { + "./package.json": [[["default"], "./package.json"]] + } + }, + { + "root": "packages/@glimmer/program", + "name": "@glimmer/program", + "version": "0.94.10", + "type": "module", + "private": false, + "repo-meta": { + "built": true + }, + "entryPoints": { + ".": [[["default"], "./index.ts"]] + } + }, + { + "root": "packages/@glimmer/program/test", + "name": "@glimmer-test/program", + "version": "0.92.0", + "type": "commonjs", + "private": true, + "repo-meta": { + "built": false + }, + "entryPoints": { + "./package.json": [[["default"], "./package.json"]] + } + }, + { + "root": "packages/@glimmer/reference", + "name": "@glimmer/reference", + "version": "0.94.9", + "type": "module", + "private": false, + "repo-meta": { + "built": true + }, + "entryPoints": { + ".": [[["default"], "./index.ts"]] + } + }, + { + "root": "packages/@glimmer/reference/test", + "name": "@glimmer-test/reference", + "version": "0.92.0", + "type": "commonjs", + "private": true, + "repo-meta": { + "built": false + }, + "entryPoints": { + "./package.json": [[["default"], "./package.json"]] + } + }, + { + "root": "packages/@glimmer/runtime", + "name": "@glimmer/runtime", + "version": "0.94.11", + "type": "module", + "private": false, + "repo-meta": { + "built": true + }, + "entryPoints": { + ".": [[["default"], "./index.ts"]] + } + }, + { + "root": "packages/@glimmer/syntax", + "name": "@glimmer/syntax", + "version": "0.95.0", + "type": "module", + "private": false, + "repo-meta": { + "built": true, + "supportcjs": true + }, + "entryPoints": { + ".": [[["default"], "./index.ts"]] + } + }, + { + "root": "packages/@glimmer/syntax/test", + "name": "@glimmer-test/syntax", + "version": "0.92.0", + "type": "commonjs", + "private": true, + "repo-meta": { + "built": false + }, + "entryPoints": { + "./package.json": [[["default"], "./package.json"]] + } + }, + { + "root": "packages/@glimmer/util", + "name": "@glimmer/util", + "version": "0.94.8", + "type": "module", + "private": false, + "repo-meta": { + "built": true + }, + "entryPoints": { + ".": [[["default"], "./index.ts"]] + } + }, + { + "root": "packages/@glimmer/util/test", + "name": "@glimmer-test/util", + "version": "0.92.0", + "type": "commonjs", + "private": true, + "repo-meta": { + "built": false + }, + "entryPoints": { + "./package.json": [[["default"], "./package.json"]] + } + }, + { + "root": "packages/@glimmer/validator", + "name": "@glimmer/validator", + "version": "0.95.0", + "type": "module", + "private": false, + "repo-meta": { + "built": true + }, + "entryPoints": { + ".": [[["default"], "./index.ts"]] + } + }, + { + "root": "packages/@glimmer/validator/test", + "name": "@glimmer-test/validator", + "version": "0.92.0", + "type": "commonjs", + "private": true, + "repo-meta": { + "built": false, + "strictness": "strict" + }, + "entryPoints": { + "./package.json": [[["default"], "./package.json"]] + } + }, + { + "root": "packages/@glimmer/vm", + "name": "@glimmer/vm", + "version": "0.94.8", + "type": "module", + "private": false, + "repo-meta": { + "built": true + }, + "entryPoints": { + ".": [[["default"], "./index.ts"]] + } + }, + { + "root": "packages/@glimmer/vm-babel-plugins", + "name": "@glimmer/vm-babel-plugins", + "version": "0.93.5", + "type": "module", + "private": false, + "repo-meta": { + "built": true + }, + "entryPoints": { + ".": [[["default"], "./index.ts"]] + } + }, + { + "root": "packages/@glimmer/wire-format", + "name": "@glimmer/wire-format", + "version": "0.94.8", + "type": "module", + "private": false, + "repo-meta": { + "built": true + }, + "entryPoints": { + ".": [[["default"], "./index.ts"]] + } + }, + { + "root": "packages/@types/eslint-community__eslint-plugin-eslint-comments", + "name": "@types/eslint-community__eslint-plugin-eslint-comments", + "version": "0.92.0", + "type": "commonjs", + "private": true, + "repo-meta": { + "built": false + }, + "entryPoints": { + ".": [[["default"], "./index.d.ts"]] + } + }, + { + "root": "packages/@types/eslint-plugin-import", + "name": "@types/eslint-plugin-import", + "version": "0.92.0", + "type": "module", + "private": true, + "repo-meta": { + "built": false + }, + "entryPoints": { + ".": [[["default"], "./index.d.ts"]] + } + }, + { + "root": "packages/@types/eslint-plugin-qunit", + "name": "@types/eslint-plugin-qunit", + "version": "0.92.0", + "type": "commonjs", + "private": true, + "repo-meta": { + "built": false + }, + "entryPoints": { + "./index.d.ts": [[["default"], "./index.d.ts"]], + "./package.json": [[["default"], "./package.json"]] + } + }, + { + "root": "packages/@types/js-reporters", + "name": "@types/js-reporters", + "version": "0.92.0", + "type": "commonjs", + "private": true, + "repo-meta": { + "built": false + }, + "entryPoints": { + ".": [[["default"], "./index.d.ts"]] + } + }, + { + "root": "packages/@types/puppeteer-chromium-resolver", + "name": "@types/puppeteer-chromium-resolver", + "version": "0.92.0", + "type": "commonjs", + "private": true, + "repo-meta": { + "built": false + }, + "entryPoints": { + ".": [[["default"], "./index.d.ts"]] + } + }, + { + "root": "repo-metadata", + "name": "@glimmer-workspace/repo-metadata", + "version": "0.92.0", + "type": "module", + "private": true, + "repo-meta": { + "built": false + }, + "entryPoints": { + ".": [ + [["types"], "./index.d.ts"], + [["default"], "./index.js"] + ], + "./metadata.json": [[["default"], "./metadata.json"]] + } + } + ] +} diff --git a/glimmer-vm/repo-metadata/package.json b/glimmer-vm/repo-metadata/package.json new file mode 100644 index 00000000000..2a7797589be --- /dev/null +++ b/glimmer-vm/repo-metadata/package.json @@ -0,0 +1,30 @@ +{ + "name": "@glimmer-workspace/repo-metadata", + "private": true, + "version": "0.92.0", + "type": "module", + "exports": { + ".": { + "types": "./index.d.ts", + "default": "./index.js" + }, + "./metadata.json": "./metadata.json" + }, + "scripts": {}, + "dependencies": { + "chalk": "^5.4.1", + "deepmerge": "^4.3.1", + "execa": "^9.5.2", + "globby": "^14.1.0", + "handlebars": "^4.7.8", + "read-pkg": "^9.0.1", + "write-pkg": "^7.0.0", + "yaml": "^2.7.0" + }, + "devDependencies": { + "@types/fs-extra": "^11.0.4", + "@types/handlebars": "^4.1.0", + "@types/node": "^22.13.4", + "pkg-entry-points": "^1.1.1" + } +} diff --git a/glimmer-vm/server/index.js b/glimmer-vm/server/index.js new file mode 100644 index 00000000000..21a814dab02 --- /dev/null +++ b/glimmer-vm/server/index.js @@ -0,0 +1,9 @@ +module.exports = function (app) { + app.get('/', function (req, res) { + res.redirect('/tests/index.html?hidepassed'); + }); + + app.get('/tests', function (req, res) { + res.redirect('/tests/index.html'); + }); +}; diff --git a/glimmer-vm/smoke-tests/node/.gitignore b/glimmer-vm/smoke-tests/node/.gitignore new file mode 100644 index 00000000000..8d12edbe864 --- /dev/null +++ b/glimmer-vm/smoke-tests/node/.gitignore @@ -0,0 +1,2 @@ +packages/ +pnpm-lock.yaml diff --git a/glimmer-vm/smoke-tests/node/package.json b/glimmer-vm/smoke-tests/node/package.json new file mode 100644 index 00000000000..15aa229ee45 --- /dev/null +++ b/glimmer-vm/smoke-tests/node/package.json @@ -0,0 +1,43 @@ +{ + "name": "@glimmer-workspace/smoke-tests-node", + "type": "module", + "private": true, + "engines": { + "node": ">=18.0.0" + }, + "exports": { + ".": "./setup.ts" + }, + "scripts": { + "test:lint": "eslint . --quiet", + "test:node": "vitest --run", + "test:setup": "node --disable-warning=ExperimentalWarning --experimental-strip-types ./setup.ts" + }, + "devDependencies": { + "execa": "^9.5.2", + "vite": "^5.4.10", + "vitest": "^3.0.4", + "prettier": "3.5.3" + }, + "config": { + "tsconfig": "../../tsconfig.json" + }, + "dependencies": { + "@glimmer/syntax": "file:./packages/@glimmer/syntax.tgz", + "@glimmer/util": "file:./packages/@glimmer/util.tgz", + "@glimmer/wire-format": "file:./packages/@glimmer/wire-format.tgz", + "@glimmer/compiler": "file:./packages/@glimmer/compiler.tgz", + "@glimmer/interfaces": "file:./packages/@glimmer/interfaces.tgz", + "@glimmer/runtime": "file:./packages/@glimmer/runtime.tgz" + }, + "pnpm": { + "overrides": { + "@glimmer/syntax": "file:./packages/@glimmer/syntax.tgz", + "@glimmer/util": "file:./packages/@glimmer/util.tgz", + "@glimmer/wire-format": "file:./packages/@glimmer/wire-format.tgz", + "@glimmer/compiler": "file:./packages/@glimmer/compiler.tgz", + "@glimmer/interfaces": "file:./packages/@glimmer/interfaces.tgz", + "@glimmer/runtime": "file:./packages/@glimmer/runtime.tgz" + } + } +} diff --git a/glimmer-vm/smoke-tests/node/setup.ts b/glimmer-vm/smoke-tests/node/setup.ts new file mode 100644 index 00000000000..7fb744be744 --- /dev/null +++ b/glimmer-vm/smoke-tests/node/setup.ts @@ -0,0 +1,74 @@ +import { readFile } from 'node:fs/promises'; +import { join } from 'node:path'; +import { styleText } from 'node:util'; + +import { execaCommand } from 'execa'; + +const WORKSPACE_ROOT = join(import.meta.dirname, '../../'); +const NODE_SMOKE_DIR = join(WORKSPACE_ROOT, './smoke-tests/node'); + +function inRoot(cmd: string, options = {}) { + return inDir(WORKSPACE_ROOT, cmd, options); +} + +let asBin = false; + +function log(msg: any) { + if (asBin) { + console.info(msg); + } +} + +function inDir(dir: string, cmd: string, options = {}) { + log(styleText('gray', `in ${dir}:\n`) + styleText('green', '\t' + cmd)); + + return execaCommand(cmd, { + cwd: dir, + preferLocal: true, + shell: true, + stdio: 'inherit', + ...options, + }); +} + +export function inNodeSmoke(cmd: string, options = {}) { + return inDir(NODE_SMOKE_DIR, cmd, options); +} + +export async function prepare() { + ////////// + // build + // When turbo is set up with "dependsOn": "["^prepack"], we see these packages + // - @glimmer/syntax + // - @glimmer/util + // - @glimmer/wire-format + // + // So these 3 packages need to be packed and installed + await inRoot(`pnpm turbo prepack`); + + let manifestPath = join(WORKSPACE_ROOT, 'smoke-tests/node/package.json'); + let manifest = JSON.parse((await readFile(manifestPath)).toString()); + let deps = Object.keys(manifest.dependencies); + + ////////// + // install the tarballs using stable names so we don't have to + // dynamically build the package.json + let pack = (out: string) => `pnpm pack --out ${join(NODE_SMOKE_DIR, 'packages', out)}.tgz`; + + for (let dep of deps) { + await inDir(join(WORKSPACE_ROOT, `packages/${dep}`), pack(dep)); + } +} + +if (process.argv[1] === import.meta.filename) { + asBin = true; + log(`Setting up smoke test packages`); + log({ WORKSPACE_ROOT, NODE_SMOKE_DIR }); + + await prepare(); + + log(`Installing Deps`); + await inNodeSmoke(`pnpm install --ignore-workspace`); + + log(`Done`); +} diff --git a/glimmer-vm/smoke-tests/node/tests/prettier.test.ts b/glimmer-vm/smoke-tests/node/tests/prettier.test.ts new file mode 100644 index 00000000000..cde553827fb --- /dev/null +++ b/glimmer-vm/smoke-tests/node/tests/prettier.test.ts @@ -0,0 +1,34 @@ +import { createRequire } from 'node:module'; + +import * as prettier from 'prettier'; +import { describe, expect, it } from 'vitest'; + +const require = createRequire(import.meta.url); + +/** + * See: https://github.com/glimmerjs/glimmer-vm/issues/1688 + */ +describe('Prettier', () => { + it(`SMOKE: we've symlinked to the in-repo copy of @glimmer/syntax`, () => { + let workspacePath = require.resolve('@glimmer/syntax'); + let prettierPath = require.resolve('prettier'); + let prettierGlimmer = require.resolve('@glimmer/syntax', { paths: [prettierPath] }); + + expect(prettierGlimmer).toBe(workspacePath); + }); + + it('Underlynig preprocess API works', async () => { + let result = (await import('@glimmer/syntax')).preprocess('

'); + + expect(result, `It can be await import()'d, and doesn't error`).toBeTruthy(); + }); + + it('Prettier can call preprocess', async () => { + let result = await prettier.format(`
\n
`, { parser: 'glimmer' }); + + expect(result).toMatchInlineSnapshot(` + "
+
" + `); + }); +}); diff --git a/glimmer-vm/smoke-tests/node/tests/syntax.test.ts b/glimmer-vm/smoke-tests/node/tests/syntax.test.ts new file mode 100644 index 00000000000..8c5a927c979 --- /dev/null +++ b/glimmer-vm/smoke-tests/node/tests/syntax.test.ts @@ -0,0 +1,96 @@ +import { preprocess } from '@glimmer/syntax'; +import { describe, it, expect } from 'vitest'; + +describe('@glimmer/syntax', () => { + it('process()', () => { + expect(preprocess('

')).toMatchInlineSnapshot(` + { + "blockParams": [], + "body": [ + { + "attributes": [], + "blockParams": [], + "children": [], + "closeTag": { + "end": { + "column": 9, + "line": 1, + }, + "start": { + "column": 4, + "line": 1, + }, + }, + "comments": [], + "loc": { + "end": { + "column": 9, + "line": 1, + }, + "start": { + "column": 0, + "line": 1, + }, + }, + "modifiers": [], + "openTag": { + "end": { + "column": 4, + "line": 1, + }, + "start": { + "column": 0, + "line": 1, + }, + }, + "params": [], + "path": { + "head": { + "loc": { + "end": { + "column": 3, + "line": 1, + }, + "start": { + "column": 1, + "line": 1, + }, + }, + "name": "h1", + "original": "h1", + "type": "VarHead", + }, + "loc": { + "end": { + "column": 3, + "line": 1, + }, + "start": { + "column": 1, + "line": 1, + }, + }, + "original": "h1", + "tail": [], + "type": "PathExpression", + }, + "selfClosing": false, + "tag": "h1", + "type": "ElementNode", + }, + ], + "loc": { + "end": { + "column": 9, + "line": 1, + }, + "start": { + "column": 0, + "line": 1, + }, + }, + "type": "Template", + } + `); + }); +}); diff --git a/glimmer-vm/smoke-tests/node/vite.config.ts b/glimmer-vm/smoke-tests/node/vite.config.ts new file mode 100644 index 00000000000..75417a18269 --- /dev/null +++ b/glimmer-vm/smoke-tests/node/vite.config.ts @@ -0,0 +1,7 @@ +import { defineConfig } from 'vite'; + +export default defineConfig({ + resolve: { + conditions: ['module', 'node', process.env['NODE_ENV'] ?? 'production'], + }, +}); diff --git a/glimmer-vm/test/index.html b/glimmer-vm/test/index.html new file mode 100644 index 00000000000..69e65abaac5 --- /dev/null +++ b/glimmer-vm/test/index.html @@ -0,0 +1,139 @@ + + + + + Glimmer Test Suite + + + + + + +
+
+ + + + + + + + + + + diff --git a/glimmer-vm/testem.js b/glimmer-vm/testem.js new file mode 100644 index 00000000000..95cf322e885 --- /dev/null +++ b/glimmer-vm/testem.js @@ -0,0 +1,36 @@ +'use strict'; + +let isCI = !!process.env.CI; +let smokeTests = !!process.env.SMOKE_TESTS; + +let config = { + framework: 'qunit', + test_page: smokeTests ? 'tests/index.html?smoke_tests=true' : 'tests/index.html?hidepassed', + disable_watching: true, + browser_start_timeout: smokeTests ? 300000 : 30000, + browser_disconnect_timeout: smokeTests ? 120 : 10, + browser_args: { + Chrome: { + mode: 'ci', + args: [ + // --no-sandbox is needed when running Chrome inside a container + process.env.CI ? '--no-sandbox' : null, + '--headless', + '--disable-gpu', + '--disable-dev-shm-usage', + '--disable-software-rasterizer', + '--mute-audio', + '--remote-debugging-port=0', + '--window-size=1440,900', + ], + }, + }, + launch_in_dev: ['Chrome'], + launch_in_ci: ['Chrome'], +}; + +if (isCI) { + config.tap_quiet_logs = true; +} + +module.exports = config; diff --git a/glimmer-vm/turbo.json b/glimmer-vm/turbo.json new file mode 100644 index 00000000000..cecd4440871 --- /dev/null +++ b/glimmer-vm/turbo.json @@ -0,0 +1,81 @@ +{ + "$schema": "https://turbo.build/schema.json", + "ui": "tui", + "globalEnv": ["NODE_ENV", "CI"], + "globalDependencies": [ + "pnpm-lock.yaml", + "patches/**/*", + ".env*", + ".npmrc", + ".prettierrc.json", + "eslint.config.js", + "rollup.config.mjs", + "vite.config.mts", + "tsconfig*.json", + "packages/@glimmer-workspace/eslint-plugin/**/*", + "packages/@glimmer-workspace/build-support/**/*" + ], + "tasks": { + "lint:all": { + "cache": false, + "dependsOn": ["lint", "test:publint"] + }, + "test:node": { + "cache": true, + "inputs": ["test/**/*", "lib/**/*", "!**/*.md"], + "env": ["NODE_ENV"] + }, + "lint": { + "cache": true, + "inputs": [ + "**/*.{js,ts,mjs,mts,cjs,cts,json}", + "!dist/**", + "!node_modules/**", + "!.reference/**" + ] + }, + "test:publint": { + "cache": true, + "dependsOn": ["prepack"], + "inputs": ["package.json", "dist/**/*"] + }, + "prepack": { + "cache": true, + "outputs": ["dist/**"], + "dependsOn": ["^prepack"], + "inputs": [ + "lib/**/*", + "index.{js,ts,mjs,mts}", + "package.json", + "rollup.config.mjs", + "!**/*.md" + ], + "env": ["NODE_ENV"] + }, + "//#test:lint": { + "dependsOn": ["//#repo:update:conventions", "//#repo:update:metadata"] + }, + "//#repo:update:conventions": { + "cache": false + }, + "//#repo:update:metadata": { + "cache": false + }, + "//#test:types": { + "cache": true, + "inputs": ["packages/**/dist/**", "tsconfig.dist.json"], + "dependsOn": ["^prepack", "//#benchmark:setup", "//#smoke:setup"], + "env": ["NODE_ENV"] + }, + "//#benchmark:setup": { + "cache": true, + "outputs": ["benchmark/benchmarks/krausest/packages/**"], + "dependsOn": ["^prepack"] + }, + "//#smoke:setup": { + "cache": true, + "outputs": ["smoke-tests/node/packages/**"], + "dependsOn": ["^prepack"] + } + } +} diff --git a/glimmer-vm/vite.config.mts b/glimmer-vm/vite.config.mts new file mode 100644 index 00000000000..bd7668f97f9 --- /dev/null +++ b/glimmer-vm/vite.config.mts @@ -0,0 +1,29 @@ +import { defineConfig } from 'vite'; +import repo from '@glimmer-workspace/repo-metadata'; + +const published = repo.packages.filter((pkg) => !pkg.private).map((pkg) => pkg.name); + +export default defineConfig({ + server: { + open: '?hidepassed', + }, + mode: 'testing', + optimizeDeps: { + entries: ['./packages/{@glimmer,@glimmer-workspace}/*/test/**/*-test.ts'], + }, + plugins: [ + { + name: 'define custom import.meta.env', + async transform(code) { + if (code.includes('import.meta.env.VM_LOCAL_DEV')) { + return code.replace(/import.meta.env.VM_LOCAL_DEV/g, 'true'); + } + return undefined; + }, + enforce: 'pre', + }, + ], + resolve: { + extensions: ['.mjs', '.js', '.mts', '.ts', '.jsx', '.tsx', '.json', '.d.ts'], + }, +}); diff --git a/index.html b/index.html index 6650ae66571..c6988aa7d69 100644 --- a/index.html +++ b/index.html @@ -74,6 +74,12 @@ import.meta.glob('./packages/*/tests/**/*.{js,ts}', { eager: true, }); + + // packages originally authored in glimmer-vm repo have a different test + // naming convention + import.meta.glob('./packages/{@glimmer,@glimmer-workspace}/*/test/**/*-test.{js,ts}', { + eager: true, + });
diff --git a/package.json b/package.json index ea43b559e35..04a9af68749 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,6 @@ "build": "npm-run-all build:*", "docs": "ember ember-cli-yuidoc", "start": "vite dev", - "link:glimmer-vm": "node bin/link-glimmer-vm-packages.mjs", "lint": "npm-run-all --continue-on-error --aggregate-output --parallel \"lint:!(fix)\"", "lint:docs": "qunit tests/docs/coverage-test.js", "lint:eslint": "eslint --report-unused-disable-directives --cache .", @@ -60,30 +59,13 @@ "test:browserstack": "node bin/run-browserstack-tests.js", "test:wip": "vite build --mode development --minify false && testem ci", "type-check:internals": "tsc --noEmit", - "type-check:types": "pnpm build:types && tsc --noEmit --project type-tests", - "type-check": "npm-run-all type-check:*", - "unlink:all": "node bin/unlink-all.mjs" + "type-check:types": "tsc --noEmit --project type-tests", + "type-check": "npm-run-all type-check:*" }, "dependencies": { "@babel/core": "^7.24.4", "@ember/edition-utils": "^1.2.0", "@embroider/addon-shim": "^1.9.0", - "@glimmer/compiler": "0.94.11", - "@glimmer/destroyable": "0.94.8", - "@glimmer/global-context": "0.93.4", - "@glimmer/interfaces": "0.94.6", - "@glimmer/manager": "0.94.10", - "@glimmer/node": "0.94.10", - "@glimmer/opcode-compiler": "0.94.10", - "@glimmer/owner": "0.93.4", - "@glimmer/program": "0.94.10", - "@glimmer/reference": "0.94.9", - "@glimmer/runtime": "0.94.11", - "@glimmer/syntax": "0.95.0", - "@glimmer/util": "0.94.8", - "@glimmer/validator": "0.95.0", - "@glimmer/vm": "0.94.8", - "@glimmer/vm-babel-plugins": "0.93.5", "@simple-dom/interface": "^1.4.0", "backburner.js": "^2.8.0", "broccoli-file-creator": "^2.1.1", @@ -114,7 +96,7 @@ "@embroider/macros": "^1.18.0", "@embroider/shared-internals": "^2.5.0", "@eslint/js": "^9.21.0", - "@glimmer/component": "workspace:^", + "@glimmer/component": "workspace:*", "@rollup/plugin-babel": "^6.0.4", "@simple-dom/document": "^1.4.0", "@swc-node/register": "^1.6.8", @@ -125,7 +107,7 @@ "ast-types": "^0.14.2", "auto-dist-tag": "^2.1.1", "babel-plugin-debug-macros": "1.0.0", - "babel-plugin-ember-template-compilation": "^2.1.1", + "babel-plugin-ember-template-compilation": "3.0.0-alpha.4", "brotli": "^1.3.3", "dag-map": "^2.0.2", "decorator-transforms": "2.0.0", @@ -164,7 +146,7 @@ "terser": "^5.42.0", "testem": "^3.10.1", "testem-failure-only-reporter": "^1.0.0", - "typescript": "5.2.2", + "typescript": "^5.7.3", "typescript-eslint": "^8.26.0", "vite": "^5.4.12" }, @@ -339,7 +321,6 @@ "@ember/version/index.js": "ember-source/@ember/version/index.js", "@glimmer/destroyable/index.js": "ember-source/@glimmer/destroyable/index.js", "@glimmer/encoder/index.js": "ember-source/@glimmer/encoder/index.js", - "@glimmer/env/index.js": "ember-source/@glimmer/env/index.js", "@glimmer/global-context/index.js": "ember-source/@glimmer/global-context/index.js", "@glimmer/manager/index.js": "ember-source/@glimmer/manager/index.js", "@glimmer/node/index.js": "ember-source/@glimmer/node/index.js", @@ -349,7 +330,7 @@ "@glimmer/reference/index.js": "ember-source/@glimmer/reference/index.js", "@glimmer/runtime/index.js": "ember-source/@glimmer/runtime/index.js", "@glimmer/tracking/index.js": "ember-source/@glimmer/tracking/index.js", - "@glimmer/tracking/primitives/cache.js": "ember-source/@glimmer/tracking/primitives/cache.js", + "@glimmer/tracking/primitives/cache/index.js": "ember-source/@glimmer/tracking/primitives/cache/index.js", "@glimmer/util/index.js": "ember-source/@glimmer/util/index.js", "@glimmer/validator/index.js": "ember-source/@glimmer/validator/index.js", "@glimmer/vm/index.js": "ember-source/@glimmer/vm/index.js", @@ -357,7 +338,6 @@ "@simple-dom/document/index.js": "ember-source/@simple-dom/document/index.js", "backburner.js/index.js": "ember-source/backburner.js/index.js", "dag-map/index.js": "ember-source/dag-map/index.js", - "ember-template-compiler/index.js": "ember-source/ember-template-compiler/index.js", "ember-testing/index.js": "ember-source/ember-testing/index.js", "ember-testing/lib/adapters/adapter.js": "ember-source/ember-testing/lib/adapters/adapter.js", "ember-testing/lib/adapters/qunit.js": "ember-source/ember-testing/lib/adapters/qunit.js", @@ -401,4 +381,4 @@ } }, "packageManager": "pnpm@10.5.0" -} +} \ No newline at end of file diff --git a/packages/@ember/-internals/glimmer/tests/integration/components/render-component-test.ts b/packages/@ember/-internals/glimmer/tests/integration/components/render-component-test.ts index d3411754267..bfdbe80b39f 100644 --- a/packages/@ember/-internals/glimmer/tests/integration/components/render-component-test.ts +++ b/packages/@ember/-internals/glimmer/tests/integration/components/render-component-test.ts @@ -26,7 +26,7 @@ import Service, { service } from '@ember/service'; import type Owner from '@ember/owner'; class RenderComponentTestCase extends AbstractStrictTestCase { - component: (RenderResult & { rerender: () => void }) | undefined; + declare component: (RenderResult & { rerender: () => void }) | undefined; owner: Owner; constructor(assert: QUnit['assert']) { diff --git a/packages/@ember/-internals/package.json b/packages/@ember/-internals/package.json index b0e9e70c0b1..873441b41ab 100644 --- a/packages/@ember/-internals/package.json +++ b/packages/@ember/-internals/package.json @@ -37,29 +37,31 @@ "@ember/modifier": "workspace:*", "@ember/object": "workspace:*", "@ember/owner": "workspace:*", + "@ember/reactive": "workspace:*", "@ember/routing": "workspace:*", "@ember/runloop": "workspace:*", "@ember/service": "workspace:*", "@ember/template-factory": "workspace:*", "@ember/utils": "workspace:*", "@ember/version": "workspace:*", - "@glimmer/compiler": "0.94.11", - "@glimmer/component": "workspace:^", - "@glimmer/destroyable": "0.94.8", - "@glimmer/env": "^0.1.7", - "@glimmer/global-context": "0.93.4", - "@glimmer/interfaces": "0.94.6", - "@glimmer/manager": "0.94.10", - "@glimmer/node": "0.94.10", - "@glimmer/opcode-compiler": "0.94.10", - "@glimmer/owner": "0.93.4", - "@glimmer/program": "0.94.10", - "@glimmer/reference": "0.94.9", - "@glimmer/runtime": "0.94.11", - "@glimmer/syntax": "0.95.0", - "@glimmer/util": "0.94.8", - "@glimmer/validator": "0.95.0", - "@glimmer/vm": "0.94.8", + "@glimmer/compiler": "workspace:*", + "@glimmer/component": "workspace:*", + "@glimmer/destroyable": "workspace:*", + "@glimmer/env": "workspace:*", + "@glimmer/global-context": "workspace:*", + "@glimmer/interfaces": "workspace:*", + "@glimmer/manager": "workspace:*", + "@glimmer/node": "workspace:*", + "@glimmer/opcode-compiler": "workspace:*", + "@glimmer/owner": "workspace:*", + "@glimmer/program": "workspace:*", + "@glimmer/reference": "workspace:*", + "@glimmer/runtime": "workspace:*", + "@glimmer/syntax": "workspace:*", + "@glimmer/tracking": "workspace:*", + "@glimmer/util": "workspace:*", + "@glimmer/validator": "workspace:*", + "@glimmer/vm": "workspace:*", "@simple-dom/interface": "^1.4.0", "backburner.js": "^2.7.0", "dag-map": "^2.0.2", diff --git a/packages/@ember/application/package.json b/packages/@ember/application/package.json index b4a1050a81f..0aa1de249e7 100644 --- a/packages/@ember/application/package.json +++ b/packages/@ember/application/package.json @@ -19,11 +19,11 @@ "@ember/runloop": "workspace:*", "@ember/service": "workspace:*", "@ember/utils": "workspace:*", - "@glimmer/destroyable": "0.94.8", - "@glimmer/env": "^0.1.7", - "@glimmer/owner": "0.93.4", - "@glimmer/util": "0.94.8", - "@glimmer/validator": "0.95.0", + "@glimmer/destroyable": "workspace:*", + "@glimmer/env": "workspace:*", + "@glimmer/owner": "workspace:*", + "@glimmer/util": "workspace:*", + "@glimmer/validator": "workspace:*", "backburner.js": "^2.7.0", "dag-map": "^2.0.2", "ember": "workspace:*", diff --git a/packages/@ember/array/package.json b/packages/@ember/array/package.json index 2e98b131304..4d70f3a7416 100644 --- a/packages/@ember/array/package.json +++ b/packages/@ember/array/package.json @@ -17,12 +17,12 @@ "@ember/object": "workspace:*", "@ember/runloop": "workspace:*", "@ember/utils": "workspace:*", - "@glimmer/destroyable": "0.94.8", - "@glimmer/env": "^0.1.7", - "@glimmer/manager": "0.94.10", - "@glimmer/owner": "0.93.4", - "@glimmer/util": "0.94.8", - "@glimmer/validator": "0.95.0", + "@glimmer/destroyable": "workspace:*", + "@glimmer/env": "workspace:*", + "@glimmer/manager": "workspace:*", + "@glimmer/owner": "workspace:*", + "@glimmer/util": "workspace:*", + "@glimmer/validator": "workspace:*", "expect-type": "^0.15.0", "internal-test-helpers": "workspace:*" } diff --git a/packages/@ember/component/package.json b/packages/@ember/component/package.json index ef1aecc89a8..1ba77462038 100644 --- a/packages/@ember/component/package.json +++ b/packages/@ember/component/package.json @@ -9,12 +9,13 @@ }, "dependencies": { "@ember/-internals": "workspace:*", - "@glimmer/manager": "0.94.10", - "@glimmer/runtime": "0.94.11", + "@glimmer/manager": "workspace:*", + "@glimmer/runtime": "workspace:*", "expect-type": "^0.15.0" }, "devDependencies": { "@ember/object": "workspace:*", - "@ember/owner": "workspace:*" + "@ember/owner": "workspace:*", + "@glimmer/interfaces": "workspace:*" } } diff --git a/packages/@ember/controller/package.json b/packages/@ember/controller/package.json index 232f6fee3b2..516e2c15e8b 100644 --- a/packages/@ember/controller/package.json +++ b/packages/@ember/controller/package.json @@ -12,11 +12,11 @@ "@ember/object": "workspace:*", "@ember/routing": "workspace:*", "@ember/service": "workspace:*", - "@glimmer/destroyable": "0.94.8", - "@glimmer/env": "^0.1.7", - "@glimmer/owner": "0.93.4", - "@glimmer/util": "0.94.8", - "@glimmer/validator": "0.95.0", + "@glimmer/destroyable": "workspace:*", + "@glimmer/env": "workspace:*", + "@glimmer/owner": "workspace:*", + "@glimmer/util": "workspace:*", + "@glimmer/validator":"workspace:*", "expect-type": "^0.15.0", "internal-test-helpers": "workspace:*" }, diff --git a/packages/@ember/debug/package.json b/packages/@ember/debug/package.json index d8dabef0f11..d3dba7157e9 100644 --- a/packages/@ember/debug/package.json +++ b/packages/@ember/debug/package.json @@ -18,12 +18,13 @@ "@ember/routing": "workspace:*", "@ember/runloop": "workspace:*", "@ember/utils": "workspace:*", - "@glimmer/destroyable": "0.94.8", - "@glimmer/env": "^0.1.7", - "@glimmer/manager": "0.94.10", - "@glimmer/owner": "0.93.4", - "@glimmer/util": "0.94.8", - "@glimmer/validator": "0.95.0", + "@glimmer/destroyable": "workspace:*", + "@glimmer/env": "workspace:*", + "@glimmer/interfaces": "workspace:*", + "@glimmer/manager": "workspace:*", + "@glimmer/owner": "workspace:*", + "@glimmer/util": "workspace:*", + "@glimmer/validator": "workspace:*", "backburner.js": "^2.7.0", "expect-type": "^0.15.0", "internal-test-helpers": "workspace:*" diff --git a/packages/@ember/destroyable/package.json b/packages/@ember/destroyable/package.json index cc8b4d344cd..07688a98e9e 100644 --- a/packages/@ember/destroyable/package.json +++ b/packages/@ember/destroyable/package.json @@ -6,7 +6,7 @@ ".": "./index.ts" }, "dependencies": { - "@glimmer/destroyable": "0.94.8", + "@glimmer/destroyable": "workspace:*", "expect-type": "^0.15.0" } } diff --git a/packages/@ember/engine/package.json b/packages/@ember/engine/package.json index 38cae238ae8..75ace0b4a22 100644 --- a/packages/@ember/engine/package.json +++ b/packages/@ember/engine/package.json @@ -19,11 +19,11 @@ "@ember/runloop": "workspace:*", "@ember/service": "workspace:*", "@ember/utils": "workspace:*", - "@glimmer/destroyable": "0.94.8", - "@glimmer/env": "^0.1.7", - "@glimmer/owner": "0.93.4", - "@glimmer/util": "0.94.8", - "@glimmer/validator": "0.95.0", + "@glimmer/destroyable": "workspace:*", + "@glimmer/env": "workspace:*", + "@glimmer/owner": "workspace:*", + "@glimmer/util": "workspace:*", + "@glimmer/validator": "workspace:*", "dag-map": "^2.0.2", "expect-type": "^0.15.0", "internal-test-helpers": "workspace:*", diff --git a/packages/@ember/enumerable/package.json b/packages/@ember/enumerable/package.json index 2df6ea6d669..8c7a9a95bf2 100644 --- a/packages/@ember/enumerable/package.json +++ b/packages/@ember/enumerable/package.json @@ -11,11 +11,11 @@ "@ember/array": "workspace:*", "@ember/debug": "workspace:*", "@ember/object": "workspace:*", - "@glimmer/destroyable": "0.94.8", - "@glimmer/env": "^0.1.7", - "@glimmer/owner": "0.93.4", - "@glimmer/util": "0.94.8", - "@glimmer/validator": "0.95.0", + "@glimmer/destroyable": "workspace:*", + "@glimmer/env": "workspace:*", + "@glimmer/owner": "workspace:*", + "@glimmer/util": "workspace:*", + "@glimmer/validator": "workspace:*", "internal-test-helpers": "workspace:*" } } diff --git a/packages/@ember/helper/package.json b/packages/@ember/helper/package.json index dbaa12165ae..08cdf2c7a0e 100644 --- a/packages/@ember/helper/package.json +++ b/packages/@ember/helper/package.json @@ -8,8 +8,10 @@ "dependencies": { "@ember/-internals": "workspace:*", "@ember/component": "workspace:*", - "@glimmer/manager": "0.94.10", - "@glimmer/runtime": "0.94.11", + "@glimmer/interfaces": "workspace:*", + "@glimmer/manager": "workspace:*", + "@glimmer/runtime": "workspace:*", + "@glimmer/validator": "workspace:*", "expect-type": "^0.15.0" } } diff --git a/packages/@ember/instrumentation/package.json b/packages/@ember/instrumentation/package.json index 9a10a4b808d..71c5dba9d64 100644 --- a/packages/@ember/instrumentation/package.json +++ b/packages/@ember/instrumentation/package.json @@ -13,8 +13,8 @@ "@ember/object": "workspace:*", "@ember/runloop": "workspace:*", "@ember/utils": "workspace:*", - "@glimmer/env": "^0.1.7", - "@glimmer/validator": "0.95.0", + "@glimmer/env": "workspace:*", + "@glimmer/validator": "workspace:*", "internal-test-helpers": "workspace:*" } } diff --git a/packages/@ember/modifier/package.json b/packages/@ember/modifier/package.json index 881a0265b7a..ce095c02a16 100644 --- a/packages/@ember/modifier/package.json +++ b/packages/@ember/modifier/package.json @@ -9,7 +9,8 @@ "dependencies": { "@ember/-internals": "workspace:*", "@ember/owner": "workspace:*", - "@glimmer/manager": "0.94.10", - "@glimmer/runtime": "0.94.11" + "@glimmer/interfaces": "workspace:*", + "@glimmer/manager": "workspace:*", + "@glimmer/runtime": "workspace:*" } } diff --git a/packages/@ember/object/package.json b/packages/@ember/object/package.json index 57993fbff6b..d6e7c7eaeb4 100644 --- a/packages/@ember/object/package.json +++ b/packages/@ember/object/package.json @@ -26,12 +26,12 @@ "@ember/runloop": "workspace:*", "@ember/service": "workspace:*", "@ember/utils": "workspace:*", - "@glimmer/destroyable": "0.94.8", - "@glimmer/env": "^0.1.7", - "@glimmer/manager": "0.94.10", - "@glimmer/owner": "0.93.4", - "@glimmer/util": "0.94.8", - "@glimmer/validator": "0.95.0", + "@glimmer/destroyable": "workspace:*", + "@glimmer/env": "workspace:*", + "@glimmer/manager": "workspace:*", + "@glimmer/owner": "workspace:*", + "@glimmer/util": "workspace:*", + "@glimmer/validator": "workspace:*", "expect-type": "^0.15.0", "internal-test-helpers": "workspace:*" }, diff --git a/packages/@ember/owner/package.json b/packages/@ember/owner/package.json index ae12cf5dbb3..2ee55bd4ae5 100644 --- a/packages/@ember/owner/package.json +++ b/packages/@ember/owner/package.json @@ -13,8 +13,8 @@ "@ember/object": "workspace:*", "@ember/routing": "workspace:*", "@ember/runloop": "workspace:*", - "@glimmer/component": "workspace:^", - "@glimmer/env": "^0.1.7", + "@glimmer/component": "workspace:*", + "@glimmer/env": "workspace:*", "expect-type": "^0.15.0" } } diff --git a/packages/@ember/routing/package.json b/packages/@ember/routing/package.json index 8d5d9c04b4f..c7eca12260a 100644 --- a/packages/@ember/routing/package.json +++ b/packages/@ember/routing/package.json @@ -26,12 +26,13 @@ "@ember/runloop": "workspace:*", "@ember/service": "workspace:*", "@ember/utils": "workspace:*", - "@glimmer/destroyable": "0.94.8", - "@glimmer/env": "^0.1.7", - "@glimmer/manager": "0.94.10", - "@glimmer/owner": "0.93.4", - "@glimmer/util": "0.94.8", - "@glimmer/validator": "0.95.0", + "@glimmer/destroyable": "workspace:*", + "@glimmer/env": "workspace:*", + "@glimmer/interfaces": "workspace:*", + "@glimmer/manager": "workspace:*", + "@glimmer/owner": "workspace:*", + "@glimmer/util": "workspace:*", + "@glimmer/validator": "workspace:*", "backburner.js": "^2.7.0", "dag-map": "^2.0.2", "expect-type": "^0.15.0", diff --git a/packages/@ember/runloop/package.json b/packages/@ember/runloop/package.json index aea9ebd3ae4..ec634d80459 100644 --- a/packages/@ember/runloop/package.json +++ b/packages/@ember/runloop/package.json @@ -12,8 +12,8 @@ "@ember/debug": "workspace:*", "@ember/object": "workspace:*", "@ember/utils": "workspace:*", - "@glimmer/env": "^0.1.7", - "@glimmer/validator": "0.95.0", + "@glimmer/env": "workspace:*", + "@glimmer/validator": "workspace:*", "backburner.js": "^2.7.0", "expect-type": "^0.15.0", "internal-test-helpers": "workspace:*" diff --git a/packages/@ember/service/package.json b/packages/@ember/service/package.json index 5972a5d90d2..d098d020379 100644 --- a/packages/@ember/service/package.json +++ b/packages/@ember/service/package.json @@ -10,11 +10,11 @@ "@ember/array": "workspace:*", "@ember/debug": "workspace:*", "@ember/object": "workspace:*", - "@glimmer/destroyable": "0.94.8", - "@glimmer/env": "^0.1.7", - "@glimmer/owner": "0.93.4", - "@glimmer/util": "0.94.8", - "@glimmer/validator": "0.95.0", + "@glimmer/destroyable": "workspace:*", + "@glimmer/env": "workspace:*", + "@glimmer/owner": "workspace:*", + "@glimmer/util": "workspace:*", + "@glimmer/validator": "workspace:*", "expect-type": "^0.15.0", "internal-test-helpers": "workspace:*" }, diff --git a/packages/@ember/template-compilation/package.json b/packages/@ember/template-compilation/package.json index 5b4c27b28d8..751f7ce4016 100644 --- a/packages/@ember/template-compilation/package.json +++ b/packages/@ember/template-compilation/package.json @@ -8,9 +8,10 @@ "dependencies": { "@ember/-internals": "workspace:*", "@ember/canary-features": "workspace:*", - "@glimmer/compiler": "0.94.11", - "@glimmer/env": "^0.1.7", - "@glimmer/syntax": "0.95.0", + "@glimmer/compiler": "workspace:*", + "@glimmer/env": "workspace:*", + "@glimmer/interfaces": "workspace:*", + "@glimmer/syntax": "workspace:*", "ember": "workspace:*", "ember-template-compiler": "workspace:*" } diff --git a/packages/@ember/template-compiler/package.json b/packages/@ember/template-compiler/package.json index 7ef7e089bec..7a10006fbad 100644 --- a/packages/@ember/template-compiler/package.json +++ b/packages/@ember/template-compiler/package.json @@ -12,12 +12,12 @@ "@ember/-internals": "workspace:*", "@ember/component": "workspace:*", "@ember/debug": "workspace:*", - "@glimmer/compiler": "0.94.11", - "@glimmer/env": "^0.1.7", - "@glimmer/interfaces": "0.94.6", - "@glimmer/manager": "0.94.10", - "@glimmer/opcode-compiler": "0.94.10", - "@glimmer/syntax": "0.95.0", + "@glimmer/compiler": "workspace:*", + "@glimmer/env": "workspace:*", + "@glimmer/interfaces": "workspace:*", + "@glimmer/manager": "workspace:*", + "@glimmer/opcode-compiler": "workspace:*", + "@glimmer/syntax": "workspace:*", "expect-type": "^0.15.0" }, "devDependencies": { diff --git a/packages/@ember/utils/package.json b/packages/@ember/utils/package.json index 705bd53417a..43ffa12c448 100644 --- a/packages/@ember/utils/package.json +++ b/packages/@ember/utils/package.json @@ -13,12 +13,12 @@ "@ember/enumerable": "workspace:*", "@ember/object": "workspace:*", "@ember/runloop": "workspace:*", - "@glimmer/destroyable": "0.94.8", - "@glimmer/env": "^0.1.7", - "@glimmer/manager": "0.94.10", - "@glimmer/owner": "0.93.4", - "@glimmer/util": "0.94.8", - "@glimmer/validator": "0.95.0", + "@glimmer/destroyable": "workspace:*", + "@glimmer/env": "workspace:*", + "@glimmer/manager": "workspace:*", + "@glimmer/owner": "workspace:*", + "@glimmer/util": "workspace:*", + "@glimmer/validator": "workspace:*", "expect-type": "^0.15.0", "internal-test-helpers": "workspace:*" } diff --git a/packages/@ember/version/package.json b/packages/@ember/version/package.json index 1ddde78a042..aac5a26488e 100644 --- a/packages/@ember/version/package.json +++ b/packages/@ember/version/package.json @@ -22,8 +22,8 @@ "@ember/runloop": "workspace:*", "@ember/service": "workspace:*", "@ember/utils": "workspace:*", - "@glimmer/manager": "0.94.10", - "@glimmer/runtime": "0.94.11", + "@glimmer/manager": "workspace:*", + "@glimmer/runtime": "workspace:*", "backburner.js": "^2.7.0", "ember": "workspace:*", "expect-type": "^0.15.0" diff --git a/packages/@glimmer-workspace/env/index.d.ts b/packages/@glimmer-workspace/env/index.d.ts new file mode 100644 index 00000000000..2ec39c225c9 --- /dev/null +++ b/packages/@glimmer-workspace/env/index.d.ts @@ -0,0 +1,17 @@ +/** + * Declare import.meta.env in state, since it's the root package. + */ + +interface ImportMetaEnv { + BASE_URL: string; + MODE: string; + DEV: boolean; + PROD: boolean; + SSR: boolean; +} + +interface ImportMeta { + url: string; + + readonly env: ImportMetaEnv; +} diff --git a/packages/@glimmer-workspace/env/package.json b/packages/@glimmer-workspace/env/package.json new file mode 100644 index 00000000000..0dddbc69cff --- /dev/null +++ b/packages/@glimmer-workspace/env/package.json @@ -0,0 +1,8 @@ +{ + "name": "@glimmer-workspace/env", + "private": true, + "version": "0.92.0", + "type": "module", + "exports": "./index.d.ts", + "scripts": {} +} diff --git a/packages/@glimmer-workspace/integration-tests/index.ts b/packages/@glimmer-workspace/integration-tests/index.ts new file mode 100644 index 00000000000..1199fdaa1db --- /dev/null +++ b/packages/@glimmer-workspace/integration-tests/index.ts @@ -0,0 +1,26 @@ +export * from './lib/base-env'; +export * from './lib/compile'; +export * from './lib/components'; +export * from './lib/dom/assertions'; +export * from './lib/dom/blocks'; +export * from './lib/dom/simple-utils'; +export * from './lib/markers'; +export * from './lib/modes/env'; +export * from './lib/modes/jit/delegate'; +export * from './lib/modes/jit/register'; +export * from './lib/modes/jit/resolver'; +export * from './lib/modes/node/env'; +export * from './lib/modes/rehydration/delegate'; +export * from './lib/modes/rehydration/partial-rehydration-delegate'; +export type { default as RenderDelegate, RenderDelegateOptions } from './lib/render-delegate'; +export * from './lib/render-test'; +export * from './lib/setup-harness'; +export * from './lib/snapshot'; +export * from './lib/suites'; +export * from './lib/test-decorator'; +export * from './lib/test-helpers/define'; +export * from './lib/test-helpers/module'; +export * from './lib/test-helpers/strings'; +export * from './lib/test-helpers/tracked'; +export * from './lib/test-helpers/tracked-object'; +export { syntaxErrorFor } from '@glimmer-workspace/test-utils'; diff --git a/packages/@glimmer-workspace/integration-tests/lib/base-env.ts b/packages/@glimmer-workspace/integration-tests/lib/base-env.ts new file mode 100644 index 00000000000..24dc0280253 --- /dev/null +++ b/packages/@glimmer-workspace/integration-tests/lib/base-env.ts @@ -0,0 +1,37 @@ +import type { Destroyable, Destructor } from '@glimmer/interfaces'; +import type { EnvironmentDelegate } from '@glimmer/runtime'; + +interface Scheduled { + destroyable: Destroyable; + destructor: Destructor; +} + +let scheduled: Scheduled[] = []; +let scheduledFinishDestruction: (() => void)[] = []; + +export function scheduleWillDestroy(task: Scheduled) { + scheduled.push(task); +} + +export function scheduleDidDestroy(fn: () => void) { + scheduledFinishDestruction.push(fn); +} + +export const BaseEnv: EnvironmentDelegate = { + isInteractive: true, + + enableDebugTooling: false, + + onTransactionCommit() { + for (const { destroyable, destructor } of scheduled) { + destructor(destroyable); + } + + scheduledFinishDestruction.forEach((fn) => fn()); + + scheduled = []; + scheduledFinishDestruction = []; + }, +}; + +export {}; diff --git a/packages/@glimmer-workspace/integration-tests/lib/compile.ts b/packages/@glimmer-workspace/integration-tests/lib/compile.ts new file mode 100644 index 00000000000..012278e8765 --- /dev/null +++ b/packages/@glimmer-workspace/integration-tests/lib/compile.ts @@ -0,0 +1,42 @@ +import type { + Nullable, + SerializedTemplateWithLazyBlock, + Template, + TemplateFactory, +} from '@glimmer/interfaces'; +import type { PrecompileOptions, PrecompileOptionsWithLexicalScope } from '@glimmer/syntax'; +import { precompileJSON } from '@glimmer/compiler'; +import { templateFactory } from '@glimmer/opcode-compiler'; + +// TODO: This fundamentally has little to do with testing and +// most tests should just use a more generic preprocess, extracted +// out of the test environment. +export function preprocess(templateSource: string, options?: PrecompileOptions): Template { + return createTemplate(templateSource, options)({}); +} + +let templateId = 0; + +export function createTemplate( + templateSource: Nullable, + options: PrecompileOptions | PrecompileOptionsWithLexicalScope = {}, + scopeValues: Record = {} +): TemplateFactory { + options.locals = options.locals ?? Object.keys(scopeValues ?? {}); + let [block, usedLocals] = precompileJSON(templateSource, options); + let reifiedScopeValues = usedLocals.map((key) => scopeValues[key]); + + if ('emit' in options && options.emit?.debugSymbols) { + block.push(usedLocals); + } + + let templateBlock: SerializedTemplateWithLazyBlock = { + id: String(templateId++), + block: JSON.stringify(block), + moduleName: options.meta?.moduleName ?? '(unknown template module)', + scope: reifiedScopeValues.length > 0 ? () => reifiedScopeValues : null, + isStrictMode: options.strictMode ?? false, + }; + + return templateFactory(templateBlock); +} diff --git a/packages/@glimmer-workspace/integration-tests/lib/components.ts b/packages/@glimmer-workspace/integration-tests/lib/components.ts new file mode 100644 index 00000000000..d7eeb0bfa44 --- /dev/null +++ b/packages/@glimmer-workspace/integration-tests/lib/components.ts @@ -0,0 +1,3 @@ +export * from './components/emberish-curly'; +export * from './components/emberish-glimmer'; +export * from './components/types'; diff --git a/packages/@glimmer-workspace/integration-tests/lib/components/emberish-curly.ts b/packages/@glimmer-workspace/integration-tests/lib/components/emberish-curly.ts new file mode 100644 index 00000000000..010301e0131 --- /dev/null +++ b/packages/@glimmer-workspace/integration-tests/lib/components/emberish-curly.ts @@ -0,0 +1,326 @@ +import type { + Bounds, + CapturedNamedArguments, + CompilableProgram, + Destroyable, + Dict, + DynamicScope, + ElementOperations, + Environment, + InternalComponentCapabilities, + Nullable, + Owner, + PreparedArguments, + Reference, + Template, + VMArguments, + WithCreateInstance, + WithDynamicLayout, + WithDynamicTagName, +} from '@glimmer/interfaces'; +import type { DirtyableTag } from '@glimmer/validator'; +import { unwrapTemplate } from '@glimmer/debug-util'; +import { registerDestructor } from '@glimmer/destroyable'; +import { setInternalComponentManager } from '@glimmer/manager'; +import { + childRefFor, + createComputeRef, + createConstRef, + createPrimitiveRef, + valueForRef, +} from '@glimmer/reference'; +import { reifyNamed, reifyPositional } from '@glimmer/runtime'; +import { assign, EMPTY_ARRAY, keys } from '@glimmer/util'; +import { consumeTag, createTag, dirtyTag, dirtyTagFor } from '@glimmer/validator'; + +import type { TestJitRuntimeResolver } from '../modes/jit/resolver'; +import type { TestComponentConstructor } from './types'; + +export type Attrs = Dict; +export type AttrsDiff = { oldAttrs: Nullable; newAttrs: Attrs }; + +export interface EmberishCurlyComponentFactory + extends TestComponentConstructor { + fromDynamicScope?: string[]; + positionalParams: string | string[]; + create(options: { attrs: Attrs; targetObject: any }): EmberishCurlyComponent; + new (...args: unknown[]): this; +} + +let GUID = 1; + +export class EmberishCurlyComponent { + public static positionalParams: string[] | string = []; + + public dirtinessTag: DirtyableTag = createTag(); + declare public layout: Template; + declare public name: string; + public tagName: Nullable = null; + public attributeBindings: Nullable = null; + declare public attrs: Attrs; + declare public element: Element; + declare public bounds: Bounds; + public parentView: Nullable = null; + declare public args: CapturedNamedArguments; + + public _guid: string; + + // create(options: { attrs: Attrs; targetObject: any }): EmberishCurlyComponent + + static create(args: { attrs: Attrs; targetObject: any }): EmberishCurlyComponent { + let c = new this(); + + for (let key of keys(args)) { + (c as any)[key] = args[key]; + } + + return c; + } + + init() {} + + constructor() { + this._guid = `${GUID++}`; + this.init(); + } + + set(key: string, value: unknown) { + (this as any)[key] = value; + dirtyTagFor(this, key); + } + + setProperties(dict: Dict) { + for (let key of keys(dict)) { + this.set(key, dict[key]); + } + } + + recompute() { + dirtyTag(this.dirtinessTag); + } + + destroy() {} + + didInitAttrs(_options: { attrs: Attrs }) {} + didUpdateAttrs(_diff: AttrsDiff) {} + didReceiveAttrs(_diff: AttrsDiff) {} + willInsertElement() {} + willDestroyElement() {} + willUpdate() {} + willRender() {} + didInsertElement() {} + didUpdate() {} + didRender() {} +} + +export interface EmberishCurlyComponentState { + component: EmberishCurlyComponent; + selfRef: Reference; +} + +const EMBERISH_CURLY_CAPABILITIES: InternalComponentCapabilities = { + dynamicLayout: true, + dynamicTag: true, + prepareArgs: true, + createArgs: true, + attributeHook: true, + elementHook: true, + dynamicScope: true, + createCaller: true, + updateHook: true, + createInstance: true, + wrapped: true, + willDestroy: true, + hasSubOwner: false, +}; + +export class EmberishCurlyComponentManager + implements + WithCreateInstance, + WithDynamicTagName, + WithDynamicLayout +{ + getDebugName(state: EmberishCurlyComponentFactory) { + return state.name; + } + + getCapabilities(): InternalComponentCapabilities { + return EMBERISH_CURLY_CAPABILITIES; + } + + getDynamicLayout({ + component: { layout }, + }: EmberishCurlyComponentState): CompilableProgram | null { + if (layout) { + return unwrapTemplate(layout).asWrappedLayout(); + } + + return null; + } + + prepareArgs( + definition: EmberishCurlyComponentFactory, + args: VMArguments + ): Nullable { + const { positionalParams } = definition || EmberishCurlyComponent; + if (typeof positionalParams === 'string') { + if (args.named.has(positionalParams)) { + if (args.positional.length === 0) { + return null; + } else { + throw new Error( + `You cannot specify positional parameters and the hash argument \`${positionalParams}\`.` + ); + } + } + + let named = args.named.capture(); + let positional = args.positional.capture(); + named[positionalParams] = createComputeRef(() => reifyPositional(positional)); + + return { positional: EMPTY_ARRAY, named } as PreparedArguments; + } else if (Array.isArray(positionalParams)) { + let named = assign({}, args.named.capture()); + let count = Math.min(positionalParams.length, args.positional.length); + + for (let i = 0; i < count; i++) { + let name = positionalParams[i] as string; + + if (named[name]) { + throw new Error( + `You cannot specify both a positional param (at position ${i}) and the hash argument \`${name}\`.` + ); + } + + named[name] = args.positional.at(i); + } + + return { positional: EMPTY_ARRAY, named } as PreparedArguments; + } else { + return null; + } + } + + create( + _owner: Owner, + definition: EmberishCurlyComponentFactory, + _args: VMArguments, + _env: Environment, + dynamicScope: DynamicScope, + callerSelf: Reference, + hasDefaultBlock: boolean + ): EmberishCurlyComponentState { + let klass = definition || EmberishCurlyComponent; + let self = valueForRef(callerSelf); + let args = _args.named.capture(); + let attrs = reifyNamed(args); + let merged = assign( + {}, + attrs, + { attrs }, + { args }, + { targetObject: self }, + { HAS_BLOCK: hasDefaultBlock } + ); + let component = klass.create(merged); + + component.args = args; + + let dyn: Nullable = klass.fromDynamicScope || null; + + if (dyn) { + for (let i = 0; i < dyn.length; i++) { + let name = dyn[i] as string; + component.set(name, valueForRef(dynamicScope.get(name))); + } + } + + consumeTag(component.dirtinessTag); + + component.didInitAttrs({ attrs }); + component.didReceiveAttrs({ oldAttrs: null, newAttrs: attrs }); + component.willInsertElement(); + component.willRender(); + + registerDestructor(component, () => component.destroy()); + + const selfRef = createConstRef(component, 'this'); + + return { component, selfRef }; + } + + getSelf({ selfRef }: EmberishCurlyComponentState): Reference { + return selfRef; + } + + getTagName({ component: { tagName } }: EmberishCurlyComponentState): Nullable { + if (tagName) { + return tagName; + } else if (tagName === null) { + return 'div'; + } else { + return null; + } + } + + didCreateElement( + { component, selfRef }: EmberishCurlyComponentState, + element: Element, + operations: ElementOperations + ): void { + component.element = element; + + operations.setAttribute('id', createPrimitiveRef(`ember${component._guid}`), false, null); + operations.setAttribute('class', createPrimitiveRef('ember-view'), false, null); + + let bindings = component.attributeBindings; + + if (bindings) { + for (const attribute of bindings) { + let reference = childRefFor(selfRef, attribute); + + operations.setAttribute(attribute, reference, false, null); + } + } + } + + didRenderLayout({ component }: EmberishCurlyComponentState, bounds: Bounds): void { + component.bounds = bounds; + } + + didCreate({ component }: EmberishCurlyComponentState): void { + component.didInsertElement(); + registerDestructor(component, () => component.willDestroyElement(), true); + + component.didRender(); + } + + update({ component }: EmberishCurlyComponentState): void { + let oldAttrs = component.attrs; + let newAttrs = reifyNamed(component.args); + let merged = assign({}, newAttrs, { attrs: newAttrs }); + + consumeTag(component.dirtinessTag); + + component.setProperties(merged); + component.didUpdateAttrs({ oldAttrs, newAttrs }); + component.didReceiveAttrs({ oldAttrs, newAttrs }); + component.willUpdate(); + component.willRender(); + } + + didUpdateLayout(): void {} + + didUpdate({ component }: EmberishCurlyComponentState): void { + component.didUpdate(); + component.didRender(); + } + + getDestroyable({ component }: EmberishCurlyComponentState): Destroyable { + return component; + } +} + +const EMBERISH_CURLY_COMPONENT_MANAGER = new EmberishCurlyComponentManager(); + +setInternalComponentManager(EMBERISH_CURLY_COMPONENT_MANAGER, EmberishCurlyComponent); diff --git a/packages/@glimmer-workspace/integration-tests/lib/components/emberish-glimmer.ts b/packages/@glimmer-workspace/integration-tests/lib/components/emberish-glimmer.ts new file mode 100644 index 00000000000..42a5f2f9e30 --- /dev/null +++ b/packages/@glimmer-workspace/integration-tests/lib/components/emberish-glimmer.ts @@ -0,0 +1,65 @@ +import type { Arguments, ComponentManager, Dict, Owner } from '@glimmer/interfaces'; +import { destroy, isDestroyed, isDestroying, registerDestructor } from '@glimmer/destroyable'; +import { componentCapabilities, setComponentManager } from '@glimmer/manager'; +import { setOwner } from '@glimmer/owner'; + +export type Args = Dict; + +export class GlimmerishComponent { + public args: Dict; + + constructor(owner: Owner, args: Dict) { + setOwner(this, owner); + this.args = args; + } + + get isDestroying() { + return isDestroying(this); + } + + get isDestroyed() { + return isDestroyed(this); + } + + willDestroy() {} +} + +export interface Constructor { + // eslint-disable-next-line @typescript-eslint/no-empty-object-type + new (owner: unknown, args: {}): T; +} + +const CAPABILITIES = componentCapabilities('3.13', { + destructor: true, +}); + +class GlimmerComponentManager implements ComponentManager { + capabilities = CAPABILITIES; + + private owner: unknown; + + constructor(owner: unknown) { + this.owner = owner; + } + + createComponent( + ComponentClass: Constructor, + args: Arguments + ): GlimmerishComponent { + let component = new ComponentClass(this.owner, args.named); + + registerDestructor(component, () => component.willDestroy()); + + return component; + } + + getContext(component: GlimmerishComponent): GlimmerishComponent { + return component; + } + + destroyComponent(component: GlimmerishComponent): void { + destroy(component); + } +} + +setComponentManager((owner) => new GlimmerComponentManager(owner), GlimmerishComponent); diff --git a/packages/@glimmer-workspace/integration-tests/lib/components/types.ts b/packages/@glimmer-workspace/integration-tests/lib/components/types.ts new file mode 100644 index 00000000000..15a1d61a289 --- /dev/null +++ b/packages/@glimmer-workspace/integration-tests/lib/components/types.ts @@ -0,0 +1,35 @@ +import type { Dict } from '@glimmer/interfaces'; +import type { TemplateOnlyComponent } from '@glimmer/runtime'; + +import type { EmberishCurlyComponent } from './emberish-curly'; +import type { GlimmerishComponent } from './emberish-glimmer'; + +export type ComponentKind = 'Glimmer' | 'Curly' | 'Dynamic' | 'TemplateOnly' | 'Custom' | 'unknown'; + +export interface TestComponentConstructor { + new (): T; +} + +export interface ComponentTypes { + Glimmer: typeof GlimmerishComponent; + Curly: TestComponentConstructor; + Dynamic: TestComponentConstructor; + TemplateOnly: TemplateOnlyComponent; + Custom: unknown; + unknown: unknown; +} + +export interface ComponentBlueprint { + layout: string; + tag?: string; + else?: string; + template?: string; + name?: string; + args?: Dict; + attributes?: Dict; + layoutAttributes?: Dict; + blockParams?: string[]; +} + +export const GLIMMER_TEST_COMPONENT = 'TestComponent'; +export const CURLY_TEST_COMPONENT = 'test-component'; diff --git a/packages/@glimmer-workspace/integration-tests/lib/dom/assertions.ts b/packages/@glimmer-workspace/integration-tests/lib/dom/assertions.ts new file mode 100644 index 00000000000..f064182840c --- /dev/null +++ b/packages/@glimmer-workspace/integration-tests/lib/dom/assertions.ts @@ -0,0 +1,273 @@ +/* eslint-disable @typescript-eslint/no-unsafe-enum-comparison */ +import type { Dict, SimpleElement, SimpleNode } from '@glimmer/interfaces'; +import { isSimpleElement } from '@glimmer/debug-util'; +import { assign, dict } from '@glimmer/util'; + +export interface DebugElement { + element: SimpleElement | null | undefined; + description: string; +} + +function isDebugElement(el: SimpleNode | Node | DebugElement): el is DebugElement { + return !('nodeType' in el); +} + +function extract(node: EqualsElement): DebugElement { + if (node === null || node === undefined) { + return { element: node, description: 'element' }; + } else if (isDebugElement(node)) { + return node; + } else if (isSimpleElement(node)) { + return { element: node, description: node.tagName }; + } else { + return { element: null, description: node.constructor.name }; + } +} + +export type EqualsElement = SimpleNode | Node | null | undefined | DebugElement; + +export function equalsElement( + input: EqualsElement, + tagName: string, + attributes: Dict, + content: string | null +) { + let { element, description } = extract(input); + + if (element === null || element === undefined) { + QUnit.assert.pushResult({ + result: false, + actual: element, + expected: true, + message: `failed - expected ${description} to be present (it was ${ + element === null ? 'null' : 'missing' + })`, + }); + return; + } + + QUnit.assert.pushResult({ + result: element.tagName === tagName.toUpperCase(), + actual: element.tagName.toLowerCase(), + expected: tagName, + message: `expect ${description}'s tagName to be ${tagName}`, + }); + + let expectedAttrs: Dict = dict(); + + let expectedCount = 0; + for (let [prop, expected] of Object.entries(attributes)) { + expectedCount++; + + let matcher: Matcher = isMatcher(expected) ? expected : equalsAttr(expected); + expectedAttrs[prop] = matcher; + + QUnit.assert.pushResult({ + result: matcher.match(element && element.getAttribute(prop)), + actual: matcher.fail(element && element.getAttribute(prop)), + expected: matcher.fail(element && element.getAttribute(prop)), + message: `Expected ${description}'s ${prop} attribute ${matcher.expected()}`, + }); + } + + let actualAttributes = dict(); + if (element) { + for (const attribute of Array.from(element.attributes)) { + actualAttributes[attribute.name] = attribute.value; + } + } + + if (!(element instanceof HTMLElement)) { + QUnit.assert.pushResult({ + result: element instanceof HTMLElement, + actual: null, + expected: null, + message: 'Element must be an HTML Element, not an SVG Element', + }); + } else { + QUnit.assert.pushResult({ + result: element.attributes.length === expectedCount, + actual: element.attributes.length, + expected: expectedCount, + message: `Expected ${expectedCount} attributes; got ${element.outerHTML}`, + }); + + if (content !== null) { + QUnit.assert.pushResult({ + result: element.innerHTML === content, + actual: element.innerHTML, + expected: content, + message: `${description} had '${content}' as its content`, + }); + } + } +} + +// eslint-disable-next-line @typescript-eslint/no-deprecated +interface CompatibleTagNameMap extends ElementTagNameMap { + foreignobject: SVGForeignObjectElement; +} + +export function assertIsElement(node: SimpleNode | null): node is SimpleElement { + let nodeType = node === null ? null : node.nodeType; + QUnit.assert.pushResult({ + result: nodeType === 1, + expected: 1, + actual: nodeType, + message: 'expected node to be an element', + }); + return nodeType === 1; +} + +export function assertNodeTagName< + T extends keyof CompatibleTagNameMap, + U extends CompatibleTagNameMap[T], +>(node: SimpleNode | null, tagName: T): node is SimpleNode & U { + if (assertIsElement(node)) { + const lowerTagName = node.tagName.toLowerCase(); + const nodeTagName = node.tagName; + + QUnit.assert.pushResult({ + result: lowerTagName === tagName || nodeTagName === tagName, + expected: tagName, + actual: nodeTagName, + message: `expected tagName to be ${tagName} but was ${nodeTagName}`, + }); + return nodeTagName === tagName || lowerTagName === tagName; + } + return false; +} + +export function equalsAttr(expected: any): Matcher { + return { + '3d4ef194-13be-4ccf-8dc7-862eea02c93e': true, + match(actual: any) { + return expected === actual; + }, + + expected() { + return `to equal ${expected}`; + }, + + fail(actual: any) { + return `${actual} did not equal ${expected}`; + }, + }; +} + +export function assertEmberishElement( + element: SimpleElement, + tagName: string, + attrs: object, + contents: string +): void; +export function assertEmberishElement(element: SimpleElement, tagName: string, attrs: object): void; +export function assertEmberishElement( + element: SimpleElement, + tagName: string, + contents: string +): void; +export function assertEmberishElement(element: SimpleElement, tagName: string): void; +export function assertEmberishElement(...args: any[]): void { + let [element, tagName, attrs, contents] = processAssertComponentArgs(args); + + let fullAttrs = assign({ class: classes('ember-view'), id: regex(/^ember\d*$/u) }, attrs); + + equalsElement(element, tagName, fullAttrs, contents); +} + +export function assertSerializedInElement(result: string, expected: string, message?: string) { + let matched = / + + `; + this.renderServerSide(template, { data: '{ "status": "ok" }', otherData: '{ "code": 200 }' }); + let b = blockStack(); + this.assertHTML(strip` + ${b(0)} + + + + ${b(0)} + `); + this.renderClientSide(template, { data: '{ "status": "ok" }', otherData: '{ "code": 200 }' }); + this.assertRehydrationStats({ nodesRemoved: 0 }); + this.assertHTML(strip` + + + + `); + this.assertStableRerender(); + } + + @test + 'style tag'() { + let template = ''; + this.renderServerSide(template, { selector: 'div' }); + let b = blockStack(); + this.assertHTML(strip` + ${b(0)} + + ${b(0)} + `); + this.renderClientSide(template, { selector: 'div' }); + this.assertRehydrationStats({ nodesRemoved: 0 }); + this.assertHTML(strip` + + `); + this.assertStableRerender(); + } + + @test + 'clearing bounds'() { + let template = strip` + {{#if this.isTrue}} + {{#each this.items key="id" as |item i|}} +

{{item}}-{{i}}

+ {{/each}} + {{/if}} + `; + this.renderServerSide(template, { isTrue: true, items: [1, 2] }); + let b = blockStack(); + this.assertHTML(strip` + ${b(0)} + ${b(1)} + ${b(2)} + ${b(3)} + ${b(4)} +

+ ${b(5)} + 1 + ${b(5)} + - + ${b(5)} + 0 + ${b(5)} +

+ ${b(4)} + ${b(4)} +

+ ${b(5)} + 2 + ${b(5)} + - + ${b(5)} + 1 + ${b(5)} +

+ ${b(4)} + ${b(3)} + ${b(2)} + ${b(1)} + ${b(0)} + `); + + this.renderClientSide(template, { isTrue: false, items: [3, 4] }); + // Removes the block and each

+ this.assertRehydrationStats({ nodesRemoved: 2 }); + this.assertHTML(''); + this.assertStableRerender(); + } + + @test + 'top-level clearing bounds'() { + let template = strip` + + {{#if this.isTrue}} + + {{#each this.items key="id" as |item i|}} +

{{item}}-{{i}}

+ {{/each}} + + {{/if}} + + {{#if this.isFalse}} + {{#each this.items key="id" as |item i|}} +

{{item}}-{{i}}

+ {{/each}} + {{/if}} + `; + this.renderServerSide(template, { isTrue: true, items: [1, 2], isFalse: false }); + let b = blockStack(); + this.assertHTML(strip` + ${b(0)} + + ${b(1)} + + ${b(2)} + ${b(3)} + ${b(4)} +

+ ${b(5)} + 1 + ${b(5)} + - + ${b(5)} + 0 + ${b(5)} +

+ ${b(4)} + ${b(4)} +

+ ${b(5)} + 2 + ${b(5)} + - + ${b(5)} + 1 + ${b(5)} +

+ ${b(4)} + ${b(3)} + ${b(2)} +
+ ${b(1)} +
+ ${b(1)} + + ${b(1)} + ${b(0)} + `); + + this.renderClientSide(template, { isTrue: false, items: [3, 4], isFalse: true }); + // Clears block markers for both and removes `inside` + this.assertRehydrationStats({ nodesRemoved: 1 }); + this.assertHTML('

3-0

4-1

'); + this.assertStableRerender(); + } + + @test + '#each rehydration'() { + let template = "{{#each this.items key='id' as |item|}}

{{item}}

{{/each}}"; + this.renderServerSide(template, { items: [1, 2, 3] }); + let b = blockStack(); + this.assertHTML(strip` + ${b(0)} + ${b(1)} + ${b(2)} + ${b(3)} +

+ ${b(4)} + 1 + ${b(4)} +

+ ${b(3)} + ${b(3)} +

+ ${b(4)} + 2 + ${b(4)} +

+ ${b(3)} + ${b(3)} +

+ ${b(4)} + 3 + ${b(4)} +

+ ${b(3)} + ${b(2)} + ${b(1)} + ${b(0)} + `); + + this.renderClientSide(template, { items: [1, 2, 4] }); + this.assertRehydrationStats({ nodesRemoved: 0 }); + this.assertHTML(strip` +

1

+

2

+

4

+ `); + this.assertStableRerender(); + } +} + +class RehydratingComponents extends AbstractRehydrationTests { + _buildComponent(blueprint: ComponentBlueprint, properties: Dict = {}) { + let template = this.buildComponent(blueprint); + if (this.testType === 'Dynamic' && properties['componentName'] === undefined) { + properties['componentName'] = blueprint.name || GLIMMER_TEST_COMPONENT; + } + return template; + } + + assertServerComponent(html: string, attrs: object = {}) { + // the Dynamic test type is using {{component 'foo'}} style invocation + // and therefore an extra node is added delineating the block start + let elementIndex = this.testType === 'Dynamic' ? 3 : 2; + let element = assertingElement(this.element.childNodes[elementIndex]); + + if (this.testType === 'Glimmer') { + assertElementShape(element, 'div', attrs, html); + } else { + assertEmberishElement(element, 'div', attrs, html); + } + } + + override renderServerSide(blueprint: ComponentBlueprint, properties: Dict = {}) { + let template = this._buildComponent(blueprint, properties); + super.renderServerSide(template, properties); + } + + override renderClientSide(blueprint: ComponentBlueprint, properties: Dict = {}) { + let template = this._buildComponent(blueprint, properties); + super.renderClientSide(template, properties); + } + + @test + 'Component invocations'() { + let layout = 'Hello {{@name}}'; + let args = { name: 'this.name' }; + this.renderServerSide( + { + layout, + args, + }, + { name: 'Filewatcher' } + ); + let b = blockStack(); + let id = this.testType === 'Dynamic' ? 3 : 2; + this.assertServerComponent(`Hello ${b(id)}Filewatcher${b(id)}`); + + this.renderClientSide( + { + layout, + args, + }, + { name: 'Filewatcher' } + ); + this.assertRehydrationStats({ nodesRemoved: 0 }); + this.assertComponent('Hello Filewatcher'); + this.assertStableRerender(); + } + + @test + 'Mismatched Component invocations'() { + let layout = 'Hello {{@name}}'; + let args = { name: 'this.name' }; + this.renderServerSide( + { + layout, + args, + }, + { name: 'Filewatcher' } + ); + let b = blockStack(); + let id = this.testType === 'Dynamic' ? 3 : 2; + this.assertServerComponent(`Hello ${b(id)}Filewatcher${b(id)}`); + + this.renderClientSide( + { + layout, + args, + }, + { name: 'Chad' } + ); + this.assertRehydrationStats({ nodesRemoved: 0 }); + this.assertComponent('Hello Chad'); + this.assertStableRerender(); + } + + @test + '

invoking a block which emits a

'() { + let componentToRender = { + layout: '

hello {{#if @show}}

world!
{{/if}}

', + args: { show: 'this.show' }, + }; + + this.renderServerSide(componentToRender, { show: true }); + let b = blockStack(); + + let id = this.testType === 'Dynamic' ? 3 : 2; + + this.assertServerComponent(`

hello ${b(id)}

world!
${b(id)}

`); + + this.renderClientSide(componentToRender, { show: true }); + this.assertComponent('

hello

world!

'); + + this.assertRehydrationStats({ nodesRemoved: 2 }); + this.assertStableNodes(); + } + + @test + 'Component invocations with block params'() { + let layout = 'Hello {{yield @name}}'; + let template = '{{this.name}}'; + let blockParams = ['name']; + let args = { name: 'this.name' }; + + this.renderServerSide( + { + layout, + template, + args, + blockParams, + }, + { name: 'Filewatcher' } + ); + let b = blockStack(); + let id = this.testType === 'Dynamic' ? 3 : 2; + this.assertServerComponent(`Hello ${b(id)}Filewatcher${b(id)}`); + + this.renderClientSide( + { + layout, + template, + args, + blockParams, + }, + { name: 'Filewatcher' } + ); + this.assertRehydrationStats({ nodesRemoved: 0 }); + this.assertComponent('Hello Filewatcher'); + this.assertStableRerender(); + } + + @test + 'Mismatched Component invocations with block params'() { + let layout = 'Hello {{yield @name}}'; + let template = '{{this.name}}'; + let blockParams = ['name']; + let args = { name: 'this.name' }; + + this.renderServerSide( + { + layout, + template, + args, + blockParams, + }, + { name: 'Filewatcher' } + ); + let b = blockStack(); + let id = this.testType === 'Dynamic' ? 3 : 2; + this.assertServerComponent(`Hello ${b(id)}Filewatcher${b(id)}`); + + this.renderClientSide( + { + layout, + template, + args, + blockParams, + }, + { name: 'Chad' } + ); + this.assertRehydrationStats({ nodesRemoved: 0 }); + this.assertComponent('Hello Chad'); + this.assertStableRerender(); + } + + @test + 'Component invocations with template'() { + let layout = 'Hello {{yield}}'; + let template = 'Filewatcher'; + this.renderServerSide( + { + layout, + template, + }, + { name: 'Filewatcher' } + ); + this.assertServerComponent(`Hello Filewatcher`); + + this.renderClientSide({ + layout, + template, + }); + this.assertRehydrationStats({ nodesRemoved: 0 }); + this.assertComponent('Hello Filewatcher'); + this.assertStableRerender(); + } + + @test + 'Mismatched Component invocations with template'() { + let layout = 'Hello {{yield}}'; + let template = 'Filewatcher'; + this.renderServerSide({ + layout, + template, + }); + this.assertServerComponent(`Hello Filewatcher`); + + this.renderClientSide({ + layout, + template: 'Chad', + }); + this.assertRehydrationStats({ nodesRemoved: 0 }); + this.assertComponent('Hello Chad'); + this.assertStableRerender(); + } + + @test + 'Component invocations with empty args'() { + let layout = 'Hello {{@foo}}'; + this.renderServerSide({ + layout, + }); + let b = blockStack(); + let id = this.testType === 'Dynamic' ? 3 : 2; + this.assertServerComponent(`Hello ${b(id)}${b(id)}`); + + this.renderClientSide({ + layout, + }); + this.assertRehydrationStats({ nodesRemoved: 0 }); + this.assertComponent('Hello '); + this.assertStableRerender(); + } + + @test + 'Multiple invocations'() { + let name; + let template; + + let emberishComponent = false; + if (this.testType === 'Dynamic' || this.testType === 'Curly') { + name = 'foo-bar'; + template = '{{#foo-bar}}World{{/foo-bar}}'; + emberishComponent = true; + } else { + name = 'FooBar'; + template = 'World'; + } + + this.registerComponent(this.testType, name, 'Hello {{yield}}'); + let layout = `{{yield}}`; + this.renderServerSide({ + layout, + template, + }); + let b = blockStack(); + if (emberishComponent) { + let wrapper = assertingElement(firstElementChild(this.element)); + + // injects wrapper elements + this.assert.strictEqual(wrapper.getAttribute('class'), 'ember-view'); + this.assert.strictEqual(toTextContent(wrapper), 'Hello World'); + // this.assert.strictEqual(this.element.textContent, 'Hello World'); + } else { + this.assertServerComponent(`${b(2)}Hello World${b(2)}`); + } + + this.renderClientSide({ + layout, + template, + }); + this.assertRehydrationStats({ nodesRemoved: 0 }); + this.assert.strictEqual(toTextContent(this.element), 'Hello World'); + this.assertStableRerender(); + } + + @test + 'Mismatched Multiple invocations'() { + let name; + let template; + + let emberishComponent = false; + if (this.testType === 'Dynamic' || this.testType === 'Curly') { + name = 'foo-bar'; + template = '{{#foo-bar}}World{{/foo-bar}}'; + emberishComponent = true; + } else { + name = 'FooBar'; + template = 'World'; + } + + this.registerComponent(this.testType, name, 'Hello {{yield}}'); + let layout = `{{yield}}`; + this.renderServerSide({ + layout, + template, + }); + let b = blockStack(); + if (emberishComponent) { + let wrapper = assertingElement(firstElementChild(this.element)); + // injects wrapper elements + this.assert.strictEqual(wrapper.getAttribute('class'), 'ember-view'); + this.assert.strictEqual(toTextContent(this.element), 'Hello World'); + } else { + this.assertServerComponent(`${b(2)}Hello World${b(2)}`); + } + + if (this.testType === 'Dynamic' || this.testType === 'Curly') { + template = '{{#foo-bar}}Chad{{/foo-bar}}'; + } else { + template = 'Chad'; + } + + this.renderClientSide({ + layout, + template, + }); + this.assertRehydrationStats({ nodesRemoved: 0 }); + this.assert.strictEqual(toTextContent(this.element), 'Hello Chad'); + this.assertStableRerender(); + } + + @test + 'interacting with builtins'() { + let layout = strip` +
    + {{#each @items key="id" as |item i|}} + {{#if item.show}} +
  • {{item.name}}
  • + {{else}} + {{yield i}} + {{/if}} + {{/each}} +
`; + this.registerHelper( + 'even', + (params: ReadonlyArray) => (params[0] as number) % 2 === 0 + ); + let template = '{{#if (even i)}}{{/if}}'; + this.registerComponent('TemplateOnly', 'FooBar', '
  • {{@count}}
  • '); + let blockParams = ['i']; + let args = { items: 'this.items' }; + + this.renderServerSide( + { + layout, + template, + blockParams, + args, + }, + { + items: [ + { show: true, name: 'Industry' }, + { show: false, name: 'Standard' }, + { show: false, name: 'Components' }, + ], + } + ); + + let b = blockStack(); + + let id = (num: number) => (this.testType === 'Dynamic' ? num + 1 : num); + + this.assertServerComponent(strip` +
      + ${b(id(2))} + ${b(id(3))} + ${b(id(4))} + ${b(id(5))} +
    • + ${b(id(6))} + Industry + ${b(id(6))} +
    • + ${b(id(5))} + ${b(id(4))} + ${b(id(4))} + ${b(id(5))} + ${b(id(6))} + + ${b(id(6))} + ${b(id(5))} + ${b(id(4))} + ${b(id(4))} + ${b(id(5))} + ${b(id(6))} + ${b(id(7))} +
    • + ${b(id(8))} + 2 + ${b(id(8))} +
    • + ${b(id(7))} + ${b(id(6))} + ${b(id(5))} + ${b(id(4))} + ${b(id(3))} + ${b(id(2))} +
    + `); + + this.renderClientSide( + { + layout, + template, + blockParams, + args, + }, + { + items: [ + { show: true, name: 'Industry' }, + { show: false, name: 'Standard' }, + { show: false, name: 'Components' }, + ], + } + ); + + this.assertComponent('
    • Industry
    • 2
    '); + this.assertRehydrationStats({ nodesRemoved: 0 }); + this.assertStableRerender(); + } + + @test + 'mismatched interacting with builtins'() { + let layout = strip` +
      + {{#each @items key="id" as |item i|}} + {{#if item.show}} +
    • {{item.name}}
    • + {{else}} + {{yield i}} + {{/if}} + {{/each}} +
    `; + this.registerHelper( + 'even', + (params: ReadonlyArray) => (params[0] as number) % 2 === 0 + ); + let template = '{{#if (even i)}}{{/if}}'; + this.registerComponent('TemplateOnly', 'FooBar', '
  • {{@count}}
  • '); + let blockParams = ['i']; + let args = { items: 'this.items' }; + + this.renderServerSide( + { + layout, + template, + blockParams, + args, + }, + { + items: [ + { show: true, name: 'Industry' }, + { show: false, name: 'Standard' }, + { show: false, name: 'Components' }, + ], + } + ); + + let b = blockStack(); + + let id = (num: number) => (this.testType === 'Dynamic' ? num + 1 : num); + + this.assertServerComponent(strip` +
      + ${b(id(2))} + ${b(id(3))} + ${b(id(4))} + ${b(id(5))} +
    • + ${b(id(6))} + Industry + ${b(id(6))} +
    • + ${b(id(5))} + ${b(id(4))} + ${b(id(4))} + ${b(id(5))} + ${b(id(6))} + + ${b(id(6))} + ${b(id(5))} + ${b(id(4))} + ${b(id(4))} + ${b(id(5))} + ${b(id(6))} + ${b(id(7))} +
    • + ${b(id(8))} + 2 + ${b(id(8))} +
    • + ${b(id(7))} + ${b(id(6))} + ${b(id(5))} + ${b(id(4))} + ${b(id(3))} + ${b(id(2))} +
    + `); + + this.renderClientSide( + { + layout, + template, + blockParams, + args, + }, + { + items: [ + { show: true, name: 'Industry' }, + { show: true, name: 'Standard' }, + { show: true, name: 'Components' }, + ], + } + ); + + this.assertRehydrationStats({ nodesRemoved: 1 }); + this.assertComponent('
    • Industry
    • Standard
    • Components
    '); + } + + @test + 'mismatched blocks interacting with builtins'() { + let layout = strip` +
      + {{#each @items key="id" as |item i|}} + {{#if item.show}} +
    • {{item.name}}
    • + {{else}} + {{yield i}} + {{/if}} + {{/each}} +
    +
      + {{#each @things key="id" as |item i|}} + {{#if item.show}} +
    • {{item.name}}
    • + {{else}} + {{yield i}} + {{/if}} + {{/each}} +
    + `; + this.registerHelper( + 'even', + (params: ReadonlyArray) => (params[0] as number) % 2 === 0 + ); + let template = '{{#if (even i)}}{{/if}}'; + this.registerComponent('TemplateOnly', 'FooBar', '
  • {{@count}}
  • '); + let blockParams = ['i']; + let args = { items: 'this.items', things: 'this.things' }; + + this.renderServerSide( + { + layout, + template, + blockParams, + args, + }, + { + items: [ + { show: true, name: 'Industry' }, + { show: false, name: 'Standard' }, + { show: false, name: 'Components' }, + ], + } + ); + + let b = blockStack(); + + let id = (num: number) => (this.testType === 'Dynamic' ? num + 1 : num); + + this.assertServerComponent(strip` +
      + ${b(id(2))} + ${b(id(3))} + ${b(id(4))} + ${b(id(5))} +
    • + ${b(id(6))} + Industry + ${b(id(6))} +
    • + ${b(id(5))} + ${b(id(4))} + ${b(id(4))} + ${b(id(5))} + ${b(id(6))} + + ${b(id(6))} + ${b(id(5))} + ${b(id(4))} + ${b(id(4))} + ${b(id(5))} + ${b(id(6))} + ${b(id(7))} +
    • + ${b(id(8))} + 2 + ${b(id(8))} +
    • + ${b(id(7))} + ${b(id(6))} + ${b(id(5))} + ${b(id(4))} + ${b(id(3))} + ${b(id(2))} +
    +
      + ${b(id(2))} + + ${b(id(2))} +
    + `); + + this.renderClientSide( + { + layout, + template, + blockParams, + args, + }, + { + things: [ + { show: true, name: 'Industry' }, + { show: true, name: 'Standard' }, + { show: false, name: 'Components' }, + ], + } + ); + + this.assertRehydrationStats({ nodesRemoved: 2 }); + this.assertComponent('
    • Industry
    • Standard
    • 2
    '); + } +} + +suite(Rehydration, RehydrationDelegate); +jitSuite(RenderTests); +componentSuite(RehydratingComponents, RehydrationDelegate); diff --git a/packages/@glimmer-workspace/integration-tests/test/input-range-test.ts b/packages/@glimmer-workspace/integration-tests/test/input-range-test.ts new file mode 100644 index 00000000000..0e8c3bf767f --- /dev/null +++ b/packages/@glimmer-workspace/integration-tests/test/input-range-test.ts @@ -0,0 +1,160 @@ +import type { EmberishCurlyComponentFactory } from '@glimmer-workspace/integration-tests'; +import { EmberishCurlyComponent, jitSuite, test } from '@glimmer-workspace/integration-tests'; + +import { AttributesTests } from './attributes-test'; + +abstract class RangeTests extends AttributesTests { + min = -5; + max = 50; + + abstract renderRange(value: number): void; + abstract assertRangeValue(value: number): void; + setup() {} + + @test + 'value over default max but below set max is kept'() { + this.setup(); + this.renderRange(25); + this.assertRangeValue(25); + } + + @test + 'value below default min but above set min is kept'() { + this.setup(); + this.renderRange(-2); + this.assertRangeValue(-2); + } + + @test + 'in the valid default range is kept'() { + this.setup(); + this.renderRange(5); + this.assertRangeValue(5); + } + + @test + 'value above max is reset to max'() { + this.setup(); + this.renderRange(55); + this.assertRangeValue(50); + } + + @test + 'value below min is reset to min'() { + this.setup(); + this.renderRange(-10); + this.assertRangeValue(-5); + } +} + +abstract class TemplateRangeTests extends RangeTests { + abstract readonly attrs: string; + + renderRange(value: number) { + this.render(``, { + max: this.max, + min: this.min, + value, + }); + } + + assertRangeValue(value: number) { + this.assert.strictEqual(this.readDOMAttr('value'), value.toString()); + } +} + +jitSuite( + class extends TemplateRangeTests { + static override suiteName = `[emberjs/ember.js#15675] Template `; + + attrs = 'type="range" value={{this.value}} min={{this.min}} max={{this.max}}'; + } +); + +// Ember Components attributeBindings + +class EmberInputRangeComponent extends EmberishCurlyComponent { + override tagName = 'input'; + type = 'range'; +} + +jitSuite( + class EmberComponentRangeTests extends RangeTests { + static override suiteName = `Components - [emberjs/ember.js#15675] - type value min max`; + + component(): EmberishCurlyComponentFactory { + return class extends EmberInputRangeComponent { + override attributeBindings = ['type', 'value', 'min', 'max']; + } as any; + } + + renderRange(value: number): void { + this.registerComponent('Curly', 'range-input', '', this.component()); + this.render(`{{range-input max=this.max min=this.min value=this.value}}`, { + max: this.max, + min: this.min, + value, + }); + } + + assertRangeValue(value: number): void { + let attr = (this.element.firstChild as any)['value']; + this.assert.strictEqual(attr, value.toString()); + } + } +); + +jitSuite( + class BasicComponentImplicitAttributesRangeTest extends RangeTests { + static override suiteName = `integration - GlimmerComponent - [emberjs/ember.js#15675] ...attributes `; + attrs = 'type="range" value="%x" min="-5" max="50"'; + + renderRange(value: number): void { + this.registerComponent('Glimmer', 'RangeInput', ''); + this.render(``); + } + + assertRangeValue(value: number): void { + let attr = this.readDOMAttr('value'); + this.assert.strictEqual(attr, value.toString()); + } + } +); + +jitSuite( + class BasicComponentSplattributesLastRangeTest extends RangeTests { + static override suiteName = `integration - GlimmerComponent - [emberjs/ember.js#15675] ...attributes last `; + attrs = 'type="range" value="%x" min="-5" max="50"'; + + renderRange(value: number): void { + this.registerComponent('Glimmer', 'RangeInput', ''); + this.render(``); + } + + assertRangeValue(value: number): void { + let attr = this.readDOMAttr('value'); + this.assert.strictEqual(attr, value.toString()); + } + } +); + +jitSuite( + class BasicComponentSplattributesFirstRangeTest extends RangeTests { + static override suiteName = `integration - GlimmerComponent - [emberjs/ember.js#15675] ...attributes first `; + attrs = 'type="text" min="-5" max="50"'; + + renderRange(value: number): void { + this.registerComponent( + 'Glimmer', + 'RangeInput', + `` + ); + this.render(``); + } + + assertRangeValue(value: number): void { + let attr = this.readDOMAttr('value'); + this.assert.strictEqual(attr, value.toString()); + } + } +); diff --git a/packages/@glimmer-workspace/integration-tests/test/invalid-html-test.ts b/packages/@glimmer-workspace/integration-tests/test/invalid-html-test.ts new file mode 100644 index 00000000000..4962c3cba66 --- /dev/null +++ b/packages/@glimmer-workspace/integration-tests/test/invalid-html-test.ts @@ -0,0 +1,254 @@ +import { + jitSuite, + preprocess, + RenderTest, + syntaxErrorFor, + test, +} from '@glimmer-workspace/integration-tests'; + +class CompileErrorTests extends RenderTest { + static suiteName = 'compile errors'; + + @test + 'A helpful error message is provided for unclosed elements'() { + this.assert.throws( + () => { + preprocess('\n
    \n\n\n', { + meta: { moduleName: 'test-module' }, + }); + }, + syntaxErrorFor( + 'Unclosed element `div`', + '
    ', + 'test-module', + 2, + 0 + ) + ); + + this.assert.throws( + () => { + preprocess('\n
    \n\n', { + meta: { moduleName: 'test-module' }, + }); + }, + syntaxErrorFor('Unclosed element `span`', '', 'test-module', 3, 0) + ); + } + + @test + 'A helpful error message is provided for unmatched end tags'() { + this.assert.throws( + () => { + preprocess('

    ', { meta: { moduleName: 'test-module' } }); + }, + syntaxErrorFor('Closing tag

    without an open tag', '

    ', 'test-module', 1, 0) + ); + + this.assert.throws( + () => { + preprocess('{{ foo }} \n {{ bar }}\n
    ', { + meta: { moduleName: 'test-module' }, + }); + }, + syntaxErrorFor('Closing tag
    without an open tag', '
    ', 'test-module', 3, 0) + ); + } + + @test + 'A helpful error message is provided for end tags for void elements'() { + this.assert.throws( + () => { + preprocess('', { meta: { moduleName: 'test-module' } }); + }, + syntaxErrorFor( + ' elements do not need end tags. You should remove it', + '', + 'test-module', + 1, + 7 + ) + ); + + this.assert.throws( + () => { + preprocess('
    \n \n
    ', { meta: { moduleName: 'test-module' } }); + }, + syntaxErrorFor( + ' elements do not need end tags. You should remove it', + '', + 'test-module', + 2, + 9 + ) + ); + + this.assert.throws( + () => { + preprocess('\n\n
    ', { meta: { moduleName: 'test-module' } }); + }, + syntaxErrorFor( + '
    elements do not need end tags. You should remove it', + '
    ', + 'test-module', + 3, + 0 + ) + ); + } + + @test + 'A helpful error message is provided for end tags with attributes'() { + this.assert.throws( + () => { + preprocess('
    \nSomething\n\n
    ', { meta: { moduleName: 'test-module' } }); + }, + syntaxErrorFor( + 'Invalid end tag: closing tag must not have attributes', + '
    { + preprocess('
    \n

    \nSomething\n\n

    ', { meta: { moduleName: 'test-module' } }); + }, + syntaxErrorFor( + 'Closing tag did not match last open tag

    (on line 2)', + '', + 'test-module', + 5, + 0 + ) + ); + } + + @test + 'error line numbers include comment lines'() { + this.assert.throws( + () => { + preprocess('

    \n

    \n{{! some comment}}\n\n

    ', { + meta: { moduleName: 'test-module' }, + }); + }, + syntaxErrorFor( + 'Closing tag did not match last open tag

    (on line 2)', + '', + 'test-module', + 5, + 0 + ) + ); + } + + @test + 'error line numbers include mustache only lines'() { + this.assert.throws( + () => { + preprocess('

    \n

    \n{{someProp}}\n\n

    ', { meta: { moduleName: 'test-module' } }); + }, + syntaxErrorFor( + 'Closing tag did not match last open tag

    (on line 2)', + '', + 'test-module', + 5, + 0 + ) + ); + } + + @test + 'error line numbers include block lines'() { + this.assert.throws( + () => { + preprocess('

    \n

    \n{{#some-comment}}\n{{/some-comment}}\n

    ', { + meta: { moduleName: 'test-module' }, + }); + }, + syntaxErrorFor( + 'Closing tag did not match last open tag

    (on line 2)', + '', + 'test-module', + 5, + 0 + ) + ); + } + + @test + 'error line numbers include whitespace control mustaches'() { + this.assert.throws( + () => { + preprocess('

    \n

    \n{{someProp~}}\n\n

    {{some-comment}}', { + meta: { moduleName: 'test-module' }, + }); + }, + syntaxErrorFor( + 'Closing tag did not match last open tag

    (on line 2)', + '', + 'test-module', + 5, + 0 + ) + ); + } + + @test + 'error line numbers include multiple mustache lines'() { + this.assert.throws( + () => { + preprocess('

    \n

    \n{{some-comment}}

    {{some-comment}}', { + meta: { moduleName: 'test-module' }, + }); + }, + syntaxErrorFor( + 'Closing tag did not match last open tag

    (on line 2)', + '', + 'test-module', + 3, + 16 + ) + ); + } + + @test + 'Unquoted attribute with expression throws an exception'() { + this.assert.throws( + () => preprocess('', { meta: { moduleName: 'test-module' } }), + expectedError('class=foo{{bar}}', 1, 5) + ); + this.assert.throws( + () => preprocess('', { meta: { moduleName: 'test-module' } }), + expectedError('class={{foo}}{{bar}}', 1, 5) + ); + this.assert.throws( + () => preprocess('', { meta: { moduleName: 'test-module' } }), + expectedError('class={{foo}}bar', 2, 0) + ); + this.assert.throws( + () => + preprocess('

    ', { + meta: { moduleName: 'test-module' }, + }), + expectedError('class\n=\n{{foo}}&bar', 2, 0) + ); + + function expectedError(code: string, line: number, column: number) { + return syntaxErrorFor( + `An unquoted attribute value must be a string or a mustache, preceded by whitespace or a '=' character, and followed by whitespace, a '>' character, or '/>'`, + code, + 'test-module', + line, + column + ); + } + } +} + +jitSuite(CompileErrorTests); diff --git a/packages/@glimmer-workspace/integration-tests/test/invocation-generation-test.ts b/packages/@glimmer-workspace/integration-tests/test/invocation-generation-test.ts new file mode 100644 index 00000000000..5218e4e1a07 --- /dev/null +++ b/packages/@glimmer-workspace/integration-tests/test/invocation-generation-test.ts @@ -0,0 +1,365 @@ +import { JitRenderDelegate, RenderTest } from '@glimmer-workspace/integration-tests'; + +import { module } from './support'; + +let renderTests: RenderTest; +module( + 'Render Tests: buildComponent', + { + beforeEach() { + renderTests = new RenderTest(new JitRenderDelegate()); + }, + }, + ({ test }) => { + test('Can build basic glimmer invocation', (assert) => { + renderTests['testType'] = 'Glimmer'; + let invocation = renderTests.buildComponent({ + layout: 'Hello', + }); + + assert.strictEqual(invocation, ''); + }); + + test('Can build glimmer invocation with template', (assert) => { + renderTests['testType'] = 'Glimmer'; + let invocation = renderTests.buildComponent({ + layout: 'Hello {{yield}}', + template: 'World', + }); + + assert.strictEqual(invocation, 'World'); + }); + + test('Can build glimmer invocation with args', (assert) => { + renderTests['testType'] = 'Glimmer'; + let invocation = renderTests.buildComponent({ + layout: 'Hello {{yield}}', + template: 'World', + args: { foo: 'bar', baz: 1, bar: null, literal: "'literal'" }, + }); + + assert.strictEqual( + invocation, + "World" + ); + }); + + test('Can build glimmer invocation with attributes', (assert) => { + renderTests['testType'] = 'Glimmer'; + let invocation = renderTests.buildComponent({ + layout: 'Hello {{yield}}', + template: 'World', + args: { foo: 'bar', baz: 1, bar: null }, + attributes: { 'data-foo': 'bar', id: 'wat' }, + }); + + assert.strictEqual( + invocation, + 'World' + ); + }); + + test('Can build glimmer invocation with custom tag name', (assert) => { + renderTests['testType'] = 'Glimmer'; + let invocation = renderTests.buildComponent({ + name: 'LolWat', + layout: 'Hello {{yield}}', + template: 'World', + args: { foo: 'bar', baz: 1, bar: null }, + attributes: { 'data-foo': '"bar"', id: '"wat"' }, + }); + + assert.strictEqual( + invocation, + `World` + ); + }); + + test('Can build glimmer invocation with block params', (assert) => { + renderTests['testType'] = 'Glimmer'; + let invocation = renderTests.buildComponent({ + name: 'Lol', + layout: 'Hello {{yield}}', + template: 'World', + args: { foo: 'bar', baz: 1, bar: null }, + attributes: { 'data-foo': '"bar"', id: '"wat"' }, + blockParams: ['a b c'], + }); + + assert.strictEqual( + invocation, + `World` + ); + }); + + test('Can build basic curly invocation', (assert) => { + renderTests['testType'] = 'Curly'; + let invocation = renderTests.buildComponent({ + layout: 'Hello', + }); + + assert.strictEqual(invocation, '{{test-component}}'); + }); + + test('Can build curly invocation with template', (assert) => { + renderTests['testType'] = 'Curly'; + let invocation = renderTests.buildComponent({ + layout: 'Hello {{yield}}', + template: 'World', + }); + + assert.strictEqual(invocation, '{{#test-component}}World{{/test-component}}'); + }); + + test('Can build curly invocation with args', (assert) => { + renderTests['testType'] = 'Curly'; + let invocation = renderTests.buildComponent({ + layout: 'Hello {{yield}}', + template: 'World', + args: { foo: 'bar', baz: 1, bar: null }, + }); + + assert.strictEqual( + invocation, + '{{#test-component foo=bar baz=1 bar=null}}World{{/test-component}}' + ); + }); + + test('Can build curly invocation with attributes throws', (assert) => { + renderTests['testType'] = 'Curly'; + + assert.throws(() => { + renderTests.buildComponent({ + layout: 'Hello {{yield}}', + template: 'World', + args: { foo: 'bar', baz: 1, bar: null }, + attributes: { 'data-foo': '"bar"', id: '"wat"' }, + }); + }, /Cannot pass attributes to curly components/u); + }); + + test("Can build curly invocation with 'attributes' in args", (assert) => { + renderTests['testType'] = 'Curly'; + let invocation = renderTests.buildComponent({ + layout: 'Hello {{yield}}', + template: 'World', + args: { foo: 'bar', baz: 1, bar: null, 'data-foo': '"bar"', id: '"wat"' }, + }); + + assert.strictEqual( + invocation, + `{{#test-component foo=bar baz=1 bar=null data-foo="bar" id="wat"}}World{{/test-component}}` + ); + }); + + test('Can build curly invocation with custom tag name', (assert) => { + renderTests['testType'] = 'Curly'; + let invocation = renderTests.buildComponent({ + name: 'lol-wat', + layout: 'Hello {{yield}}', + template: 'World', + args: { foo: 'bar', baz: 1, bar: null, 'data-foo': '"bar"', id: '"wat"' }, + }); + + assert.strictEqual( + invocation, + `{{#lol-wat foo=bar baz=1 bar=null data-foo="bar" id="wat"}}World{{/lol-wat}}` + ); + }); + + test('Can build curly invocation with block params', (assert) => { + renderTests['testType'] = 'Curly'; + let invocation = renderTests.buildComponent({ + name: 'lol-wat', + layout: 'Hello {{yield}}', + template: 'World', + args: { foo: 'bar', baz: 1, bar: null, 'data-foo': '"bar"', id: '"wat"' }, + blockParams: ['a b c'], + }); + + assert.strictEqual( + invocation, + `{{#lol-wat foo=bar baz=1 bar=null data-foo="bar" id="wat" as |a b c|}}World{{/lol-wat}}` + ); + }); + + test('Can build curly invocation with else', (assert) => { + renderTests['testType'] = 'Curly'; + let invocation = renderTests.buildComponent({ + name: 'lol-wat', + layout: 'Hello {{yield}}', + template: 'World', + args: { foo: 'bar', baz: 1, bar: null, 'data-foo': '"bar"', id: '"wat"' }, + blockParams: ['a b c'], + else: 'ELSE', + }); + + assert.strictEqual( + invocation, + `{{#lol-wat foo=bar baz=1 bar=null data-foo="bar" id="wat" as |a b c|}}World{{else}}ELSE{{/lol-wat}}` + ); + }); + + test('Can build basic dynamic invocation', (assert) => { + renderTests['testType'] = 'Dynamic'; + let invocation = renderTests.buildComponent({ + layout: 'Hello', + }); + + assert.strictEqual(invocation, '{{component this.componentName}}'); + }); + + test('Can build dynamic invocation with template', (assert) => { + renderTests['testType'] = 'Dynamic'; + let invocation = renderTests.buildComponent({ + layout: 'Hello {{yield}}', + template: 'World', + }); + + assert.strictEqual(invocation, '{{#component this.componentName}}World{{/component}}'); + }); + + test('Can build dynamic invocation with args', (assert) => { + renderTests['testType'] = 'Dynamic'; + let invocation = renderTests.buildComponent({ + layout: 'Hello {{yield}}', + template: 'World', + args: { foo: 'bar', baz: 1, bar: null }, + }); + + assert.strictEqual( + invocation, + '{{#component this.componentName foo=bar baz=1 bar=null}}World{{/component}}' + ); + }); + + test('Can build dynamic invocation with custom tag name', (assert) => { + renderTests['testType'] = 'Dynamic'; + let invocation = renderTests.buildComponent({ + name: 'lol-wat', + layout: 'Hello {{yield}}', + template: 'World', + args: { foo: 'bar', baz: 1, bar: null, 'data-foo': '"bar"', id: '"wat"' }, + }); + + assert.strictEqual( + invocation, + `{{#component this.componentName foo=bar baz=1 bar=null data-foo="bar" id="wat"}}World{{/component}}` + ); + }); + + test('Can build dynamic invocation with block params', (assert) => { + renderTests['testType'] = 'Dynamic'; + let invocation = renderTests.buildComponent({ + name: 'lol-wat', + layout: 'Hello {{yield}}', + template: 'World', + args: { foo: 'bar', baz: 1, bar: null, 'data-foo': '"bar"', id: '"wat"' }, + blockParams: ['a b c'], + }); + + assert.strictEqual( + invocation, + `{{#component this.componentName foo=bar baz=1 bar=null data-foo="bar" id="wat" as |a b c|}}World{{/component}}` + ); + }); + + test('Can build dynamic invocation with else', (assert) => { + renderTests['testType'] = 'Dynamic'; + let invocation = renderTests.buildComponent({ + name: 'lol-wat', + layout: 'Hello {{yield}}', + template: 'World', + args: { foo: 'bar', baz: 1, bar: null, 'data-foo': '"bar"', id: '"wat"' }, + blockParams: ['a b c'], + else: 'ELSE', + }); + + assert.strictEqual( + invocation, + `{{#component this.componentName foo=bar baz=1 bar=null data-foo="bar" id="wat" as |a b c|}}World{{else}}ELSE{{/component}}` + ); + }); + + test('Can build basic component invocation', (assert) => { + renderTests['testType'] = 'TemplateOnly'; + let invocation = renderTests.buildComponent({ + layout: 'Hello', + }); + + assert.strictEqual(invocation, ''); + }); + + test('Can build basic component invocation with template', (assert) => { + renderTests['testType'] = 'TemplateOnly'; + let invocation = renderTests.buildComponent({ + layout: 'Hello {{yield}}', + template: 'World', + }); + + assert.strictEqual(invocation, 'World'); + }); + + test('Can build basic component invocation with args', (assert) => { + renderTests['testType'] = 'TemplateOnly'; + let invocation = renderTests.buildComponent({ + layout: 'Hello {{yield}}', + template: 'World', + args: { foo: 'bar', baz: 1, bar: null }, + }); + + assert.strictEqual( + invocation, + 'World' + ); + }); + + test('Can build basic component invocation with attributes', (assert) => { + renderTests['testType'] = 'TemplateOnly'; + let invocation = renderTests.buildComponent({ + layout: 'Hello {{yield}}', + template: 'World', + args: { foo: 'bar', baz: 1, bar: null }, + attributes: { 'data-foo': 'bar', id: 'wat' }, + }); + + assert.strictEqual( + invocation, + 'World' + ); + }); + + test('Can build basic component invocation with custom tag name', (assert) => { + renderTests['testType'] = 'TemplateOnly'; + let invocation = renderTests.buildComponent({ + name: 'Lol', + layout: 'Hello {{yield}}', + template: 'World', + args: { foo: 'bar', baz: 1, bar: null }, + attributes: { 'data-foo': '"bar"', id: '"wat"' }, + }); + + assert.strictEqual( + invocation, + `World` + ); + }); + + test('Can build basic component invocation with block params', (assert) => { + renderTests['testType'] = 'TemplateOnly'; + let invocation = renderTests.buildComponent({ + name: 'Lol', + layout: 'Hello {{yield}}', + template: 'World', + args: { foo: 'bar', baz: 1, bar: null }, + attributes: { 'data-foo': '"bar"', id: '"wat"' }, + blockParams: ['a b c'], + }); + + assert.strictEqual( + invocation, + `World` + ); + }); + } +); diff --git a/packages/@glimmer-workspace/integration-tests/test/jit-suites-test.ts b/packages/@glimmer-workspace/integration-tests/test/jit-suites-test.ts new file mode 100644 index 00000000000..69afb5a202c --- /dev/null +++ b/packages/@glimmer-workspace/integration-tests/test/jit-suites-test.ts @@ -0,0 +1,30 @@ +import { + DebuggerSuite, + EachSuite, + EmberishComponentTests, + GlimmerishComponents, + HasBlockParamsHelperSuite, + HasBlockSuite, + InElementSuite, + jitComponentSuite, + jitSuite, + ScopeSuite, + ShadowingSuite, + TemplateOnlyComponents, + WithDynamicVarsSuite, + YieldSuite, +} from '@glimmer-workspace/integration-tests'; + +jitComponentSuite(DebuggerSuite); +jitSuite(EachSuite); +jitSuite(InElementSuite); + +jitComponentSuite(GlimmerishComponents); +jitComponentSuite(TemplateOnlyComponents); +jitComponentSuite(EmberishComponentTests); +jitComponentSuite(HasBlockSuite); +jitComponentSuite(HasBlockParamsHelperSuite); +jitComponentSuite(ScopeSuite); +jitComponentSuite(ShadowingSuite); +jitComponentSuite(WithDynamicVarsSuite); +jitComponentSuite(YieldSuite); diff --git a/packages/@glimmer-workspace/integration-tests/test/keywords/each-test.ts b/packages/@glimmer-workspace/integration-tests/test/keywords/each-test.ts new file mode 100644 index 00000000000..030879baa8c --- /dev/null +++ b/packages/@glimmer-workspace/integration-tests/test/keywords/each-test.ts @@ -0,0 +1,35 @@ +import { + defineComponent, + jitSuite, + RenderTest, + test, + tracked, +} from '@glimmer-workspace/integration-tests'; + +class Each extends RenderTest { + static suiteName = '{{#each}} keyword'; + + @test({ skip: true }) + 'each with undefined item https://github.com/emberjs/ember.js/issues/20786'() { + class State { + @tracked data = [undefined]; + } + + let state = new State(); + + const Bar = defineComponent( + { state }, + `{{#each state.data key='anything' as |datum|}} + {{datum}} + {{/each}}` + .replaceAll(/^\s|\s+$|\s+(?=\s)/gu, '') + .replaceAll(/\n/gu, '') + ); + + this.renderComponent(Bar); + + this.assertHTML(' '); + } +} + +jitSuite(Each); diff --git a/packages/@glimmer-workspace/integration-tests/test/keywords/log-test.ts b/packages/@glimmer-workspace/integration-tests/test/keywords/log-test.ts new file mode 100644 index 00000000000..089b162df65 --- /dev/null +++ b/packages/@glimmer-workspace/integration-tests/test/keywords/log-test.ts @@ -0,0 +1,86 @@ +import { LOCAL_TRACE_LOGGING } from '@glimmer/local-debug-flags'; +import { jitSuite, RenderTest, test } from '@glimmer-workspace/integration-tests'; + +class LogTest extends RenderTest { + static suiteName = '{{log}} keyword'; + + originalLog?: () => void; + logCalls: unknown[] = []; + + beforeEach() { + /* eslint-disable no-console */ + this.originalLog = console.log; + console.log = (...args: unknown[]) => { + this.logCalls.push(...args); + /* eslint-enable no-console */ + }; + } + + afterEach() { + /* eslint-disable no-console */ + console.log = this.originalLog!; + /* eslint-enable no-console */ + } + + assertLog(values: unknown[]) { + this.assertHTML(''); + this.assert.strictEqual(this.logCalls.length, values.length); + + for (let i = 0, len = values.length; i < len; i++) { + this.assert.strictEqual(this.logCalls[i], values[i]); + } + } + + @test + 'correctly logs primitives'() { + this.render(`{{log "one" 1 true}}`); + + this.assertLog(['one', 1, true]); + } + + @test + 'correctly logs a property'() { + this.render(`{{log this.value}}`, { + value: 'one', + }); + + this.assertLog(['one']); + } + + @test + 'correctly logs multiple arguments'() { + this.render(`{{log "my variable:" this.value}}`, { + value: 'one', + }); + + this.assertLog(['my variable:', 'one']); + } + + @test + 'correctly logs `this`'() { + this.render(`{{log this}}`); + + this.assertLog([this.context]); + } + + @test + 'correctly logs as a subexpression'() { + this.render(`{{if (log "one" 1 true) "Hello!"}}`); + + this.assertLog(['one', 1, true]); + } + + @test + 'correctly logs when values update'() { + this.render(`{{log this.foo}}`, { foo: 123 }); + + this.rerender({ foo: 456 }); + this.rerender({ foo: true }); + + this.assertLog([123, 456, true]); + } +} + +if (!LOCAL_TRACE_LOGGING) { + jitSuite(LogTest); +} diff --git a/packages/@glimmer-workspace/integration-tests/test/lexical-scope-test.ts b/packages/@glimmer-workspace/integration-tests/test/lexical-scope-test.ts new file mode 100644 index 00000000000..92b0ae94eeb --- /dev/null +++ b/packages/@glimmer-workspace/integration-tests/test/lexical-scope-test.ts @@ -0,0 +1,17 @@ +import { defineComponent, jitSuite, RenderTest, test } from '@glimmer-workspace/integration-tests'; + +class LexicalScopeTest extends RenderTest { + static suiteName = 'loose mode: lexical scope'; + + @test + 'Can use a component in scope'() { + const Foo = defineComponent({}, 'Hello, world!', { strictMode: false }); + const Bar = defineComponent({ Foo }, '', { strictMode: false }); + + this.renderComponent(Bar); + this.assertHTML('Hello, world!'); + this.assertStableRerender(); + } +} + +jitSuite(LexicalScopeTest); diff --git a/packages/@glimmer-workspace/integration-tests/test/managers/helper-manager-test.ts b/packages/@glimmer-workspace/integration-tests/test/managers/helper-manager-test.ts new file mode 100644 index 00000000000..839d7295024 --- /dev/null +++ b/packages/@glimmer-workspace/integration-tests/test/managers/helper-manager-test.ts @@ -0,0 +1,504 @@ +/* eslint-disable @typescript-eslint/no-extraneous-class */ +import type { Arguments, Owner } from '@glimmer/interfaces'; +import { helperCapabilities, setHelperManager, setModifierManager } from '@glimmer/manager'; +import { + defineComponent, + GlimmerishComponent, + jitSuite, + RenderTest, + test, + TestHelper, + TestHelperManager, + tracked, + trackedObj, +} from '@glimmer-workspace/integration-tests'; +import { consume } from '@glimmer-workspace/test-utils'; +import { DEBUG } from '@glimmer/env'; + +class HelperManagerTest extends RenderTest { + static suiteName = 'Helper Managers'; + + @test 'it works'() { + class Hello extends TestHelper { + value() { + return 'hello'; + } + } + + const Main = defineComponent({ hello: Hello }, '{{hello}}'); + + this.renderComponent(Main); + + this.assertHTML('hello'); + + this.rerender(); + + this.assertHTML('hello'); + } + + @test + '(Default Helper Manager) plain functions work as helpers'(assert: Assert) { + let count = 0; + + const hello = () => { + count++; + return 'plain function'; + }; + + const Main = defineComponent({ hello }, '{{hello}}'); + + this.renderComponent(Main); + + assert.strictEqual(count, 1, 'rendered once'); + this.assertHTML('plain function'); + + this.rerender(); + + assert.strictEqual(count, 1, 'rendered once'); + this.assertHTML('plain function'); + } + + @test + '(Default Helper Manager) plain functions passed as component arguments work as helpers'( + assert: Assert + ) { + let count = 0; + + const hello = () => { + count++; + return 'plain function'; + }; + + const Main = defineComponent({}, '{{(@hello)}}'); + + this.renderComponent(Main, { + hello, + }); + + assert.strictEqual(count, 1, 'rendered once'); + this.assertHTML('plain function'); + + this.rerender(); + + assert.strictEqual(count, 1, 'rendered once'); + this.assertHTML('plain function'); + } + + @test + '(Default Helper Manager) plain functions stored on component class properties work as helpers'( + assert: Assert + ) { + let count = 0; + + const Main = defineComponent({}, '{{(this.hello)}}', { + definition: class extends GlimmerishComponent { + hello = () => { + count++; + return 'plain function'; + }; + }, + }); + + this.renderComponent(Main); + + assert.strictEqual(count, 1, 'rendered once'); + this.assertHTML('plain function'); + + this.rerender(); + + assert.strictEqual(count, 1, 'rendered once'); + this.assertHTML('plain function'); + } + + @test + '(Default Helper Manager) plain functions track positional args'(assert: Assert) { + let count = 0; + + let obj = (x: string) => { + count++; + return x; + }; + let args = trackedObj({ value: 'hello', unused: 'unused' }); + + this.renderComponent(defineComponent({ obj }, '{{obj @value @unused}}'), args); + + assert.strictEqual(count, 1, 'rendered once'); + this.assertHTML('hello'); + + args['value'] = 'there'; + this.rerender(); + + assert.strictEqual(count, 2, 'rendered twice'); + this.assertHTML('there'); + + args['unused'] = 'unused2'; + this.rerender(); + + assert.strictEqual(count, 3, 'rendered thrice'); + this.assertHTML('there'); + } + + @test + '(Default Helper Manager) plain functions entangle with any tracked data'(assert: Assert) { + let count = 0; + let trackedState = trackedObj({ value: 'hello' }); + + let obj = () => { + count++; + return trackedState['value']; + }; + + this.renderComponent(defineComponent({ obj }, '{{obj}}')); + + assert.strictEqual(count, 1, 'rendered once'); + this.assertHTML('hello'); + + trackedState['value'] = 'there'; + this.rerender(); + this.assertHTML('there'); + assert.strictEqual(count, 2, 'rendered twice'); + } + + @test + '(Default Helper Manager) plain functions do not track unused named args'(assert: Assert) { + let count = 0; + + let obj = (x: string, _options: Record) => { + count++; + return x; + }; + let args = trackedObj({ value: 'hello', unused: 'unused' }); + + this.renderComponent(defineComponent({ obj }, '{{obj @value namedOpt=@unused}}'), args); + assert.strictEqual(count, 1, 'rendered once'); + this.assertHTML('hello'); + + args['unused'] = 'unused2'; + this.rerender(); + + assert.strictEqual(count, 1, 'rendered once'); + this.assertHTML('hello'); + } + + @test + '(Default Helper Manager) plain functions tracked used named args'(assert: Assert) { + let count = 0; + + let obj = (_x: string, options: Record) => { + count++; + return options['namedOpt']; + }; + + let args = trackedObj({ value: 'hello', used: 'used' }); + + this.renderComponent(defineComponent({ obj }, '{{obj @value namedOpt=@used}}'), args); + assert.strictEqual(count, 1, 'rendered once'); + this.assertHTML('used'); + + args['used'] = 'there'; + this.rerender(); + + assert.strictEqual(count, 2, 'rendered twice'); + this.assertHTML('there'); + } + + @test + '(Default Helper Manager) plain function helpers can have default values (missing data)'( + assert: Assert + ) { + let count = 0; + let obj = (x = 'default value') => { + count++; + return x; + }; + + let args = trackedObj({}); + + this.renderComponent(defineComponent({ obj }, 'result: {{obj}}'), args); + this.assertHTML('result: default value'); + assert.strictEqual(count, 1, 'rendered once'); + } + + @test + '(Default Helper Manager) plain function helpers can have overwritten default values'( + assert: Assert + ) { + let count = 0; + let obj = (x = 'default value') => { + count++; + return x; + }; + + let args = trackedObj({ value: undefined }); + + this.renderComponent(defineComponent({ obj }, 'result: {{obj @value}}'), args); + this.assertHTML('result: default value'); + assert.strictEqual(count, 1, 'rendered once'); + + args['value'] = 'value'; + this.rerender(); + + this.assertHTML('result: value'); + assert.strictEqual(count, 2, 'rendered twice'); + } + + @test 'tracks changes to named arguments'(assert: Assert) { + let count = 0; + + class Hello extends TestHelper { + value() { + count++; + return this.args.named['foo']; + } + } + + let args = trackedObj({ foo: 123 }); + + this.renderComponent(defineComponent({ hello: Hello }, '{{hello foo=@foo}}'), args); + + assert.strictEqual(count, 1, 'rendered once'); + this.assertHTML('123'); + + this.rerender(); + + assert.strictEqual(count, 1, 'rendered once'); + this.assertHTML('123'); + + args['foo'] = 456; + this.rerender(); + + assert.strictEqual(count, 2, 'rendered twice'); + this.assertHTML('456'); + } + + @test 'tracks changes to positional arguments'(assert: Assert) { + let count = 0; + + class Hello extends TestHelper { + value() { + count++; + return this.args.positional[0]; + } + } + + let args = trackedObj({ foo: 123 }); + + this.renderComponent(defineComponent({ hello: Hello }, '{{hello @foo}}'), args); + + assert.strictEqual(count, 1, 'rendered once'); + this.assertHTML('123'); + + this.rerender(); + + assert.strictEqual(count, 1, 'rendered once'); + this.assertHTML('123'); + + args['foo'] = 456; + this.rerender(); + + assert.strictEqual(count, 2, 'rendered twice'); + this.assertHTML('456'); + } + + @test 'tracks changes to tracked properties'(assert: Assert) { + let count = 0; + let instance: Hello; + + const setInstance = (i: Hello) => (instance = i); + + class Hello extends TestHelper { + @tracked foo = 123; + + constructor(owner: Owner, args: Arguments) { + super(owner, args); + setInstance(this); + } + + value() { + count++; + return this.foo; + } + } + this.renderComponent(defineComponent({ hello: Hello }, '{{hello}}')); + + assert.strictEqual(count, 1, 'rendered once'); + this.assertHTML('123'); + + this.rerender(); + + assert.strictEqual(count, 1, 'rendered once'); + this.assertHTML('123'); + + instance!.foo = 456; + this.rerender(); + + assert.strictEqual(count, 2, 'rendered twice'); + this.assertHTML('456'); + } + + @test 'destroyable is associated correctly'(assert: Assert) { + class Hello extends TestHelper { + value() { + return 'hello'; + } + + override willDestroy() { + assert.ok(true, 'destructor called'); + } + } + + this.renderComponent(defineComponent({ hello: Hello }, '{{hello}}')); + + this.assertHTML('hello'); + } + + @test({ skip: !DEBUG }) 'debug name is used for backtracking message'(assert: Assert) { + class Hello extends TestHelper { + @tracked foo = 123; + + value() { + consume(this.foo); + this.foo = 456; + } + } + + assert.throws(() => { + this.renderComponent(defineComponent({ hello: Hello }, '{{hello}}')); + }, /You attempted to update `foo` on/u); + } + + @test({ skip: !DEBUG }) 'asserts against using both `hasValue` and `hasScheduledEffect`'( + assert: Assert + ) { + assert.throws(() => { + helperCapabilities('3.23', { + hasValue: true, + hasScheduledEffect: true, + }); + }, /You must pass either the `hasValue` OR the `hasScheduledEffect` capability when defining a helper manager. Passing neither, or both, is not permitted./u); + } + + @test({ skip: !DEBUG }) 'asserts requiring either `hasValue` or `hasScheduledEffect`'( + assert: Assert + ) { + assert.throws(() => { + helperCapabilities('3.23', {}); + }, /You must pass either the `hasValue` OR the `hasScheduledEffect` capability when defining a helper manager. Passing neither, or both, is not permitted./u); + } + + @test({ skip: !DEBUG }) 'asserts against using `hasScheduledEffect`'(assert: Assert) { + assert.throws(() => { + helperCapabilities('3.23', { + hasScheduledEffect: true, + }); + }, /The `hasScheduledEffect` capability has not yet been implemented for helper managers. Please pass `hasValue` instead/u); + } + + @test({ skip: !DEBUG }) 'asserts against using incorrect version for capabilities'( + assert: Assert + ) { + assert.throws(() => { + helperCapabilities('aoeu' as any, { + hasScheduledEffect: true, + }); + }, /Invalid helper manager compatibility specified/u); + } + + @test 'helper manager and modifier manager can be associated with the same value'() { + abstract class TestModifierHelper extends TestHelper {} + + setModifierManager(() => ({}) as any, TestHelper); + + class Hello extends TestModifierHelper { + value() { + return 'hello'; + } + } + + this.renderComponent(defineComponent({ hello: Hello }, '{{hello}}')); + + this.assertHTML('hello'); + + this.rerender(); + + this.assertHTML('hello'); + } + + @test({ skip: !DEBUG }) 'capabilities helper function must be used to generate capabilities'( + assert: Assert + ) { + class OverrideTestHelperManager extends TestHelperManager { + override capabilities = { + hasValue: true, + hasDestroyable: true, + hasScheduledEffect: false, + } as any; + } + + class TestHelper {} + + setHelperManager((owner) => new OverrideTestHelperManager(owner), TestHelper); + + class Hello extends TestHelper { + value() { + return 'hello'; + } + } + + assert.throws(() => { + this.renderComponent(defineComponent({ hello: Hello }, '{{hello}}')); + }, /Custom helper managers must have a `capabilities` property that is the result of calling the `capabilities\('3.23'\)` \(imported via `import \{ capabilities \} from '@ember\/helper';`\). /u); + } + + @test({ skip: !DEBUG }) + 'custom helpers gives helpful assertion when reading then mutating a tracked value within constructor'( + assert: Assert + ) { + class Hello extends TestHelper { + @tracked foo = 123; + + constructor(owner: Owner, args: Arguments) { + super(owner, args); + + // first read the tracked property + + consume(this.foo); + + // then attempt to update the tracked property + this.foo = 456; + } + + value() { + return this.foo; + } + } + + assert.throws(() => { + this.renderComponent(defineComponent({ hello: Hello }, '{{hello}}')); + }, /You attempted to update `foo` on /u); + } + + @test({ skip: !DEBUG }) + 'custom helpers gives helpful assertion when reading then mutating a tracked value within value'( + assert: Assert + ) { + class Hello extends TestHelper { + @tracked foo = 123; + + value() { + // first read the tracked property + + consume(this.foo); + + // then attempt to update the tracked property + this.foo = 456; + } + } + + assert.throws(() => { + this.renderComponent(defineComponent({ hello: Hello }, '{{hello}}')); + }, /You attempted to update `foo` on /u); + } +} + +jitSuite(HelperManagerTest); diff --git a/packages/@glimmer-workspace/integration-tests/test/managers/modifier-manager-test.ts b/packages/@glimmer-workspace/integration-tests/test/managers/modifier-manager-test.ts new file mode 100644 index 00000000000..dd93d05ed05 --- /dev/null +++ b/packages/@glimmer-workspace/integration-tests/test/managers/modifier-manager-test.ts @@ -0,0 +1,427 @@ +import type { Arguments, ModifierManager, Owner } from '@glimmer/interfaces'; +import { modifierCapabilities, setModifierManager } from '@glimmer/manager'; +import { getOwner, setOwner } from '@glimmer/owner'; +import { + defineComponent, + jitSuite, + RenderTest, + test, + tracked, + trackedObj, +} from '@glimmer-workspace/integration-tests'; +import { consume } from '@glimmer-workspace/test-utils'; +import { DEBUG } from '@glimmer/env'; + +abstract class CustomModifier { + static create( + this: This, + args: Arguments + ): InstanceType { + return new this(getOwner(args)!, args) as InstanceType; + } + + constructor( + owner: Owner, + public args: Arguments + ) { + setOwner(this, owner); + } + + declare element: Element; + + didInsertElement(): void {} + didUpdate(): void {} + willDestroyElement(): void {} +} + +abstract class ModifierManagerTest extends RenderTest { + abstract CustomModifierManager: { new (owner: Owner): ModifierManager }; + + defineModifier(Klass: T): T { + return setModifierManager((owner) => { + return new this.CustomModifierManager(owner); + }, Klass); + } + + @test 'can register a custom element modifier and render it'() { + let foo = this.defineModifier( + class extends CustomModifier { + override didInsertElement() {} + override didUpdate() {} + override willDestroyElement() {} + } + ); + + const Main = defineComponent({ foo }, '

    hello world

    '); + + this.renderComponent(Main); + + this.assertHTML(`

    hello world

    `); + } + + @test 'custom lifecycle hooks'(assert: Assert) { + let foo = this.defineModifier( + class extends CustomModifier { + override didInsertElement() { + assert.step('Called didInsertElement'); + assert.strictEqual(this.args.positional[0], true, 'gets initial args'); + } + override didUpdate() { + assert.step('Called didUpdate'); + assert.strictEqual(this.args.positional[0], 'true', 'gets updated args'); + } + override willDestroyElement() { + assert.step('Called willDestroyElement'); + } + } + ); + + const Main = defineComponent( + { foo }, + '{{#if @truthy}}

    hello world

    {{/if}}' + ); + let args = trackedObj({ truthy: true }); + + this.renderComponent(Main, args); + + this.assertHTML(`

    hello world

    `); + assert.verifySteps(['Called didInsertElement']); + + args['truthy'] = 'true'; + this.rerender(); + assert.verifySteps(['Called didUpdate']); + + args['truthy'] = false; + this.rerender(); + assert.verifySteps(['Called willDestroyElement']); + + args['truthy'] = true; + this.rerender(); + assert.verifySteps(['Called didInsertElement']); + } + + @test 'associates manager even through an inheritance structure'(assert: Assert) { + let Foo = this.defineModifier( + class extends CustomModifier { + override didInsertElement() { + assert.step('Foo didInsertElement'); + assert.strictEqual(this.args.positional[0], true, 'gets initial args'); + } + } + ); + + class Bar extends Foo { + override didInsertElement() { + super.didInsertElement(); + assert.step('Bar didInsertElement'); + assert.strictEqual(this.args.positional[0], true, 'gets initial args'); + } + } + + const Main = defineComponent({ bar: Bar }, '

    hello world

    '); + + this.renderComponent(Main, { truthy: true }); + this.assertHTML(`

    hello world

    `); + assert.verifySteps(['Foo didInsertElement', 'Bar didInsertElement']); + } + + @test 'can give consistent access to underlying DOM element'(assert: Assert) { + assert.expect(6); + + let foo = this.defineModifier( + class extends CustomModifier { + savedElement?: Element; + + override didInsertElement() { + // consume first positional argument (ensures updates run) + + // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- intentionally consume + this.args.positional[0]; + + assert.strictEqual(this.element.tagName, 'H1'); + this.savedElement = this.element; + } + + override didUpdate() { + assert.strictEqual(this.element, this.savedElement); + } + + override willDestroyElement() { + assert.strictEqual(this.element, this.savedElement); + } + } + ); + + const Main = defineComponent({ foo }, '

    hello world

    '); + let args = trackedObj({ truthy: true }); + + this.renderComponent(Main, args); + this.assertHTML(`

    hello world

    `); + + args['truthy'] = 'true'; + this.rerender(); + } + + @test 'lifecycle hooks are autotracked by default'(assert: Assert) { + class TrackedClass { + @tracked count = 0; + } + + let trackedOne = new TrackedClass(); + let trackedTwo = new TrackedClass(); + + let insertCount = 0; + let updateCount = 0; + + let foo = this.defineModifier( + class extends CustomModifier { + override didInsertElement() { + // track the count of the first item + + consume(trackedOne.count); + insertCount++; + } + + override didUpdate() { + // track the count of the second item + + consume(trackedTwo.count); + updateCount++; + } + } + ); + + let Main = defineComponent({ foo }, '

    hello world

    '); + + this.renderComponent(Main); + this.assertHTML(`

    hello world

    `); + + assert.strictEqual(insertCount, 1); + assert.strictEqual(updateCount, 0); + + trackedTwo.count++; + this.rerender(); + assert.strictEqual(updateCount, 0); + + trackedOne.count++; + this.rerender(); + assert.strictEqual(updateCount, 1); + + trackedOne.count++; + this.rerender(); + assert.strictEqual(updateCount, 1); + + trackedTwo.count++; + this.rerender(); + assert.strictEqual(updateCount, 2); + } + + @test({ skip: !DEBUG }) + 'provides a helpful deprecation when mutating a tracked value that was consumed already within constructor'( + assert: Assert + ) { + class Foo extends CustomModifier { + @tracked foo = 123; + + constructor(owner: Owner, args: Arguments) { + super(owner, args); + + // first read the tracked property + + consume(this.foo); + + // then attempt to update the tracked property + this.foo = 456; + } + + override didInsertElement() {} + override didUpdate() {} + override willDestroyElement() {} + } + + let foo = this.defineModifier(Foo); + + let Main = defineComponent({ foo }, '

    hello world

    '); + + assert.throws(() => { + this.renderComponent(Main); + }, /You attempted to update `foo` on `.*`, but it had already been used previously in the same computation/u); + } + + @test + 'does not eagerly access arguments during destruction'(assert: Assert) { + class Foo extends CustomModifier {} + + let foo = this.defineModifier(Foo); + + let Main = defineComponent( + { foo }, + '{{#if @state.show}}

    hello world

    {{/if}}' + ); + + let barCount = 0; + let bazCount = 0; + + class State { + @tracked show = true; + + get bar() { + if (!this.show) { + barCount++; + } + + return; + } + + get baz() { + if (!this.show) { + bazCount++; + } + + return; + } + } + + let state = new State(); + + this.renderComponent(Main, { state }); + + state.show = false; + + this.rerender(); + + assert.strictEqual(barCount, 0, 'bar was not accessed during detruction'); + assert.strictEqual(bazCount, 0, 'baz was not accessed during detruction'); + } +} + +class ModifierManagerTest322 extends ModifierManagerTest { + static suiteName = 'Basic Custom Modifier Manager: 3.22'; + + CustomModifierManager = class CustomModifierManager implements ModifierManager { + capabilities = modifierCapabilities('3.22'); + + constructor(public owner: Owner) {} + + createModifier( + Modifier: { new (owner: Owner, args: Arguments): CustomModifier }, + args: Arguments + ) { + return new Modifier(this.owner, args); + } + + installModifier(instance: CustomModifier, element: Element, args: Arguments) { + instance.element = element; + instance.args = args; + instance.didInsertElement(); + } + + updateModifier(instance: CustomModifier, args: Arguments) { + instance.args = args; + instance.didUpdate(); + } + + destroyModifier(instance: CustomModifier) { + instance.willDestroyElement(); + } + }; + + @test 'modifers only track positional arguments they consume'(assert: Assert) { + let insertCount = 0; + let updateCount = 0; + + let foo = this.defineModifier( + class extends CustomModifier { + override didInsertElement() { + insertCount++; + + // consume the second positional + + consume(this.args.positional[1]); + } + + override didUpdate() { + updateCount++; + + // consume the second positional + + consume(this.args.positional[1]); + } + } + ); + + let Main = defineComponent( + { foo }, + '

    hello world

    ' + ); + + let args = trackedObj({ + positionOne: 'first!!!', + positionTwo: 'second :(', + bar: 'bar', + qux: 'quz', + }); + + this.renderComponent(Main, args); + + this.assertHTML(`

    hello world

    `); + + assert.strictEqual(insertCount, 1); + assert.strictEqual(updateCount, 0); + + args['positionOne'] = 'no first?'; + this.rerender(); + assert.strictEqual(updateCount, 0); + + args['positionTwo'] = 'YASSSSSSS!!!'; + this.rerender(); + assert.strictEqual(updateCount, 1); + } + + @test 'modifers only track named arguments they consume'(assert: Assert) { + let insertCount = 0; + let updateCount = 0; + + let foo = this.defineModifier( + class extends CustomModifier { + override didInsertElement() { + insertCount++; + + // consume the named arg + consume(this.args.named['qux']); + } + + override didUpdate() { + updateCount++; + } + } + ); + + let Main = defineComponent( + { foo }, + '

    hello world

    ' + ); + + let args = trackedObj({ + bar: 'bar', + qux: 'quz', + }); + + this.renderComponent(Main, args); + + this.assertHTML(`

    hello world

    `); + + assert.strictEqual(insertCount, 1); + assert.strictEqual(updateCount, 0); + + args['bar'] = 'other bar'; + this.rerender(); + assert.strictEqual(updateCount, 0); + + args['qux'] = 'quuuuxxxxxx'; + this.rerender(); + assert.strictEqual(updateCount, 1); + } +} + +jitSuite(ModifierManagerTest322); diff --git a/packages/@glimmer-workspace/integration-tests/test/math-test.ts b/packages/@glimmer-workspace/integration-tests/test/math-test.ts new file mode 100644 index 00000000000..193b234770a --- /dev/null +++ b/packages/@glimmer-workspace/integration-tests/test/math-test.ts @@ -0,0 +1,81 @@ +import type { Namespace } from '@glimmer/interfaces'; +import { NS_HTML, NS_MATHML, NS_SVG } from '@glimmer/constants'; +import { defineComponent, jitSuite, RenderTest, test } from '@glimmer-workspace/integration-tests'; + +class MathElementTest extends RenderTest { + static suiteName = ''; + query(selector: string) { + let el = (s: string) => (this.element as unknown as HTMLElement).querySelector(s); + return el(selector) as Element; + } + assertNamespace(selector: string, ns: Namespace) { + this.assert.strictEqual( + this.query(selector).namespaceURI, + ns, + `Expecting "${ns}" namespace for tag "${selector}"` + ); + } + + @test + ' element can render'() { + const Bar = defineComponent({}, 'x'); + + this.renderComponent(Bar); + + this.assertNamespace('math', NS_MATHML); + this.assertNamespace('msqrt', NS_MATHML); + this.assertNamespace('mi', NS_MATHML); + } + + @test + 'HTML and element can render together'() { + const Bar = defineComponent( + {}, + '

    Math inside:

    x
    ' + ); + + this.renderComponent(Bar); + + this.assertNamespace('div', NS_HTML); + this.assertNamespace('p', NS_HTML); + this.assertNamespace('math', NS_MATHML); + this.assertNamespace('msqrt', NS_MATHML); + this.assertNamespace('mi', NS_MATHML); + } + + @test + 'SVG and element can render together'() { + const Bar = defineComponent( + {}, + 'x' + ); + + this.renderComponent(Bar); + + this.assertNamespace('svg', NS_SVG); + this.assertNamespace('circle', NS_SVG); + this.assertNamespace('math', NS_MATHML); + this.assertNamespace('msqrt', NS_MATHML); + this.assertNamespace('mi', NS_MATHML); + } + + @test + 'HTML, SVG, and element can render together'() { + const Bar = defineComponent( + {}, + '

    Math and SVG inside:

    x
    ' + ); + + this.renderComponent(Bar); + + this.assertNamespace('div', NS_HTML); + this.assertNamespace('p', NS_HTML); + this.assertNamespace('svg', NS_SVG); + this.assertNamespace('circle', NS_SVG); + this.assertNamespace('math', NS_MATHML); + this.assertNamespace('msqrt', NS_MATHML); + this.assertNamespace('mi', NS_MATHML); + } +} + +jitSuite(MathElementTest); diff --git a/packages/@glimmer-workspace/integration-tests/test/modifiers-test.ts b/packages/@glimmer-workspace/integration-tests/test/modifiers-test.ts new file mode 100644 index 00000000000..bf56f06c9b0 --- /dev/null +++ b/packages/@glimmer-workspace/integration-tests/test/modifiers-test.ts @@ -0,0 +1,514 @@ +import type { Dict, Nullable, SimpleElement } from '@glimmer/interfaces'; +import type { Count } from '@glimmer-workspace/integration-tests'; +import { jitSuite, RenderTest, test } from '@glimmer-workspace/integration-tests'; + +class BaseModifier { + element?: SimpleElement; + didInsertElement(_params: unknown[], _hash: Dict): void {} + willDestroyElement(): void {} + didUpdate(_params: unknown[], _hash: Dict): void {} +} + +abstract class AbstractInsertable extends BaseModifier { + abstract override didInsertElement(_params: unknown[], _hash: Dict): void; +} + +abstract class AbstractDestroyable extends BaseModifier { + abstract override willDestroyElement(): void; +} + +class ModifierTests extends RenderTest { + static suiteName = 'modifiers'; + + @test + 'Element modifier with hooks'(assert: Assert, count: Count) { + this.registerModifier( + 'foo', + class { + element?: SimpleElement; + didInsertElement() { + count.expect('didInsertElement'); + assert.ok(this.element, 'didInsertElement'); + assert.strictEqual(this.element?.getAttribute('data-ok'), 'true', 'didInsertElement'); + } + + didUpdate() { + count.expect('didUpdate'); + assert.ok(true, 'didUpdate'); + } + + willDestroyElement() { + count.expect('willDestroyElement'); + assert.ok(true, 'willDestroyElement'); + } + } + ); + + this.render('{{#if this.ok}}
    {{/if}}', { + bar: 'bar', + ok: true, + }); + + this.rerender({ bar: 'foo' }); + this.rerender({ ok: false }); + } + + @test + 'didUpdate is not called when params are constants'(assert: Assert, count: Count) { + this.registerModifier( + 'foo', + class { + element?: SimpleElement; + didInsertElement() { + count.expect('didInsertElement'); + assert.ok(true); + } + didUpdate() { + count.expect('didUpdate', 0); + assert.ok(false); + } + willDestroyElement() { + count.expect('willDestroyElement'); + } + } + ); + + this.render('{{#if this.ok}}
    {{/if}}{{this.ok}}', { + ok: true, + data: 'ok', + }); + this.rerender({ data: 'yup' }); + this.rerender({ ok: false }); + } + + @test + 'modifiers on components are forwarded to a single element receiving the splattributes'( + assert: Assert + ) { + let modifierParams: Nullable = null; + let modifierNamedArgs: Nullable = null; + let modifiedElement: SimpleElement | undefined; + class Bar extends AbstractInsertable { + didInsertElement(params: unknown[], namedArgs: Dict) { + modifierParams = params; + modifierNamedArgs = namedArgs; + modifiedElement = this.element; + } + } + this.registerComponent('Glimmer', 'TheFoo', '
    Foo
    '); + this.registerModifier('bar', Bar); + this.render(''); + assert.deepEqual(modifierParams, ['something']); + assert.deepEqual(modifierNamedArgs, { foo: 'else' }); + assert.strictEqual( + modifiedElement && modifiedElement.getAttribute('id'), + 'inner-div', + 'Modifier is called on the element receiving the splattributes' + ); + } + + @test + 'modifiers on components are forwarded to all the elements receiving the splattributes'( + assert: Assert + ) { + let elementIds: Nullable[] = []; + class Bar extends AbstractInsertable { + didInsertElement(params: unknown[], namedArgs: Dict) { + assert.deepEqual(params, ['something']); + assert.deepEqual(namedArgs, { foo: 'else' }); + if (this.element) { + elementIds.push(this.element.getAttribute('id')); + } + } + } + this.registerComponent( + 'Glimmer', + 'TheFoo', + '
    Foo
    Bar
    ' + ); + this.registerModifier('bar', Bar); + this.render(''); + assert.deepEqual( + elementIds, + ['inner-one', 'inner-two'], + 'The modifier has been instantiated twice, once for each element with splattributes' + ); + } + + @test + 'modifiers on components accept bound arguments and track changes on them'(assert: Assert) { + let modifierParams: Nullable = null; + let modifierNamedArgs: Nullable = null; + let modifiedElement: SimpleElement | undefined; + class Bar extends AbstractInsertable { + didInsertElement(params: unknown[], namedArgs: Dict) { + modifierParams = params; + modifierNamedArgs = namedArgs; + modifiedElement = this.element; + } + override didUpdate(params: unknown[], namedArgs: Dict) { + modifierParams = params; + modifierNamedArgs = namedArgs; + modifiedElement = this.element; + } + } + this.registerComponent('Glimmer', 'TheFoo', '
    Foo
    '); + this.registerModifier('bar', Bar); + this.render('', { + something: 'something', + foo: 'else', + }); + assert.deepEqual(modifierParams, ['something']); + assert.deepEqual(modifierNamedArgs, { foo: 'else' }); + assert.strictEqual( + modifiedElement && modifiedElement.getAttribute('id'), + 'inner-div', + 'Modifier is called on the element receiving the splattributes' + ); + this.rerender({ something: 'another', foo: 'thingy' }); + assert.deepEqual(modifierParams, ['another']); + assert.deepEqual(modifierNamedArgs, { foo: 'thingy' }); + assert.strictEqual( + modifiedElement && modifiedElement.getAttribute('id'), + 'inner-div', + 'Modifier is called on the element receiving the splattributes' + ); + } + + @test + 'modifiers on components accept `this` in both positional params and named arguments, and updates when it changes'( + assert: Assert + ) { + let modifierParams: Nullable = null; + let modifierNamedArgs: Nullable = null; + let modifiedElement: SimpleElement | undefined; + class Bar extends AbstractInsertable { + didInsertElement(params: unknown[], namedArgs: Dict) { + modifierParams = params; + modifierNamedArgs = namedArgs; + modifiedElement = this.element; + } + override didUpdate(params: unknown[], namedArgs: Dict) { + modifierParams = params; + modifierNamedArgs = namedArgs; + modifiedElement = this.element; + } + } + let context = { id: 1 }; + let context2 = { id: 2 }; + this.registerComponent('Glimmer', 'TheFoo', '
    Foo
    '); + this.registerModifier('bar', Bar); + this.render('', context); + assert.deepEqual(modifierParams, ['name', context]); + assert.deepEqual(modifierNamedArgs, { foo: context }); + assert.strictEqual( + modifiedElement && modifiedElement.getAttribute('id'), + 'inner-div', + 'Modifier is called on the element receiving the splattributes' + ); + this.rerender(context2); + assert.deepEqual(modifierParams, ['name', context2]); + assert.deepEqual(modifierNamedArgs, { foo: context2 }); + assert.strictEqual( + modifiedElement && modifiedElement.getAttribute('id'), + 'inner-div', + 'Modifier is called on the element receiving the splattributes' + ); + } + + @test + 'modifiers on components accept local variables in both positional params and named arguments, and updates when they change'( + assert: Assert + ) { + let modifierParams: Nullable = null; + let modifierNamedArgs: Nullable = null; + let modifiedElement: SimpleElement | undefined; + class Bar extends AbstractInsertable { + didInsertElement(params: unknown[], namedArgs: Dict) { + modifierParams = params; + modifierNamedArgs = namedArgs; + modifiedElement = this.element; + } + override didUpdate(params: unknown[], namedArgs: Dict) { + modifierParams = params; + modifierNamedArgs = namedArgs; + modifiedElement = this.element; + } + } + this.registerComponent('Glimmer', 'TheFoo', '
    Foo
    '); + this.registerModifier('bar', Bar); + this.render( + ` + {{#let this.foo as |v|}} + + {{/let}} + `, + { foo: 'bar' } + ); + assert.deepEqual(modifierParams, ['bar']); + assert.deepEqual(modifierNamedArgs, { foo: 'bar' }); + assert.strictEqual( + modifiedElement && modifiedElement.getAttribute('id'), + 'inner-div', + 'Modifier is called on the element receiving the splattributes' + ); + this.rerender({ foo: 'qux' }); + assert.deepEqual(modifierParams, ['qux']); + assert.deepEqual(modifierNamedArgs, { foo: 'qux' }); + assert.strictEqual( + modifiedElement && modifiedElement.getAttribute('id'), + 'inner-div', + 'Modifier is called on the element receiving the splattributes' + ); + } + + @test + 'modifiers on components can be received and forwarded to inner components'(assert: Assert) { + let modifierParams: Nullable = null; + let modifierNamedArgs: Nullable = null; + let elementIds: Nullable[] = []; + + class Bar extends AbstractInsertable { + didInsertElement(params: unknown[], namedArgs: Dict) { + modifierParams = params; + modifierNamedArgs = namedArgs; + if (this.element) { + elementIds.push(this.element.getAttribute('id')); + } + } + } + this.registerComponent( + 'Glimmer', + 'TheInner', + '
    {{yield}}
    ' + ); + this.registerComponent( + 'Glimmer', + 'TheFoo', + '
    Outer
    Hello' + ); + this.registerModifier('bar', Bar); + this.render( + ` + {{#let this.foo as |v|}} + + {{/let}} + `, + { foo: 'bar' } + ); + assert.deepEqual(modifierParams, ['bar']); + assert.deepEqual(modifierNamedArgs, { foo: 'bar' }); + assert.deepEqual(elementIds, ['outer-div', 'inner-div'], 'Modifiers are called on all levels'); + } + + @test + 'same element insertion order'(assert: Assert) { + let insertionOrder: string[] = []; + + class Foo extends AbstractInsertable { + didInsertElement() { + insertionOrder.push('foo'); + } + } + + class Bar extends AbstractInsertable { + didInsertElement() { + insertionOrder.push('bar'); + } + } + this.registerModifier('bar', Bar); + this.registerModifier('foo', Foo); + + this.render('
    '); + assert.deepEqual(insertionOrder, ['foo', 'bar']); + } + + @test + 'same element destruction order'(assert: Assert) { + let destructionOrder: string[] = []; + + class Foo extends AbstractDestroyable { + willDestroyElement() { + destructionOrder.push('foo'); + } + } + + class Bar extends AbstractDestroyable { + willDestroyElement() { + destructionOrder.push('bar'); + } + } + this.registerModifier('bar', Bar); + this.registerModifier('foo', Foo); + + this.render('{{#if this.nuke}}
    {{/if}}', { nuke: true }); + assert.deepEqual(destructionOrder, []); + this.rerender({ nuke: false }); + assert.deepEqual(destructionOrder, ['foo', 'bar']); + } + + @test + 'parent -> child insertion order'(assert: Assert) { + let insertionOrder: string[] = []; + + class Foo extends AbstractInsertable { + didInsertElement() { + insertionOrder.push('foo'); + } + } + + class Bar extends AbstractInsertable { + didInsertElement() { + insertionOrder.push('bar'); + } + } + this.registerModifier('bar', Bar); + this.registerModifier('foo', Foo); + + this.render('
    '); + assert.deepEqual(insertionOrder, ['bar', 'foo']); + } + + @test + 'parent -> child destruction order'(assert: Assert) { + let destructionOrder: string[] = []; + + class Foo extends AbstractDestroyable { + willDestroyElement() { + destructionOrder.push('foo'); + } + } + + class Bar extends AbstractDestroyable { + willDestroyElement() { + destructionOrder.push('bar'); + } + } + this.registerModifier('bar', Bar); + this.registerModifier('foo', Foo); + + this.render('{{#if this.nuke}}
    {{/if}}', { nuke: true }); + assert.deepEqual(destructionOrder, []); + this.rerender({ nuke: false }); + assert.deepEqual(destructionOrder, ['bar', 'foo']); + } + + @test + 'sibling insertion order'(assert: Assert) { + let insertionOrder: string[] = []; + + class Foo extends AbstractInsertable { + didInsertElement() { + insertionOrder.push('foo'); + } + } + + class Bar extends AbstractInsertable { + didInsertElement() { + insertionOrder.push('bar'); + } + } + + class Baz extends AbstractInsertable { + didInsertElement() { + insertionOrder.push('baz'); + } + } + this.registerModifier('bar', Bar); + this.registerModifier('foo', Foo); + this.registerModifier('baz', Baz); + + this.render('
    '); + assert.deepEqual(insertionOrder, ['bar', 'baz', 'foo']); + } + + @test + 'sibling destruction order'(assert: Assert) { + let destructionOrder: string[] = []; + + class Foo extends AbstractDestroyable { + willDestroyElement() { + destructionOrder.push('foo'); + } + } + + class Bar extends AbstractDestroyable { + willDestroyElement() { + destructionOrder.push('bar'); + } + } + + class Baz extends AbstractDestroyable { + willDestroyElement() { + destructionOrder.push('baz'); + } + } + this.registerModifier('bar', Bar); + this.registerModifier('foo', Foo); + this.registerModifier('baz', Baz); + + this.render( + '{{#if this.nuke}}
    {{/if}}', + { + nuke: true, + } + ); + assert.deepEqual(destructionOrder, []); + this.rerender({ nuke: false }); + assert.deepEqual(destructionOrder, ['bar', 'baz', 'foo']); + } + + @test + 'with params'(assert: Assert, count: Count) { + class Foo extends BaseModifier { + override didInsertElement([bar]: string[]) { + count.expect('didInsertElement'); + assert.strictEqual(bar, 'bar'); + } + override didUpdate([foo]: string[]) { + count.expect('didUpdate'); + assert.strictEqual(foo, 'foo'); + } + } + this.registerModifier('foo', Foo); + this.render('
    ', { bar: 'bar' }); + this.rerender({ bar: 'foo' }); + } + + @test + 'with hash'(assert: Assert, count: Count) { + class Foo extends BaseModifier { + override didInsertElement(_params: unknown[], { bar }: Dict) { + count.expect('didInsertElement'); + assert.strictEqual(bar, 'bar'); + } + override didUpdate(_params: unknown[], { bar }: Dict) { + count.expect('didUpdate'); + assert.strictEqual(bar, 'foo'); + } + } + this.registerModifier('foo', Foo); + this.render('
    ', { bar: 'bar' }); + this.rerender({ bar: 'foo' }); + } + + @test + 'with hash and params'(assert: Assert, count: Count) { + class Foo extends BaseModifier { + override didInsertElement([baz]: string[], { bar }: Dict) { + count.expect('didInsertElement'); + assert.strictEqual(bar, 'bar'); + assert.strictEqual(baz, 'baz'); + } + override didUpdate([foo]: string[], { bar }: Dict) { + count.expect('didUpdate'); + assert.strictEqual(bar, 'foo'); + assert.strictEqual(foo, 'foo'); + } + } + this.registerModifier('foo', Foo); + this.render('
    ', { bar: 'bar', baz: 'baz' }); + this.rerender({ bar: 'foo', baz: 'foo' }); + } +} +jitSuite(ModifierTests); diff --git a/packages/@glimmer-workspace/integration-tests/test/modifiers/dynamic-modifiers-test.ts b/packages/@glimmer-workspace/integration-tests/test/modifiers/dynamic-modifiers-test.ts new file mode 100644 index 00000000000..91854bdbf7e --- /dev/null +++ b/packages/@glimmer-workspace/integration-tests/test/modifiers/dynamic-modifiers-test.ts @@ -0,0 +1,204 @@ +import { + defineComponent, + defineSimpleHelper, + defineSimpleModifier, + GlimmerishComponent, + jitSuite, + RenderTest, + syntaxErrorFor, + test, +} from '@glimmer-workspace/integration-tests'; + +class DynamicModifiersResolutionModeTest extends RenderTest { + static suiteName = 'dynamic modifiers in resolution mode'; + + @test + 'Can use a dynamic modifier'() { + const foo = defineSimpleModifier((element: Element) => (element.innerHTML = 'Hello, world!')); + + this.registerComponent( + 'Glimmer', + 'Bar', + '
    ', + class extends GlimmerishComponent { + foo = foo; + } + ); + + this.render(''); + this.assertHTML('
    Hello, world!
    '); + this.assertStableRerender(); + } + + @test + 'Can use a nested argument as a modifier'() { + const foo = defineSimpleModifier((element: Element) => (element.innerHTML = 'Hello, world!')); + this.registerComponent('TemplateOnly', 'Foo', '
    '); + + this.render('', { x: { foo } }); + this.assertHTML('
    Hello, world!
    '); + this.assertStableRerender(); + } + + @test + 'Can pass curried modifier as argument and invoke dynamically'() { + const foo = defineSimpleModifier((element: Element, [value]: [string]): void => { + element.innerHTML = value; + }); + this.registerComponent('TemplateOnly', 'Foo', '
    '); + + this.render('', { foo }); + this.assertHTML('
    Hello, world!
    '); + this.assertStableRerender(); + } + + @test + 'Can pass curried modifier as argument and invoke dynamically (with args, multi-layer)'() { + const foo = defineSimpleModifier( + (element: Element, values: string[]) => (element.innerHTML = values.join(' ')) + ); + this.registerComponent('TemplateOnly', 'Foo', '
    '); + this.registerComponent('TemplateOnly', 'Bar', ''); + + this.render('', { foo }); + this.assertHTML('
    one two three
    '); + this.assertStableRerender(); + } + + @test + 'Modifiers with dynamic arguments receive the correct number of arguments'(assert: Assert) { + let receivedArgs: unknown[] = []; + const foo = defineSimpleModifier((_element: unknown, args: unknown[]) => (receivedArgs = args)); + + this.render( + ` + {{~#let (modifier this.foo this.outer) as |foo|~}} +
    General Kenobi!
    + {{~/let~}} + `, + { foo, inner: 'x', outer: 'y', cond: true } + ); + + this.assertHTML('
    General Kenobi!
    '); + this.assertStableRerender(); + assert.deepEqual(receivedArgs, ['y', 'x']); + this.rerender({ cond: false }); + this.rerender({ cond: true }); + assert.deepEqual(receivedArgs, ['y', 'x']); + } + + @test + 'Can pass curried modifier as argument and invoke dynamically (with args)'() { + const foo = defineSimpleModifier( + (element: Element, [first, second]: string[]) => (element.innerHTML = `${first} ${second}`) + ); + this.registerComponent('TemplateOnly', 'Foo', '
    '); + + this.render('', { foo }); + this.assertHTML('
    Hello, world!
    '); + this.assertStableRerender(); + } + + @test + 'Can pass curried modifier as argument and invoke dynamically (with named args)'() { + const foo = defineSimpleModifier( + (element: Element, _: unknown, { greeting }: { greeting: string }) => + (element.innerHTML = greeting) + ); + this.registerComponent( + 'TemplateOnly', + 'Foo', + '
    ' + ); + + this.render('', { foo }); + this.assertHTML('
    Hello, Nebula!
    '); + this.assertStableRerender(); + } + + @test + 'Can pass curried modifier as argument and invoke dynamically (with named args, multi-layer)'() { + const foo = defineSimpleModifier( + (element: Element, _: unknown, { greeting, name }: { greeting: string; name: string }) => + (element.innerHTML = `${greeting} ${name}`) + ); + + this.registerComponent('TemplateOnly', 'Foo', '
    '); + this.registerComponent( + 'TemplateOnly', + 'Bar', + '' + ); + + this.render('', { foo }); + this.assertHTML('
    Hello, Nebula!
    '); + this.assertStableRerender(); + } + + @test + 'Can invoke a yielded nested modifier'() { + const foo = defineSimpleModifier((element: Element) => (element.innerHTML = 'Hello, world!')); + this.registerComponent( + 'TemplateOnly', + 'Bar', + '{{#let @x as |x|}}
    {{/let}}' + ); + + this.render('', { x: { foo } }); + this.assertHTML('
    Hello, world!
    '); + this.assertStableRerender(); + } + + @test + 'Cannot invoke a modifier definition based on this fallback lookup in resolution mode'() { + this.assert.throws( + () => { + this.registerComponent('TemplateOnly', 'Bar', '
    '); + }, + syntaxErrorFor( + 'You attempted to invoke a path (`{{x.foo}}`) as a modifier, but x was not in scope', + '{{x.foo}}', + 'an unknown module', + 1, + 5 + ) + ); + } + + @test + 'Can use a dynamic modifier with a nested helper'() { + const foo = defineSimpleHelper(() => 'Hello, world!'); + const bar = defineSimpleModifier( + (element: Element, value: string) => (element.innerHTML = value) + ); + const Bar = defineComponent({ foo }, '
    ', { + definition: class extends GlimmerishComponent { + bar = bar; + }, + }); + + this.renderComponent(Bar); + this.assertHTML('
    Hello, world!
    '); + this.assertStableRerender(); + } + + @test + 'Can use a dynamic modifier with a nested dynamic helper'() { + const foo = defineSimpleHelper(() => 'Hello, world!'); + const bar = defineSimpleModifier( + (element: Element, value: string) => (element.innerHTML = value) + ); + const Bar = defineComponent({}, '
    ', { + definition: class extends GlimmerishComponent { + foo = foo; + bar = bar; + }, + }); + + this.renderComponent(Bar); + this.assertHTML('
    Hello, world!
    '); + this.assertStableRerender(); + } +} + +jitSuite(DynamicModifiersResolutionModeTest); diff --git a/packages/@glimmer-workspace/integration-tests/test/modifiers/on-test.ts b/packages/@glimmer-workspace/integration-tests/test/modifiers/on-test.ts new file mode 100644 index 00000000000..e67965b6027 --- /dev/null +++ b/packages/@glimmer-workspace/integration-tests/test/modifiers/on-test.ts @@ -0,0 +1,422 @@ +import { castToBrowser, expect } from '@glimmer/debug-util'; +import { getInternalModifierManager } from '@glimmer/manager'; +import { on } from '@glimmer/runtime'; +import { jitSuite, RenderTest, test } from '@glimmer-workspace/integration-tests'; +import { consume } from '@glimmer-workspace/test-utils'; +import { DEBUG } from '@glimmer/env'; + +// check if window exists and actually is the global +const hasDom = + typeof self === 'object' && + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition + self !== null && + self.Object === Object && + typeof Window !== 'undefined' && + self.constructor === Window && + typeof document === 'object' && + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition + document !== null && + self.document === document && + typeof location === 'object' && + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition + location !== null && + self.location === location && + typeof history === 'object' && + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition + history !== null && + self.history === history; +// node >= 21 has experimental `navigator` support, so it's no +// longer a good heuristic + +interface Counters { + adds: number; + removes: number; +} + +interface OnManager { + counters: Counters; +} + +function getOnManager() { + return getInternalModifierManager(on) as unknown as OnManager; +} + +if (hasDom) { + class OnTest extends RenderTest { + static suiteName = '{{on}} Modifier'; + + startingCounters: Counters = { adds: 0, removes: 0 }; + + findButton(selector = 'button'): HTMLButtonElement { + return expect( + castToBrowser(this.element, 'div').querySelector(selector) as HTMLButtonElement, + `BUG: expected to find ${selector}` + ); + } + + beforeEach() { + // might error if getOnManagerInstance fails + this.startingCounters = getOnManager().counters; + } + + assertCounts(expected: Counters) { + this.assert.deepEqual( + getOnManager().counters, + { + adds: expected.adds + this.startingCounters.adds, + removes: expected.removes + this.startingCounters.removes, + }, + `counters have incremented by ${JSON.stringify(expected)}` + ); + } + + @test + 'it adds an event listener'(assert: Assert) { + let count = 0; + + this.render('', { + callback() { + count++; + }, + }); + + assert.strictEqual(count, 0, 'not called on initial render'); + + this.assertStableRerender(); + this.assertCounts({ adds: 1, removes: 0 }); + assert.strictEqual(count, 0, 'not called on a rerender'); + + this.findButton().click(); + + assert.strictEqual(count, 1, 'has been called 1 time'); + + this.findButton().click(); + + assert.strictEqual(count, 2, 'has been called 2 times'); + + this.assertCounts({ adds: 1, removes: 0 }); + } + + @test + 'passes the event to the listener'(assert: Assert) { + let event: UIEvent; + + this.render('', { + callback(evt: UIEvent) { + event = evt; + }, + }); + + let button = this.findButton(); + + button.click(); + + assert.strictEqual(event!.target, button, 'has a valid event with a target'); + + this.assertCounts({ adds: 1, removes: 0 }); + } + + @test + 'the listener callback is bound'(assert: Assert) { + let first = 0; + let second = 0; + let firstCallback = () => first++; + let secondCallback = () => second++; + + this.render('', { + callback: firstCallback, + }); + + let button = this.findButton(); + + assert.strictEqual(first, 0, 'precond - first not called on initial render'); + assert.strictEqual(second, 0, 'precond - second not called on initial render'); + + button.click(); + + assert.strictEqual(first, 1, 'first has been called 1 time'); + assert.strictEqual(second, 0, 'second not called on initial render'); + + this.rerender({ callback: secondCallback }); + + button.click(); + + assert.strictEqual(first, 1, 'first has been called 1 time'); + assert.strictEqual(second, 1, 'second has been called 1 times'); + + this.assertCounts({ adds: 2, removes: 1 }); + } + + @test + 'setting once named argument ensures the callback is only called once'(assert: Assert) { + let count = 0; + + this.render('', { + callback() { + count++; + }, + }); + + let button = this.findButton(); + + assert.strictEqual(count, 0, 'not called on initial render'); + + this.assertStableRerender(); + assert.strictEqual(count, 0, 'not called on a rerender'); + + button.click(); + + assert.strictEqual(count, 1, 'has been called 1 time'); + + button.click(); + + assert.strictEqual(count, 1, 'has been called 1 times'); + + this.assertCounts({ adds: 1, removes: 0 }); + } + + @test + 'changing from `once=false` to `once=true` ensures the callback can only be called once'( + assert: Assert + ) { + let count = 0; + + this.render('', { + callback() { + count++; + }, + + once: false, + }); + + let button = this.findButton(); + + button.click(); + assert.strictEqual(count, 1, 'has been called 1 time'); + + button.click(); + assert.strictEqual(count, 2, 'has been called 2 times'); + + this.rerender({ once: true }); + + button.click(); + assert.strictEqual(count, 3, 'has been called 3 time'); + + button.click(); + assert.strictEqual(count, 3, 'is not called again'); + + this.assertCounts({ adds: 2, removes: 1 }); + } + + @test({ skip: !DEBUG }) + 'setting passive named argument prevents calling preventDefault'(assert: Assert) { + let matcher = + /You marked this listener as 'passive', meaning that you must not call 'event.preventDefault\(\)'/u; + + this.render('', { + callback(event: UIEvent) { + assert.throws(() => { + event.preventDefault(); + }, matcher); + }, + }); + + this.findButton().click(); + } + + @test + 'by default bubbling is used (capture: false)'(assert: Assert) { + this.render( + ` + + + `, + { + handleOuterClick() { + assert.step('outer clicked'); + }, + handleInnerClick() { + assert.step('inner clicked'); + }, + } + ); + + this.findButton('.inner').click(); + + assert.verifySteps(['inner clicked', 'outer clicked'], 'uses capture: false by default'); + } + + @test + 'specifying capture named argument uses capture semantics'(assert: Assert) { + this.render( + ` + + + `, + { + handleOuterClick() { + assert.step('outer clicked'); + }, + handleInnerClick() { + assert.step('inner clicked'); + }, + } + ); + + this.findButton('.inner').click(); + + assert.verifySteps(['outer clicked', 'inner clicked'], 'capture works'); + } + + @test + 'can use capture and once together'(assert: Assert) { + this.render( + ` + + + `, + { + handleOuterClick() { + assert.step('outer clicked'); + }, + handleInnerClick() { + assert.step('inner clicked'); + }, + } + ); + + this.findButton('.inner').click(); + + assert.verifySteps(['outer clicked', 'inner clicked'], 'capture works'); + + this.findButton('.inner').click(); + + assert.verifySteps(['inner clicked'], 'once works'); + } + + @test + 'unrelated updates to `this` context does not result in removing + re-adding'(assert: Assert) { + let called = false; + + this.render('', { + callback() { + called = true; + }, + otherThing: 0, + }); + + this.assertCounts({ adds: 1, removes: 0 }); + + this.findButton().click(); + + assert.strictEqual(called, true, 'callback is being invoked'); + + this.rerender({ otherThing: 1 }); + this.assertCounts({ adds: 1, removes: 0 }); + } + + @test({ skip: !DEBUG }) + 'asserts when eventName is missing'(assert: Assert) { + assert.throws(() => { + this.render(``, { + callback() {}, + }); + }, /You must pass a valid DOM event name as the first argument to the `on` modifier/u); + } + + @test({ skip: !DEBUG }) + 'asserts when eventName is a bound undefined value'(assert: Assert) { + assert.throws(() => { + this.render(``, { + callback() {}, + }); + }, /You must pass a valid DOM event name as the first argument to the `on` modifier/u); + } + + @test({ skip: !DEBUG }) + 'asserts when eventName is a function'(assert: Assert) { + assert.throws(() => { + this.render(``, { + callback() {}, + }); + }, /You must pass a valid DOM event name as the first argument to the `on` modifier/u); + } + + @test({ skip: !DEBUG }) + 'asserts when callback is missing'(assert: Assert) { + assert.throws(() => { + this.render(``); + }, /You must pass a function as the second argument to the `on` modifier/u); + } + + @test({ skip: !DEBUG }) + 'asserts when callback is undefined'(assert: Assert) { + assert.throws(() => { + this.render(``); + }, /You must pass a function as the second argument to the `on` modifier; you passed undefined. While rendering:\n{2}this.foo/u); + } + + @test({ skip: !DEBUG }) + 'asserts when callback is null'(assert: Assert) { + assert.throws(() => { + this.render(``, { foo: null }); + }, /You must pass a function as the second argument to the `on` modifier; you passed null. While rendering:\n{2}this.foo/u); + } + + @test({ skip: !DEBUG }) + 'asserts if the provided callback accesses `this` without being bound prior to passing to on'( + assert: Assert + ) { + this.render(``, { + myFunc(this: any) { + assert.throws(() => { + consume(this.arg1); + }, /You accessed `this.arg1` from a function passed to the `on` modifier, but the function itself was not bound to a valid `this` context. Consider updating to use a bound function/u); + }, + + arg1: 'foo', + }); + + this.findButton().click(); + } + + @test({ skip: !DEBUG }) + 'asserts if more than 2 positional parameters are provided'(assert: Assert) { + assert.throws(() => { + this.render(``, { + callback() {}, + someArg: 'foo', + }); + }, /You can only pass two positional arguments \(event name and callback\) to the `on` modifier, but you provided 3. Consider using the `fn` helper to provide additional arguments to the `on` callback./u); + } + + @test + 'it removes the modifier when the element is removed'(assert: Assert) { + let count = 0; + + this.render( + '{{#if this.showButton}}{{/if}}', + { + callback() { + count++; + }, + showButton: true, + } + ); + + this.assertCounts({ adds: 1, removes: 0 }); + + this.findButton().click(); + + assert.strictEqual(count, 1, 'has been called 1 time'); + + this.rerender({ showButton: false }); + this.assertCounts({ adds: 1, removes: 1 }); + } + } + + jitSuite(OnTest); +} diff --git a/packages/@glimmer-workspace/integration-tests/test/node-suites-node-test.ts b/packages/@glimmer-workspace/integration-tests/test/node-suites-node-test.ts new file mode 100644 index 00000000000..6d37fba6278 --- /dev/null +++ b/packages/@glimmer-workspace/integration-tests/test/node-suites-node-test.ts @@ -0,0 +1,22 @@ +import { + CompilationTests, + DOMHelperTests, + JitSerializationDelegate, + nodeComponentSuite, + NodeJitRenderDelegate, + nodeSuite, + SerializedDOMHelperTests, + ServerSideComponentSuite, + ServerSideSuite, + suite, +} from '@glimmer-workspace/integration-tests'; + +nodeSuite(ServerSideSuite); +nodeComponentSuite(ServerSideComponentSuite); + +suite(DOMHelperTests, NodeJitRenderDelegate); +suite(SerializedDOMHelperTests, JitSerializationDelegate); + +if (typeof (globalThis as any).process !== 'undefined') { + suite(CompilationTests, NodeJitRenderDelegate); +} diff --git a/packages/@glimmer-workspace/integration-tests/test/owner-test.ts b/packages/@glimmer-workspace/integration-tests/test/owner-test.ts new file mode 100644 index 00000000000..b80180164f5 --- /dev/null +++ b/packages/@glimmer-workspace/integration-tests/test/owner-test.ts @@ -0,0 +1,245 @@ +import type { + InternalComponentCapabilities, + Owner, + ResolvedComponentDefinition, + WithCreateInstance, + WithSubOwner, +} from '@glimmer/interfaces'; +import type { Reference } from '@glimmer/reference'; +import type { RenderDelegateOptions } from '@glimmer-workspace/integration-tests'; +import { setInternalComponentManager } from '@glimmer/manager'; +import { NULL_REFERENCE } from '@glimmer/reference'; +import { + createTemplate, + defineComponent, + EmberishCurlyComponent, + GlimmerishComponent, + JitRenderDelegate, + RenderTest, + suite, + test, + TestJitRuntimeResolver, +} from '@glimmer-workspace/integration-tests'; + +class OwnerJitRuntimeResolver extends TestJitRuntimeResolver { + override lookupComponent(name: string, owner: () => void): ResolvedComponentDefinition | null { + if (typeof owner === 'function') owner(); + + return super.lookupComponent(name, owner); + } +} + +class OwnerJitRenderDelegate extends JitRenderDelegate { + constructor(options?: RenderDelegateOptions) { + super({ + ...options, + resolver: (registry) => new OwnerJitRuntimeResolver(registry), + }); + } +} + +const CAPABILITIES = { + dynamicLayout: false, + dynamicTag: false, + prepareArgs: false, + createArgs: false, + attributeHook: false, + elementHook: false, + createCaller: false, + dynamicScope: false, + updateHook: false, + createInstance: true, + wrapped: false, + willDestroy: false, + hasSubOwner: true, +}; + +// eslint-disable-next-line @typescript-eslint/no-extraneous-class +class MountComponent { + static owner: object; +} + +class MountManager implements WithCreateInstance, WithSubOwner { + getCapabilities(): InternalComponentCapabilities { + return CAPABILITIES; + } + + getOwner(state: object) { + return state; + } + + create(_owner: Owner, state: typeof MountComponent) { + return state.owner; + } + + getSelf(): Reference { + return NULL_REFERENCE; + } + + didCreate() {} + didUpdate() {} + + didRenderLayout() {} + didUpdateLayout() {} + + getDestroyable() { + return null; + } + + getDebugName() { + return 'mount'; + } +} + +setInternalComponentManager(new MountManager(), MountComponent); + +function defineMountComponent(owner: object, scope: Record, template: string) { + return defineComponent(scope, template, { + definition: class extends MountComponent { + static override owner = owner; + }, + }); +} + +function defineCheckOwnerComponent(ownerToCheck: object | undefined, assert: Assert) { + return defineComponent({}, '{{yield}}', { + definition: class extends GlimmerishComponent { + constructor(owner: object, args: Record) { + super(owner, args); + + assert.strictEqual(owner, ownerToCheck, 'owner is correct'); + } + }, + }); +} + +class OwnerTest extends RenderTest { + static suiteName = '[owner]'; + + declare delegate: OwnerJitRenderDelegate; + + @test + 'owner can be used per-template in compile time resolver'(assert: Assert) { + class FooBar extends EmberishCurlyComponent { + override layout = createTemplate('')(() => { + assert.step('foo-bar owner called'); + }); + } + + class FooBaz extends EmberishCurlyComponent { + override layout = createTemplate('')(() => { + assert.step('foo-baz owner called'); + }); + } + + this.delegate.registerComponent('Curly', 'Curly', 'FooBar', null, FooBar); + this.delegate.registerComponent('Curly', 'Curly', 'FooBaz', null, FooBaz); + this.delegate.registerComponent('TemplateOnly', 'TemplateOnly', 'FooQux', 'testing'); + + this.render(''); + + assert.verifySteps(['foo-bar owner called', 'foo-baz owner called'], 'owners used correctly'); + } + + @test + 'owner can be used per-template in runtime resolver'(assert: Assert) { + this.delegate.registerComponent('TemplateOnly', 'TemplateOnly', 'FooQux', 'testing'); + + this.delegate.registerComponent( + 'Curly', + 'Curly', + 'FooBaz', + null, + class FooBaz extends EmberishCurlyComponent { + override layout = createTemplate('')(() => { + assert.step('foo-baz owner called'); + }); + } + ); + + this.delegate.registerComponent( + 'Curly', + 'Curly', + 'FooBar', + null, + class FooBar extends EmberishCurlyComponent { + override layout = createTemplate('')(() => { + assert.step('foo-bar owner called'); + }); + } + ); + + this.render(''); + + assert.verifySteps(['foo-bar owner called', 'foo-baz owner called'], 'owners used correctly'); + } + + @test + 'owner can be changed by a component with the hasSubOwner capability'(assert: Assert) { + let owner1 = { name: 'owner1' }; + let owner2 = { name: 'owner2' }; + + const CheckOwner2 = defineCheckOwnerComponent(owner1, assert); + const CheckOwner1 = defineCheckOwnerComponent(owner1, assert); + + const Mount2 = defineMountComponent(owner2, { CheckOwner2 }, `{{yield}}`); + const Mount1 = defineMountComponent( + owner1, + { CheckOwner1, Mount2 }, + `` + ); + + this.renderComponent(Mount1); + } + + @test + 'owner is preserved in curried closure components'(assert: Assert) { + let owner1 = { name: 'owner1' }; + let owner2 = { name: 'owner2' }; + + const CheckOwner2 = defineCheckOwnerComponent(owner1, assert); + const CheckOwner1 = defineCheckOwnerComponent(owner1, assert); + + const Mount2 = defineMountComponent(owner2, { CheckOwner2 }, `<@CheckOwner1/>`); + const Mount1 = defineMountComponent( + owner1, + { CheckOwner1, Mount2 }, + `` + ); + + this.renderComponent(Mount1); + } + + // TODO: This behavior could be confusing the users, but currently we don't know of a way + // to ensure we are using the component with the correct owner if it was not curried. + // We should continue exploring options here. + @test + 'owner is preserved in non-curried component definitions that are passed around'(assert: Assert) { + let owner1 = { name: 'owner1' }; + let owner2 = { name: 'owner2' }; + + const CheckOwner2 = defineCheckOwnerComponent(owner1, assert); + const CheckOwner1 = defineCheckOwnerComponent(owner1, assert); + + const Mount2 = defineMountComponent(owner2, { CheckOwner2 }, `<@CheckOwner2/>`); + const Mount1 = defineMountComponent( + owner1, + { CheckOwner1, CheckOwner2, Mount2 }, + `` + ); + + this.renderComponent(Mount1); + } + + @test + 'resolution mode components defined within strict mode components receive correct owner during compilation'() { + this.registerComponent('TemplateOnly', 'Foo', 'Hello, world!'); + + const Bar = defineComponent(null, ''); + const Baz = defineComponent({ Bar }, ''); + + this.renderComponent(Baz); + } +} + +suite(OwnerTest, OwnerJitRenderDelegate); diff --git a/packages/@glimmer-workspace/integration-tests/test/package.json b/packages/@glimmer-workspace/integration-tests/test/package.json new file mode 100644 index 00000000000..7fda1b061b7 --- /dev/null +++ b/packages/@glimmer-workspace/integration-tests/test/package.json @@ -0,0 +1,25 @@ +{ + "private": true, + "name": "@glimmer-test/integration-tests", + "version": "0.92.0", + "scripts": {}, + "dependencies": { + "@glimmer-workspace/integration-tests": "workspace:*", + "@glimmer-workspace/test-utils": "workspace:*", + "@glimmer/compiler": "workspace:*", + "@glimmer/constants": "workspace:*", + "@glimmer/debug-util": "workspace:*", + "@glimmer/destroyable": "workspace:*", + "@glimmer/global-context": "workspace:*", + "@glimmer/local-debug-flags": "workspace:*", + "@glimmer/manager": "workspace:*", + "@glimmer/opcode-compiler": "workspace:*", + "@glimmer/owner": "workspace:*", + "@glimmer/reference": "workspace:*", + "@glimmer/runtime": "workspace:*", + "@glimmer/syntax": "workspace:*", + "@glimmer/util": "workspace:*", + "@glimmer/validator": "workspace:*", + "@glimmer/wire-format": "workspace:*" + } +} diff --git a/packages/@glimmer-workspace/integration-tests/test/partial-rehydration-test.ts b/packages/@glimmer-workspace/integration-tests/test/partial-rehydration-test.ts new file mode 100644 index 00000000000..da8b8061cc2 --- /dev/null +++ b/packages/@glimmer-workspace/integration-tests/test/partial-rehydration-test.ts @@ -0,0 +1,194 @@ +import { castToSimple } from '@glimmer/debug-util'; +import { + CLOSE, + content, + OPEN, + PartialRehydrationDelegate, + qunitFixture, + RenderTest, + replaceHTML, + stripTight, + suite, + test, +} from '@glimmer-workspace/integration-tests'; + +export class PartialRehydrationTest extends RenderTest { + static suiteName = 'partial rehydration'; + declare delegate: PartialRehydrationDelegate; + + @test + 'can rehydrate from non starting blocks'() { + this.delegate.registerTemplateOnlyComponent('RehydratingComponent', '{{@a}}{{@b}}{{@c}}'); + + this.delegate.registerTemplateOnlyComponent( + 'Root', + '
    ' + ); + + const args = { + a: 'a', + b: 'b', + c: 'c', + }; + + const html = this.delegate.renderComponentServerSide('Root', args); + this.assert.strictEqual( + html, + content([ + OPEN, + OPEN, + '
    ', + OPEN, + OPEN, + 'a', + CLOSE, + OPEN, + 'b', + CLOSE, + OPEN, + 'c', + CLOSE, + CLOSE, + '
    ', + CLOSE, + CLOSE, + ]), + 'Expect server output to match' + ); + + replaceHTML(qunitFixture(), html); + this.element = qunitFixture(); + this.renderResult = this.delegate.renderComponentClientSide( + 'RehydratingComponent', + args, + castToSimple(document.getElementById('placeholder')!) + ); + this.assertHTML(content([OPEN, OPEN, '
    abc
    ', CLOSE, CLOSE])); + this.assert.ok( + this.delegate.rehydrationStats.clearedNodes.length === 0, + 'No nodes were cleared' + ); + this.assertStableNodes(); + this.assertStableRerender(); + } + + @test + 'can rehydrate multiple call sites'() { + this.delegate.registerTemplateOnlyComponent('Nav', '{{@title}}'); + this.delegate.registerTemplateOnlyComponent('Carousel', '{{@name}}'); + this.delegate.registerTemplateOnlyComponent('Header', '

    I am a test

    '); + + this.delegate.registerTemplateOnlyComponent( + 'Root', + stripTight` + +
    + + ` + ); + + const args = { + nav: { + title: 'Nav', + }, + carousel: { + name: 'Carousel', + }, + }; + + const html = this.delegate.renderComponentServerSide('Root', args); + this.assert.strictEqual( + html, + content([ + OPEN, + OPEN, + '', + OPEN, + '

    I am a test

    ', + CLOSE, + '', + CLOSE, + CLOSE, + ]) + ); + + replaceHTML(qunitFixture(), html); + this.element = qunitFixture(); + + // Rehydrate First Component + this.renderResult = this.delegate.renderComponentClientSide( + 'Nav', + args.nav, + castToSimple(document.querySelector('.nav-container')!) + ); + this.assertHTML( + content([ + OPEN, + OPEN, + '', + OPEN, + '

    I am a test

    ', + CLOSE, + '', + CLOSE, + CLOSE, + ]) + ); + this.assert.ok( + this.delegate.rehydrationStats.clearedNodes.length === 0, + 'No nodes were cleared' + ); + this.assertStableNodes(); + this.assertStableRerender(); + + // Rehydrate the second component + this.renderResult = this.delegate.renderComponentClientSide( + 'Carousel', + args.carousel, + castToSimple(document.querySelector('.carousel-container')!) + ); + this.assertHTML( + content([ + OPEN, + OPEN, + '', + OPEN, + '

    I am a test

    ', + CLOSE, + '', + CLOSE, + CLOSE, + ]) + ); + this.assert.ok( + this.delegate.rehydrationStats.clearedNodes.length === 0, + 'No nodes were cleared' + ); + this.assertStableNodes(); + this.assertStableRerender(); + } +} + +suite(PartialRehydrationTest, PartialRehydrationDelegate); diff --git a/packages/@glimmer-workspace/integration-tests/test/precompile-test.ts b/packages/@glimmer-workspace/integration-tests/test/precompile-test.ts new file mode 100644 index 00000000000..a45dbb19cfb --- /dev/null +++ b/packages/@glimmer-workspace/integration-tests/test/precompile-test.ts @@ -0,0 +1,81 @@ +import type { SerializedTemplateWithLazyBlock } from '@glimmer/interfaces'; +import type { + TemplateFactoryWithIdAndMeta, + TemplateWithIdAndReferrer, +} from '@glimmer/opcode-compiler'; +import { precompile } from '@glimmer/compiler'; +import { unwrapTemplate } from '@glimmer/debug-util'; +import { templateFactory } from '@glimmer/opcode-compiler'; + +let serializedTemplate: SerializedTemplateWithLazyBlock; +let serializedTemplateNoId: SerializedTemplateWithLazyBlock; + +QUnit.module('templateFactory', { + beforeEach() { + let templateJs = precompile('
    {{name}}
    ', { + meta: { moduleName: 'template/module/name' }, + }); + serializedTemplate = JSON.parse(templateJs); + serializedTemplate.id = 'server-id-1'; + + serializedTemplateNoId = JSON.parse(templateJs); + serializedTemplateNoId.id = null; + }, +}); + +QUnit.test('id of serialized template is exposed on the factory', (assert) => { + let factory = templateFactory(serializedTemplate) as TemplateFactoryWithIdAndMeta; + assert.ok(factory.__id, 'is present'); + assert.strictEqual(factory.__id, serializedTemplate.id, 'id matches serialized template id'); +}); + +QUnit.test('generates id if no id is on the serialized template', (assert) => { + let factory1 = templateFactory(serializedTemplateNoId) as TemplateFactoryWithIdAndMeta; + let factory2 = templateFactory(serializedTemplateNoId) as TemplateFactoryWithIdAndMeta; + assert.ok(factory1.__id, 'is present'); + assert.ok(factory2.__id, 'is present'); + assert.notEqual( + factory1.__id, + factory2.__id, + 'factories without underlying id create new id per factory' + ); +}); + +QUnit.test('id of template matches factory', (assert) => { + let factory = templateFactory(serializedTemplate) as TemplateFactoryWithIdAndMeta; + let template = unwrapTemplate(factory()) as TemplateWithIdAndReferrer; + assert.ok(template.id, 'is present'); + assert.strictEqual(template.id, factory.__id, 'template id matches factory id'); +}); + +QUnit.test('meta is accessible from factory', (assert) => { + let factory = templateFactory(serializedTemplate) as TemplateFactoryWithIdAndMeta; + assert.deepEqual(factory.__meta, { moduleName: 'template/module/name' }); +}); + +QUnit.test('meta is accessible from template', (assert) => { + let factory = templateFactory(serializedTemplate); + let template = unwrapTemplate(factory()) as TemplateWithIdAndReferrer; + assert.deepEqual( + template.referrer, + { moduleName: 'template/module/name', owner: null }, + 'template has expected meta' + ); +}); + +QUnit.test('can inject owner into template', (assert) => { + let owner = {}; + let factory = templateFactory(serializedTemplate); + + let template = unwrapTemplate(factory(owner)) as TemplateWithIdAndReferrer; + + assert.strictEqual(template.referrer.owner, owner, 'is owner'); + assert.deepEqual( + template.referrer, + { + moduleName: 'template/module/name', + owner, + }, + 'template has expected meta' + ); +}); diff --git a/packages/@glimmer-workspace/integration-tests/test/render-test.ts b/packages/@glimmer-workspace/integration-tests/test/render-test.ts new file mode 100644 index 00000000000..f2d3bf41dbc --- /dev/null +++ b/packages/@glimmer-workspace/integration-tests/test/render-test.ts @@ -0,0 +1,21 @@ +import { defineComponent, jitSuite, RenderTest, test } from '@glimmer-workspace/integration-tests'; + +class RenderingTest extends RenderTest { + static suiteName = ''; + + query(selector: string) { + let el = (s: string) => (this.element as unknown as HTMLElement).querySelector(s); + return el(selector) as Element; + } + + @test + 'Symbols are rendered as strings'() { + const sym = Symbol('hello world'); + const Bar = defineComponent({ sym }, '
    {{sym}}
    '); + + this.renderComponent(Bar); + this.assertHTML(`
    Symbol(hello world)
    `); + } +} + +jitSuite(RenderingTest); diff --git a/packages/@glimmer-workspace/integration-tests/test/strict-mode-test.ts b/packages/@glimmer-workspace/integration-tests/test/strict-mode-test.ts new file mode 100644 index 00000000000..f00d6096ea1 --- /dev/null +++ b/packages/@glimmer-workspace/integration-tests/test/strict-mode-test.ts @@ -0,0 +1,1361 @@ +import { castToBrowser } from '@glimmer/debug-util'; +import { array, concat, fn, get, hash, on } from '@glimmer/runtime'; +import { + defineComponent, + defineSimpleHelper, + defineSimpleModifier, + GlimmerishComponent, + jitSuite, + RenderTest, + syntaxErrorFor, + test, + TestHelper, + trackedObj, +} from '@glimmer-workspace/integration-tests'; +import { DEBUG } from '@glimmer/env'; + +class GeneralStrictModeTest extends RenderTest { + static suiteName = 'strict mode: general properties'; + + @test + 'Can call helper in append position as subexpression (without args)'() { + const plusOne = defineSimpleHelper((value = 0) => value + 1); + const Bar = defineComponent({ plusOne }, '{{(plusOne)}}'); + + this.renderComponent(Bar); + this.assertHTML('1'); + this.assertStableRerender(); + } + + @test + 'Can call helper in argument position as subexpression (without args)'() { + const plusOne = defineSimpleHelper((value = 0) => value + 1); + const Foo = defineComponent({}, '{{@value}}'); + const Bar = defineComponent({ plusOne, Foo }, ''); + + this.renderComponent(Bar); + this.assertHTML('1'); + this.assertStableRerender(); + } + + @test + 'Can call helper in argument position as subexpression in non-strict template (cross-compat test)'() { + this.registerHelper('plusOne', () => 'Hello, world!'); + this.registerComponent('TemplateOnly', 'Foo', '{{@value}}'); + this.registerComponent('TemplateOnly', 'Bar', ''); + + this.render(''); + this.assertHTML('Hello, world!'); + this.assertStableRerender(); + } + + @test + 'Can call helper in argument position as subexpression (with args)'() { + const plusOne = defineSimpleHelper((value = 0) => value + 1); + const Foo = defineComponent({}, '{{@value}}'); + const Bar = defineComponent({ plusOne, Foo }, ''); + + this.renderComponent(Bar); + this.assertHTML('2'); + this.assertStableRerender(); + } + + @test + 'Can call helper in argument position directly (with args)'() { + const plusOne = defineSimpleHelper((value = 0) => value + 1); + const Foo = defineComponent({}, '{{@value}}'); + const Bar = defineComponent({ plusOne, Foo }, ''); + + this.renderComponent(Bar); + this.assertHTML('2'); + this.assertStableRerender(); + } + + @test + 'Undefined references is an error'() { + this.registerHelper('bar', () => 'should not resolve this helper'); + + this.assert.throws( + () => { + defineComponent({}, '{{bar}}', { + definition: class extends GlimmerishComponent { + get bar() { + throw new Error('should not fallback to this.bar'); + } + }, + }); + }, + syntaxErrorFor( + 'Attempted to resolve a value in a strict mode template, but that value was not in scope: bar', + '{{bar}}', + 'an unknown module', + 1, + 0 + ) + ); + } + + @test + 'Non-native keyword'() { + this.registerHelper('bar', () => { + throw new Error('should not resolve this helper'); + }); + + this.registerHelper('$keyword.bar', () => 'bar keyword'); + + const Foo = defineComponent({}, '{{bar}}', { + keywords: ['bar'], + definition: class extends GlimmerishComponent { + get bar() { + throw new Error('should not fallback to this.bar'); + } + }, + }); + + this.renderComponent(Foo); + this.assertHTML('bar keyword'); + this.assertStableRerender(); + } + + @test + '{{component}} throws an error if a string is used in strict (append position)'() { + this.assert.throws(() => { + defineComponent({}, '{{component "bar"}}'); + }, /\(component\) cannot resolve string values in strict mode templates/u); + } + + @test({ skip: !DEBUG }) + '{{component}} throws an error if a string is used indirectly in strict (append position)'() { + const Foo = defineComponent({}, '{{component this.bar}}', { + definition: class extends GlimmerishComponent { + bar = 'bar'; + }, + }); + + this.assert.throws(() => { + this.renderComponent(Foo); + }, /Error: Attempted to resolve a dynamic component with a string definition, `bar` in a strict mode template. In strict mode, using strings to resolve component definitions is prohibited. You can instead import the component definition and use it directly./u); + } + + @test + '{{component.foo}} throws an error (append position)'() { + this.assert.throws(() => { + defineComponent({}, '{{component.foo}}', { + definition: class extends GlimmerishComponent {}, + }); + }, /The `component` keyword was used incorrectly. It was used as `component.foo`, but it cannot be used with additional path segments./u); + } + + @test({ skip: !DEBUG }) + '{{component}} throws an error if a string is used indirectly in strict after first render (append position)'() { + const Bar = defineComponent({}, 'Hello, world!'); + + const Foo = defineComponent({}, '{{component @Bar}}'); + + let args = trackedObj({ Bar }); + + this.renderComponent(Foo, args); + this.assertHTML('Hello, world!'); + this.assertStableRerender(); + + args['Bar'] = 'bar'; + + this.assert.throws(() => { + this.rerender(); + }, /Error: Attempted to resolve a dynamic component with a string definition, `bar` in a strict mode template. In strict mode, using strings to resolve component definitions is prohibited. You can instead import the component definition and use it directly./u); + } + + @test + '{{component}} throws an error if a string is used in strict (block position)'() { + this.assert.throws(() => { + defineComponent({}, '{{#component "bar"}}{{/component}}'); + }, /\(component\) cannot resolve string values in strict mode templates/u); + } + + @test({ skip: !DEBUG }) + '{{component}} throws an error if a string is used indirectly in strict (block position)'() { + const Foo = defineComponent({}, '{{#component this.bar}}{{/component}}', { + definition: class extends GlimmerishComponent { + bar = 'bar'; + }, + }); + + this.assert.throws(() => { + this.renderComponent(Foo); + }, /Error: Attempted to resolve a dynamic component with a string definition, `bar` in a strict mode template. In strict mode, using strings to resolve component definitions is prohibited. You can instead import the component definition and use it directly./u); + } + + @test({ skip: !DEBUG }) + '{{component}} throws an error if a string is used indirectly in strict after first render (block position)'() { + const Bar = defineComponent({}, 'Hello, world!'); + + const Foo = defineComponent({}, '{{#component @Bar}}{{/component}}'); + + let args = trackedObj({ Bar }); + + this.renderComponent(Foo, args); + this.assertHTML('Hello, world!'); + this.assertStableRerender(); + + args['Bar'] = 'bar'; + + this.assert.throws(() => { + this.rerender(); + }, /Error: Attempted to resolve a dynamic component with a string definition, `bar` in a strict mode template. In strict mode, using strings to resolve component definitions is prohibited. You can instead import the component definition and use it directly./u); + } + + @test + '{{component}} throws an error if a string is used in strict (expression position)'() { + this.assert.throws(() => { + defineComponent({}, '{{#let (component "bar") as |bar|}}{{/let}}'); + }, /\(component\) cannot resolve string values in strict mode templates/u); + } + + @test({ skip: !DEBUG }) + '{{component}} throws an error if a string is used indirectly in strict (expression position)'() { + const Bar = defineComponent({}, '{{#let (component this.bar) as |bar|}}{{/let}}', { + definition: class extends GlimmerishComponent { + bar = 'bar'; + }, + }); + + this.assert.throws(() => { + this.renderComponent(Bar); + }, /Error: Attempted to resolve a dynamic component with a string definition, `bar` in a strict mode template. In strict mode, using strings to resolve component definitions is prohibited. You can instead import the component definition and use it directly./u); + } + + @test({ skip: !DEBUG }) + '{{component}} throws an error if a string is used indirectly in strict after first render (expression position)'() { + const Bar = defineComponent({}, 'Hello, world!'); + + const Foo = defineComponent({}, '{{#let (component @Bar) as |bar|}}{{/let}}'); + + let args = trackedObj({ Bar }); + + this.renderComponent(Foo, args); + this.assertHTML('Hello, world!'); + this.assertStableRerender(); + + args['Bar'] = 'bar'; + + this.assert.throws(() => { + this.rerender(); + }, /Error: Attempted to resolve a dynamic component with a string definition, `bar` in a strict mode template. In strict mode, using strings to resolve component definitions is prohibited. You can instead import the component definition and use it directly./u); + } + + @test + 'works with a curried string component defined in a resolution mode component'() { + this.registerComponent('TemplateOnly', 'Hello', 'Hello, world!'); + + const Foo = defineComponent(null, '{{component "Hello"}}'); + const Bar = defineComponent({ Foo }, ''); + + this.renderComponent(Bar); + this.assertHTML('Hello, world!'); + this.assertStableRerender(); + } +} + +class StaticStrictModeTest extends RenderTest { + static suiteName = 'strict mode: static template values'; + + @test + 'Can use a component in scope'() { + const Foo = defineComponent({}, 'Hello, world!'); + const Bar = defineComponent({ Foo }, ''); + + this.renderComponent(Bar); + this.assertHTML('Hello, world!'); + this.assertStableRerender(); + } + + @test + 'Can use a custom helper in scope (in append position)'() { + const foo = defineSimpleHelper(() => 'Hello, world!'); + const Bar = defineComponent({ foo }, '{{foo}}'); + + this.renderComponent(Bar); + this.assertHTML('Hello, world!'); + this.assertStableRerender(); + } + + @test + 'Can use a custom helper in scope (in append position 1with args)'() { + const foo = defineSimpleHelper((value: string) => value); + const Bar = defineComponent({ foo }, '{{foo "Hello, world!"}}'); + + this.renderComponent(Bar); + this.assertHTML('Hello, world!'); + this.assertStableRerender(); + } + + @test + 'Can use a custom helper in scope (as subexpression)'() { + const foo = defineSimpleHelper(() => 'Hello, world!'); + const bar = defineSimpleHelper((value: string) => value); + const Baz = defineComponent({ foo, bar }, '{{bar (foo)}}'); + + this.renderComponent(Baz); + this.assertHTML('Hello, world!'); + this.assertStableRerender(); + } + + @test + 'Can use a custom modifier in scope'() { + const foo = defineSimpleModifier((element: Element) => (element.innerHTML = 'Hello, world!')); + const Bar = defineComponent({ foo }, '
    '); + + this.renderComponent(Bar); + this.assertHTML('
    Hello, world!
    '); + this.assertStableRerender(); + } + + @test + 'Can shadow keywords'() { + const ifComponent = defineComponent({}, 'Hello, world!'); + const Bar = defineComponent({ if: ifComponent }, '{{#if}}{{/if}}'); + + this.renderComponent(Bar); + this.assertHTML('Hello, world!'); + this.assertStableRerender(); + } + + @test + 'Can use template local in nested blocks with locals'() { + const place = defineSimpleHelper(() => 'world'); + const Foo = defineComponent({}, '{{yield "Hello"}}'); + const Bar = defineComponent({ Foo, place }, '{{hi}}, {{place}}!'); + + this.renderComponent(Bar); + this.assertHTML('Hello, world!'); + this.assertStableRerender(); + } + + @test + 'Can use component in ambiguous helper/component position (without args)'() { + const foo = defineComponent({}, 'Hello, world!'); + const bar = defineComponent({ foo }, '{{foo}}'); + + this.renderComponent(bar); + this.assertHTML('Hello, world!'); + this.assertStableRerender(); + } + + @test + 'Can use component in ambiguous helper/component position (with args)'() { + const foo = defineComponent({}, '{{@value}}'); + const bar = defineComponent({ foo }, '{{foo value="Hello, world!"}}'); + + this.renderComponent(bar); + this.assertHTML('Hello, world!'); + this.assertStableRerender(); + } + + @test + 'Can use constant values in ambiguous helper/component position'() { + const value = 'Hello, world!'; + + const Foo = defineComponent({ value }, '{{value}}'); + + this.renderComponent(Foo); + this.assertHTML('Hello, world!'); + this.assertStableRerender(); + } + + @test + 'Can use constant values as arguments to helpers'() { + const value = 'Hello, world!'; + + const foo = defineSimpleHelper((value: unknown) => value); + const Bar = defineComponent({ foo, value }, '{{foo value}}'); + + this.renderComponent(Bar); + this.assertHTML('Hello, world!'); + this.assertStableRerender(); + } + + @test + 'Can use constant values as arguments to components'() { + const value = 'Hello, world!'; + + const Foo = defineComponent({}, '{{@value}}'); + const Bar = defineComponent({ Foo, value }, ''); + + this.renderComponent(Bar); + this.assertHTML('Hello, world!'); + this.assertStableRerender(); + } + + @test + '{{component}} works with static components'() { + const Foo = defineComponent({}, '{{@value}}'); + const Bar = defineComponent({ Foo }, '{{component Foo value="Hello, world!"}}'); + + this.renderComponent(Bar); + this.assertHTML('Hello, world!'); + this.assertStableRerender(); + } + + @test + '{{component}} works with static components when passed to another component'() { + const Foo = defineComponent({}, '{{@value}}'); + const Bar = defineComponent({}, '<@Baz/>'); + const Baz = defineComponent( + { Foo, Bar }, + '' + ); + + this.renderComponent(Baz); + this.assertHTML('Hello, world!'); + this.assertStableRerender(); + } + + @test + 'Throws an error if component is not in scope'() { + this.assert.throws( + () => { + defineComponent({}, ''); + }, + syntaxErrorFor( + 'Attempted to invoke a component that was not in scope in a strict mode template, ``. If you wanted to create an element with that name, convert it to lowercase - ``', + '', + 'an unknown module', + 1, + 0 + ) + ); + } + + @test + 'Throws an error if value in append position is not in scope'() { + this.assert.throws( + () => { + defineComponent({}, '{{foo}}'); + }, + syntaxErrorFor( + 'Attempted to resolve a value in a strict mode template, but that value was not in scope: foo', + '{{foo}}', + 'an unknown module', + 1, + 0 + ) + ); + } + + @test + 'Throws an error if component or helper in append position is not in scope'() { + this.assert.throws( + () => { + defineComponent({}, '{{foo "bar"}}'); + }, + syntaxErrorFor( + 'Attempted to resolve a component or helper in a strict mode template, but that value was not in scope: foo', + '{{foo "bar"}}', + 'an unknown module', + 1, + 0 + ) + ); + } + + @test + 'Throws an error if a value in argument position is not in scope'() { + const Foo = defineComponent({}, '{{@foo}}'); + + this.assert.throws( + () => { + defineComponent({ Foo }, ''); + }, + syntaxErrorFor( + 'Attempted to resolve a value in a strict mode template, but that value was not in scope: bar', + '@foo={{bar}}', + 'an unknown module', + 1, + 5 + ) + ); + } + + @test + 'Throws an error if a value in attribute position is not in scope'() { + this.assert.throws( + () => { + defineComponent({}, '
    '); + }, + syntaxErrorFor( + 'Attempted to resolve a value in a strict mode template, but that value was not in scope: foo', + 'class={{foo}}', + 'an unknown module', + 1, + 5 + ) + ); + } + + @test + 'Throws an error if helper in argument position (with args) is not in scope'() { + const Foo = defineComponent({}, '{{@foo}}'); + + this.assert.throws( + () => { + defineComponent({ Foo }, ''); + }, + syntaxErrorFor( + 'Attempted to resolve a helper in a strict mode template, but that value was not in scope: bar', + '@foo={{bar "aoeu"}}', + 'an unknown module', + 1, + 5 + ) + ); + } + + @test + 'Throws an error if helper in attribute position (with args) is not in scope'() { + this.assert.throws( + () => { + defineComponent({}, '
    '); + }, + syntaxErrorFor( + 'Attempted to resolve a helper in a strict mode template, but that value was not in scope: foo', + 'class={{foo "bar"}}', + 'an unknown module', + 1, + 5 + ) + ); + } + + @test + 'Throws an error if helper in subexpression position is not in scope'() { + const foo = defineSimpleHelper((value: string) => value); + + this.assert.throws( + () => { + defineComponent({ foo }, '{{foo (bar)}}'); + }, + syntaxErrorFor( + 'Attempted to resolve a helper in a strict mode template, but that value was not in scope: bar', + '(bar)', + 'an unknown module', + 1, + 6 + ) + ); + } + + @test + 'Throws an error if modifier is not in scope'() { + this.assert.throws( + () => { + defineComponent({}, '
    '); + }, + syntaxErrorFor( + 'Attempted to resolve a modifier in a strict mode template, but that value was not in scope: foo', + '{{foo}}', + 'an unknown module', + 1, + 5 + ) + ); + } + + @test({ skip: !DEBUG }) + 'Throws an error if a non-component is used as a component'() { + const Foo = defineSimpleHelper(() => 'Hello, world!'); + const Bar = defineComponent({ Foo }, ''); + + this.assert.throws(() => { + this.renderComponent(Bar); + }, /Attempted to load a component, but there wasn't a component manager associated with the definition. The definition was:/u); + } + + @test({ skip: !DEBUG }) + 'Throws an error if a non-helper is used as a helper'() { + const foo = defineComponent({}, 'Hello, world!'); + const Bar = defineComponent({ foo }, '{{#if (foo)}}{{/if}}'); + + this.assert.throws(() => { + this.renderComponent(Bar); + }, /Attempted to load a helper, but there wasn't a helper manager associated with the definition. The definition was:/u); + } + + @test({ skip: !DEBUG }) + 'Throws an error if a non-modifier is used as a modifier'() { + const foo = defineSimpleHelper(() => 'Hello, world!'); + const Bar = defineComponent({ foo }, '
    '); + + this.assert.throws(() => { + this.renderComponent(Bar); + }, /Attempted to load a modifier, but there wasn't a modifier manager associated with the definition. The definition was:/u); + } +} + +class DynamicStrictModeTest extends RenderTest { + static suiteName = 'strict mode: dynamic template values'; + + @test + 'Can use a dynamic component'() { + const Foo = defineComponent({}, 'Hello, world!'); + const Bar = defineComponent({}, '', { + definition: class extends GlimmerishComponent { + Foo = Foo; + }, + }); + + this.renderComponent(Bar); + this.assertHTML('Hello, world!'); + this.assertStableRerender(); + } + + @test + 'Can use a dynamic component in ambiguous append position'() { + const Foo = defineComponent({}, 'Hello, world!'); + const Bar = defineComponent({}, '{{this.Foo}}', { + definition: class extends GlimmerishComponent { + Foo = Foo; + }, + }); + + this.renderComponent(Bar); + this.assertHTML('Hello, world!'); + this.assertStableRerender(); + } + + @test + 'Can use a dynamic component in append position (with args)'() { + const Foo = defineComponent({}, 'Hello, {{@value}}'); + const Bar = defineComponent({}, '{{this.Foo value="world!"}}', { + definition: class extends GlimmerishComponent { + Foo = Foo; + }, + }); + + this.renderComponent(Bar); + this.assertHTML('Hello, world!'); + this.assertStableRerender(); + } + + @test + 'Can use a dynamic component in block position'() { + const Foo = defineComponent({}, 'Hello, {{yield}}'); + const Bar = defineComponent({}, '{{#this.Foo}}world!{{/this.Foo}}', { + definition: class extends GlimmerishComponent { + Foo = Foo; + }, + }); + + this.renderComponent(Bar); + this.assertHTML('Hello, world!'); + this.assertStableRerender(); + } + + @test + 'Can use a dynamic helper'() { + const foo = defineSimpleHelper(() => 'Hello, world!'); + const Bar = defineComponent({}, '{{this.foo}}', { + definition: class extends GlimmerishComponent { + foo = foo; + }, + }); + + this.renderComponent(Bar); + this.assertHTML('Hello, world!'); + this.assertStableRerender(); + } + + @test + 'Can use a dynamic helper (with args)'() { + const foo = defineSimpleHelper((value: string) => value); + const Bar = defineComponent({}, '{{this.foo "Hello, world!"}}', { + definition: class extends GlimmerishComponent { + foo = foo; + }, + }); + + this.renderComponent(Bar); + this.assertHTML('Hello, world!'); + this.assertStableRerender(); + } + + @test + 'Can use a dynamic helper as a subexpression'() { + const foo = defineSimpleHelper(() => 'Hello, world!'); + const Bar = defineComponent({}, '{{(this.foo)}}', { + definition: class extends GlimmerishComponent { + foo = foo; + }, + }); + + this.renderComponent(Bar); + this.assertHTML('Hello, world!'); + this.assertStableRerender(); + } + + @test + 'Can use a dynamic helper as a subexpression (with args)'() { + const foo = defineSimpleHelper((value: string) => value); + const Bar = defineComponent({}, '{{(this.foo "Hello, world!")}}', { + definition: class extends GlimmerishComponent { + foo = foo; + }, + }); + + this.renderComponent(Bar); + this.assertHTML('Hello, world!'); + this.assertStableRerender(); + } + + @test + 'Can use a dynamic helper as an argument'() { + const foo = defineSimpleHelper((value: string) => value); + const bar = defineSimpleHelper((value: string) => value); + const Bar = defineComponent({ bar }, '{{bar (this.foo "Hello, world!")}}', { + definition: class extends GlimmerishComponent { + foo = foo; + }, + }); + + this.renderComponent(Bar); + this.assertHTML('Hello, world!'); + this.assertStableRerender(); + } + + @test + 'Can use a dynamic helper as an argument (with args)'() { + const foo = defineSimpleHelper(() => 'Hello, world!'); + const bar = defineSimpleHelper((value: string) => value); + const Bar = defineComponent({ bar }, '{{bar (this.foo)}}', { + definition: class extends GlimmerishComponent { + foo = foo; + }, + }); + + this.renderComponent(Bar); + this.assertHTML('Hello, world!'); + this.assertStableRerender(); + } + + @test + 'Calling a dynamic helper without a value returns undefined'() { + const Bar = defineComponent({}, '{{this.foo 123}}', { + definition: class extends GlimmerishComponent {}, + }); + + this.renderComponent(Bar); + this.assertHTML(''); + this.assertStableRerender(); + } + + @test + 'Can use a dynamic helper with a changing definition'(assert: Assert) { + class Helper1 extends TestHelper { + value() { + return 'Hello, world!'; + } + + override willDestroy() { + assert.step('willDestroy 1 called'); + } + } + + class Helper2 extends TestHelper { + value() { + return 'Hello, earth!'; + } + + override willDestroy() { + assert.step('willDestroy 2 called'); + } + } + + const Foo = defineComponent({}, '{{@helper}}'); + let args = trackedObj({ helper: Helper1 }); + + this.renderComponent(Foo, args); + this.assertHTML('Hello, world!'); + this.assertStableRerender(); + + args['helper'] = Helper2; + + this.rerender(); + this.assertHTML('Hello, earth!'); + this.assertStableRerender(); + assert.verifySteps(['willDestroy 1 called']); + + args['helper'] = undefined; + + this.rerender(); + this.assertHTML(''); + this.assertStableRerender(); + assert.verifySteps(['willDestroy 2 called']); + } + + @test + 'Can use a dynamic helper with a changing definition (curried)'(assert: Assert) { + class Helper1 extends TestHelper { + value() { + return `Hello, ${this.args.positional[0]}!`; + } + + override willDestroy() { + assert.step('willDestroy 1 called'); + } + } + + class Helper2 extends TestHelper { + value() { + return `Goodbye, ${this.args.positional[0]}!`; + } + + override willDestroy() { + assert.step('willDestroy 2 called'); + } + } + + const Foo = defineComponent({}, '{{@helper}}'); + const Bar = defineComponent({ Foo }, ''); + let args = trackedObj({ helper: Helper1 }); + + this.renderComponent(Bar, args); + this.assertHTML('Hello, world!'); + this.assertStableRerender(); + + args['helper'] = Helper2; + + this.rerender(); + this.assertHTML('Goodbye, world!'); + this.assertStableRerender(); + assert.verifySteps(['willDestroy 1 called']); + + args['helper'] = undefined; + + this.rerender(); + this.assertHTML(''); + this.assertStableRerender(); + assert.verifySteps(['willDestroy 2 called']); + } + + @test + 'Can use a dynamic modifier'() { + const foo = defineSimpleModifier((element: Element) => (element.innerHTML = 'Hello, world!')); + const Bar = defineComponent({}, '
    ', { + definition: class extends GlimmerishComponent { + foo = foo; + }, + }); + + this.renderComponent(Bar); + this.assertHTML('
    Hello, world!
    '); + this.assertStableRerender(); + } + + @test + 'Can pass modifier as argument and invoke dynamically'() { + const foo = defineSimpleModifier((element: Element) => (element.innerHTML = 'Hello, world!')); + const Foo = defineComponent({}, '
    '); + const Bar = defineComponent({ foo, Foo }, ''); + + this.renderComponent(Bar); + this.assertHTML('
    Hello, world!
    '); + this.assertStableRerender(); + } + + @test + 'Can pass modifier as argument and invoke dynamically (with args)'() { + const foo = defineSimpleModifier( + (element: Element, [value]: [string]) => (element.innerHTML = value) + ); + const Foo = defineComponent({}, '
    '); + const Bar = defineComponent({ foo, Foo }, ''); + + this.renderComponent(Bar); + this.assertHTML('
    Hello, world!
    '); + this.assertStableRerender(); + } + + @test + 'Can pass modifier as argument and invoke dynamically (with named args)'() { + const foo = defineSimpleModifier( + (element: Element, _: unknown, { greeting }: { greeting: string }) => + (element.innerHTML = greeting) + ); + const Foo = defineComponent({}, '
    '); + const Bar = defineComponent({ foo, Foo }, ''); + + this.renderComponent(Bar); + this.assertHTML('
    Hello, world!
    '); + this.assertStableRerender(); + } + + @test + 'Can pass curried modifier as argument and invoke dynamically'() { + const foo = defineSimpleModifier( + (element: Element, [value]: [string]) => (element.innerHTML = value) + ); + const Foo = defineComponent({}, '
    '); + const Bar = defineComponent({ foo, Foo }, ''); + + this.renderComponent(Bar); + this.assertHTML('
    Hello, world!
    '); + this.assertStableRerender(); + } + + @test + 'Can pass curried modifier as argument and invoke dynamically (with args)'() { + const foo = defineSimpleModifier( + (element: Element, [first, second]: string[]) => (element.innerHTML = `${first} ${second}`) + ); + const Foo = defineComponent({}, '
    '); + const Bar = defineComponent({ foo, Foo }, ''); + + this.renderComponent(Bar); + this.assertHTML('
    Hello, world!
    '); + this.assertStableRerender(); + } + + @test + 'Can pass curried modifier as argument and invoke dynamically (with args, multi-layer)'() { + const foo = defineSimpleModifier( + (element: Element, values: string[]) => (element.innerHTML = values.join(' ')) + ); + const Foo = defineComponent({}, '
    '); + const Bar = defineComponent({ Foo }, ''); + const Baz = defineComponent({ foo, Bar }, ''); + + this.renderComponent(Baz); + this.assertHTML('
    one two three
    '); + this.assertStableRerender(); + } + + @test + 'Can pass curried modifier as argument and invoke dynamically (with named args)'() { + const foo = defineSimpleModifier( + (element: Element, _: unknown, { greeting }: { greeting: string }) => + (element.innerHTML = greeting) + ); + const Foo = defineComponent({}, '
    '); + const Bar = defineComponent( + { foo, Foo }, + '' + ); + + this.renderComponent(Bar); + this.assertHTML('
    Hello, Nebula!
    '); + this.assertStableRerender(); + } + + @test + 'Can pass curried modifier as argument and invoke dynamically (with named args, multi-layer)'() { + const foo = defineSimpleModifier( + (element: Element, _: unknown, { greeting, name }: { greeting: string; name: string }) => + (element.innerHTML = `${greeting} ${name}`) + ); + + const Foo = defineComponent({}, '
    '); + const Bar = defineComponent( + { Foo }, + '' + ); + const Baz = defineComponent({ foo, Bar }, ''); + + this.renderComponent(Baz); + this.assertHTML('
    Hello, Nebula!
    '); + this.assertStableRerender(); + } + + @test + 'Can use a nested argument as a modifier'() { + const foo = defineSimpleModifier((element: Element) => (element.innerHTML = 'Hello, world!')); + const x = { foo }; + const Foo = defineComponent({}, '
    '); + const Bar = defineComponent({ Foo, x }, ''); + + this.renderComponent(Bar); + this.assertHTML('
    Hello, world!
    '); + this.assertStableRerender(); + } + + @test + 'Calling a dynamic modifier without a value is a no-op'() { + const Bar = defineComponent({}, '
    ', { + definition: class extends GlimmerishComponent {}, + }); + + this.renderComponent(Bar); + this.assertHTML('
    '); + this.assertStableRerender(); + } + + @test + 'Can use a dynamic modifier with a changing definition'(assert: Assert) { + const modifier1 = defineSimpleModifier((element: Element) => { + element.innerHTML = 'Hello, world!'; + + return () => { + assert.step('willDestroy 1 called'); + }; + }); + + const modifier2 = defineSimpleModifier((element: Element) => { + element.innerHTML = 'Hello, earth!'; + + return () => { + assert.step('willDestroy 2 called'); + }; + }); + + const Foo = defineComponent({}, '
    '); + let args = trackedObj({ modifier: modifier1 }); + + this.renderComponent(Foo, args); + this.assertHTML('
    Hello, world!
    '); + this.assertStableRerender(); + + args['modifier'] = modifier2; + + this.rerender(); + this.assertHTML('
    Hello, earth!
    '); + this.assertStableRerender(); + assert.verifySteps(['willDestroy 1 called']); + + args['modifier'] = undefined; + + this.rerender(); + this.assertHTML('
    Hello, earth!
    '); + this.assertStableRerender(); + assert.verifySteps(['willDestroy 2 called']); + } + + @test + 'Can use a dynamic modifier with a changing definition (curried)'(assert: Assert) { + const modifier1 = defineSimpleModifier((element: Element, [name]: string[]) => { + element.innerHTML = `Hello, ${name}!`; + + return () => { + assert.step('willDestroy 1 called'); + }; + }); + + const modifier2 = defineSimpleModifier((element: Element, [name]: string[]) => { + element.innerHTML = `Goodbye, ${name}!`; + + return () => { + assert.step('willDestroy 2 called'); + }; + }); + + const Foo = defineComponent({}, '
    '); + const Bar = defineComponent({ Foo }, ''); + let args = trackedObj({ modifier: modifier1 }); + + this.renderComponent(Bar, args); + this.assertHTML('
    Hello, world!
    '); + this.assertStableRerender(); + + args['modifier'] = modifier2; + + this.rerender(); + this.assertHTML('
    Goodbye, world!
    '); + this.assertStableRerender(); + assert.verifySteps(['willDestroy 1 called']); + + args['modifier'] = undefined; + + this.rerender(); + this.assertHTML('
    Goodbye, world!
    '); + this.assertStableRerender(); + assert.verifySteps(['willDestroy 2 called']); + } + + @test + 'Calling a dynamic modifier using if helper'(assert: Assert) { + // Make sure the destructor gets called + assert.expect(14); + + const world = defineSimpleModifier((element: Element) => { + element.innerHTML = `Hello, world!`; + + return () => void assert.ok(true, 'destructor called'); + }); + const nebula = defineSimpleModifier( + (element: Element, [name]: string[]) => (element.innerHTML = `Hello, ${name}!`) + ); + + const Bar = defineComponent( + { world, nebula }, + '
    ' + ); + + let args = trackedObj({ inSpace: false, name: 'Nebula' }); + + this.renderComponent(Bar, args); + this.assertHTML('
    Hello, world!
    '); + this.assertStableRerender(); + + args['inSpace'] = true; + this.rerender(); + this.assertHTML('
    Hello, Nebula!
    '); + this.assertStableRerender(); + + args['name'] = 'Luna'; + this.rerender(); + this.assertHTML('
    Hello, Luna!
    '); + this.assertStableRerender(); + } + + @test({ skip: !DEBUG }) + 'Throws an error if a non-modifier is used as a modifier'() { + const foo = defineSimpleHelper(() => 'Hello, world!'); + const Bar = defineComponent({}, '
    ', { + definition: class extends GlimmerishComponent { + foo = foo; + }, + }); + + this.assert.throws(() => { + this.renderComponent(Bar); + }, /Expected a dynamic modifier definition, but received an object or function that did not have a modifier manager associated with it. The dynamic invocation was `\{\{this.foo\}\}`, and the incorrect definition is the value at the path `this.foo`, which was:/u); + } + + @test + 'Can use a nested in scope value as dynamic component'() { + const Foo = defineComponent({}, 'Hello, world!'); + const x = { Foo }; + const Bar = defineComponent({ x }, ''); + + this.renderComponent(Bar); + this.assertHTML('Hello, world!'); + this.assertStableRerender(); + } + + @test + 'Can use a nested in scope value as dynamic helper'() { + const foo = defineSimpleHelper(() => 'Hello, world!'); + const x = { foo }; + const Bar = defineComponent({ x }, '{{x.foo}}'); + + this.renderComponent(Bar); + this.assertHTML('Hello, world!'); + this.assertStableRerender(); + } + + @test + 'Can use a nested in scope value as dynamic modifier'() { + const foo = defineSimpleModifier((element: Element) => (element.innerHTML = 'Hello, world!')); + const x = { foo }; + const Bar = defineComponent({ x }, '
    '); + + this.renderComponent(Bar); + this.assertHTML('
    Hello, world!
    '); + this.assertStableRerender(); + } + + @test + 'Can use a nested in scope value as dynamic value in argument position'() { + const x = { value: 'Hello, world!' }; + const Foo = defineComponent({}, '{{@value}}'); + const Bar = defineComponent({ Foo, x }, ''); + + this.renderComponent(Bar); + this.assertHTML('Hello, world!'); + this.assertStableRerender(); + } + + @test + 'Can use a nested in scope value as dynamic value in ambigious append position'() { + const x = { value: 'Hello, world!' }; + const Bar = defineComponent({ x }, '{{x.value}}'); + + this.renderComponent(Bar); + this.assertHTML('Hello, world!'); + this.assertStableRerender(); + } + + @test + '{{component}} works with static components'() { + const Foo = defineComponent({}, '{{@value}}'); + const Bar = defineComponent({}, '{{component this.Foo value="Hello, world!"}}', { + definition: class extends GlimmerishComponent { + Foo = Foo; + }, + }); + + this.renderComponent(Bar); + this.assertHTML('Hello, world!'); + this.assertStableRerender(); + } + + @test + '{{component}} works with static components when passed to another component'() { + const Foo = defineComponent({}, '{{@value}}'); + const Bar = defineComponent({}, '<@Baz/>'); + const Baz = defineComponent( + { Bar }, + '', + { + definition: class extends GlimmerishComponent { + Foo = Foo; + }, + } + ); + + this.renderComponent(Baz); + this.assertHTML('Hello, world!'); + this.assertStableRerender(); + } + + @test({ skip: !DEBUG }) + 'Throws an error if a non-component is used as a component'() { + const Foo = defineSimpleHelper(() => 'Hello, world!'); + const Bar = defineComponent({}, '', { + definition: class extends GlimmerishComponent { + Foo = Foo; + }, + }); + + this.assert.throws(() => { + this.renderComponent(Bar); + }, /Expected a dynamic component definition, but received an object or function that did not have a component manager associated with it. The dynamic invocation was `` or `\{\{this.Foo\}\}`, and the incorrect definition is the value at the path `this.Foo`, which was:/u); + } + + @test + 'Can pass helper as argument and invoke dynamically'() { + const plusOne = defineSimpleHelper(() => 'Hello, world!'); + const Foo = defineComponent({}, '{{@value}}'); + const Bar = defineComponent({ plusOne, Foo }, ''); + + this.renderComponent(Bar); + this.assertHTML('Hello, world!'); + this.assertStableRerender(); + } + + @test + 'Can pass helper as argument and invoke dynamically (with args)'() { + const plusOne = defineSimpleHelper((value = 0) => value + 1); + const Foo = defineComponent({}, '{{@value 123}}'); + const Bar = defineComponent({ plusOne, Foo }, ''); + + this.renderComponent(Bar); + this.assertHTML('124'); + this.assertStableRerender(); + } + + @test + 'Can pass curried helper as argument and invoke dynamically'() { + const plusOne = defineSimpleHelper((value = 0) => value + 1); + const Foo = defineComponent({}, '{{@value}}'); + const Bar = defineComponent({ plusOne, Foo }, ''); + + this.renderComponent(Bar); + this.assertHTML('124'); + this.assertStableRerender(); + } + + @test + 'Can pass curried helper as argument and invoke dynamically (with args)'() { + const add = defineSimpleHelper((a: number, b: number) => a + b); + const Foo = defineComponent({}, '{{@value 2}}'); + const Bar = defineComponent({ add, Foo }, ''); + + this.renderComponent(Bar); + this.assertHTML('3'); + this.assertStableRerender(); + } + + @test + 'Passing a curried helper without a value is a no-op'() { + const Foo = defineComponent({}, '{{@value 2}}'); + const Bar = defineComponent({ Foo }, ''); + + this.renderComponent(Bar); + this.assertHTML(''); + this.assertStableRerender(); + } + + @test({ skip: !DEBUG }) + 'Throws an error if a non-helper is used as a helper'() { + const foo = defineComponent({}, 'Hello, world!'); + const Bar = defineComponent({}, '{{#if (this.foo)}}{{/if}}', { + definition: class extends GlimmerishComponent { + foo = foo; + }, + }); + + this.assert.throws(() => { + this.renderComponent(Bar); + }, /Expected a dynamic helper definition, but received an object or function that did not have a helper manager associated with it. The dynamic invocation was `\{\{this.foo\}\}` or `\(this.foo\)`, and the incorrect definition is the value at the path `this.foo`, which was:/u); + } +} + +class BuiltInsStrictModeTest extends RenderTest { + static suiteName = 'strict mode: built in modifiers and helpers'; + + @test + 'Can use hash'() { + let Foo = defineComponent( + { hash }, + '{{#let (hash value="Hello, world!") as |hash|}}{{hash.value}}{{/let}}' + ); + + this.renderComponent(Foo); + this.assertHTML('Hello, world!'); + this.assertStableRerender(); + } + + @test + 'Can use array'() { + let Foo = defineComponent( + { array }, + '{{#each (array "Hello, world!") as |value|}}{{value}}{{/each}}' + ); + + this.renderComponent(Foo); + this.assertHTML('Hello, world!'); + this.assertStableRerender(); + } + + @test + 'Can use concat'() { + let Foo = defineComponent({ concat }, '{{(concat "Hello" ", " "world!")}}'); + + this.renderComponent(Foo); + this.assertHTML('Hello, world!'); + this.assertStableRerender(); + } + + @test + 'Can use get'() { + let Foo = defineComponent( + { hash, get }, + '{{#let (hash value="Hello, world!") as |hash|}}{{(get hash "value")}}{{/let}}' + ); + + this.renderComponent(Foo); + this.assertHTML('Hello, world!'); + this.assertStableRerender(); + } + + @test + 'Can use on and fn'(assert: Assert) { + assert.expect(3); + + let handleClick = (value: number) => { + assert.strictEqual(value, 123, 'handler called with correct value'); + }; + + let Foo = defineComponent( + { on, fn, handleClick }, + '' + ); + + this.renderComponent(Foo); + + castToBrowser(this.element, 'div').querySelector('button')!.click(); + } +} + +jitSuite(GeneralStrictModeTest); +jitSuite(StaticStrictModeTest); +jitSuite(DynamicStrictModeTest); +jitSuite(BuiltInsStrictModeTest); diff --git a/packages/@glimmer-workspace/integration-tests/test/style-warnings-test.ts b/packages/@glimmer-workspace/integration-tests/test/style-warnings-test.ts new file mode 100644 index 00000000000..82029008e4e --- /dev/null +++ b/packages/@glimmer-workspace/integration-tests/test/style-warnings-test.ts @@ -0,0 +1,82 @@ +/* eslint-disable @typescript-eslint/no-extraneous-class */ +import type { GlobalContext } from '@glimmer/global-context'; +import { testOverrideGlobalContext } from '@glimmer/global-context'; +import { jitSuite, RenderTest, test } from '@glimmer-workspace/integration-tests'; + +import { assert } from './support'; +import { DEBUG } from '@glimmer/env'; + +let warnings = 0; +let originalContext: GlobalContext | null; + +class StyleWarningsTest extends RenderTest { + static suiteName = 'Style attributes'; + + beforeEach() { + warnings = 0; + originalContext = + testOverrideGlobalContext?.({ + warnIfStyleNotTrusted() { + warnings++; + }, + + getProp(obj, key) { + return (obj as Record)[key]; + }, + }) ?? null; + } + + afterEach() { + testOverrideGlobalContext?.(originalContext); + } + + @test + 'Standard element with static style and element modifier does not give you a warning'() { + this.registerModifier('foo', class {}); + this.render('', {}); + + assert.strictEqual(warnings, 0); + } + + @test({ skip: !DEBUG }) + 'Standard element with dynamic style and element modifier gives you 1 warning'() { + this.registerModifier('foo', class {}); + this.render('', { + dynAttr: 'display:flex', + }); + + assert.strictEqual(warnings, 1); + } + + @test + 'using a static inline style on an element does not give you a warning'() { + this.render(`
    Thing
    `, {}); + + assert.strictEqual(warnings, 0); + this.assertHTML('
    Thing
    ', 'initial render'); + } + + @test + 'triple curlies are trusted'() { + this.render(`
    Thing
    `, { + styles: 'background: red', + }); + + assert.strictEqual(warnings, 0); + this.assertHTML('
    Thing
    ', 'initial render'); + } + + @test + 'using a static inline style on an namespaced element does not give you a warning'() { + this.render(``, {}); + + assert.strictEqual(warnings, 0); + + this.assertHTML( + '', + 'initial render' + ); + } +} + +jitSuite(StyleWarningsTest); diff --git a/packages/@glimmer-workspace/integration-tests/test/support.ts b/packages/@glimmer-workspace/integration-tests/test/support.ts new file mode 100644 index 00000000000..ac26805e99d --- /dev/null +++ b/packages/@glimmer-workspace/integration-tests/test/support.ts @@ -0,0 +1,64 @@ +import { assign } from '@glimmer/util'; + +interface NestedHooks { + test: (name: string, callback: (assert: Assert) => void) => void; + + /** + * Runs after the last test. If additional tests are defined after the + * module's queue has emptied, it will not run this hook again. + */ + after: (fn: (assert: Assert) => void) => void; + + /** + * Runs after each test. + */ + afterEach: (fn: (assert: Assert) => void) => void; + + /** + * Runs before the first test. + */ + before: (fn: (assert: Assert) => void) => void; + + /** + * Runs before each test. + */ + beforeEach: (fn: (assert: Assert) => void) => void; +} + +type NestedCallback = (hooks: NestedHooks) => void; + +export function module(name: string, nested: (hooks: NestedHooks) => void): void; +export function module( + name: string, + setup: Partial, + nested: Partial | NestedCallback +): void; +export function module(name: string, second?: any, third?: any) { + let nested: NestedCallback; + let setup; + + if (arguments.length === 3) { + setup = second; + nested = third; + } else if (arguments.length === 2) { + if (typeof second === 'object') { + setup = second; + } else { + nested = second; + } + } + + return void QUnit.module(`integration - ${name}`, setup, (supplied) => { + nested(assign({}, supplied, { test: QUnit.test })); + }); +} + +export function test(name: string, callback: (assert: Assert) => void) { + return void QUnit.test(name, callback); +} + +export function todo(name: string, callback: (assert: Assert) => void) { + return (QUnit as any).todo(name, callback); +} + +export const assert = QUnit.assert; diff --git a/packages/@glimmer-workspace/integration-tests/test/syntax/argument-less-helper-paren-less-invoke-test.ts b/packages/@glimmer-workspace/integration-tests/test/syntax/argument-less-helper-paren-less-invoke-test.ts new file mode 100644 index 00000000000..18567ce5480 --- /dev/null +++ b/packages/@glimmer-workspace/integration-tests/test/syntax/argument-less-helper-paren-less-invoke-test.ts @@ -0,0 +1,102 @@ +import { + defineSimpleHelper, + jitSuite, + preprocess, + RenderTest, + syntaxErrorFor, + test, +} from '@glimmer-workspace/integration-tests'; + +class ArgumentLessHelperParenLessInvokeTest extends RenderTest { + static suiteName = 'argument-less helper paren-less invoke'; + + @test + 'invoking an argument-less helper without parens in named argument position is a syntax error'( + assert: Assert + ) { + assert.throws( + () => { + preprocess('', { + meta: { moduleName: 'test-module' }, + }); + }, + syntaxErrorFor( + 'You attempted to pass a path as argument (`@content={{foo}}`) but foo was not in scope. Try:\n' + + '* `@content={{this.foo}}` if this is meant to be a property lookup, or\n' + + '* `@content={{(foo)}}` if this is meant to invoke the resolved helper, or\n' + + '* `@content={{helper "foo"}}` if this is meant to pass the resolved helper by value', + `@content={{foo}}`, + 'test-module', + 1, + 5 + ) + ); + } + + @test + 'invoking an argument-less helper with parens in named argument position is not deprecated'() { + this.registerHelper('is-string', ([value]: readonly unknown[]) => typeof value === 'string'); + + this.registerHelper('foo', () => 'Hello, world!'); + this.registerComponent('TemplateOnly', 'Bar', '[{{is-string @content}}][{{@content}}]'); + + this.render(''); + this.assertHTML('[true][Hello, world!]'); + this.assertStableRerender(); + } + + @test + 'invoking an argument-less helper with quotes in named argument position is not deprecated'() { + this.registerHelper('is-string', ([value]: readonly unknown[]) => typeof value === 'string'); + + this.registerHelper('foo', () => 'Hello, world!'); + this.registerComponent('TemplateOnly', 'Bar', '[{{is-string @content}}][{{@content}}]'); + + this.render(''); + this.assertHTML('[true][Hello, world!]'); + this.assertStableRerender(); + } + + @test + 'passing a local helper in named argument position is not deprecated'() { + this.registerHelper('is-string', ([value]: readonly unknown[]) => typeof value === 'string'); + + const foo = defineSimpleHelper(() => 'Hello, world!'); + + this.registerComponent('TemplateOnly', 'Bar', '[{{is-string @content}}][{{@content}}]'); + + this.render('{{#let this.foo as |foo|}}{{/let}}', { foo }); + this.assertHTML('[false][Hello, world!]'); + this.assertStableRerender(); + } + + @test + 'invoking a local helper with parens in named argument position is not deprecated'() { + this.registerHelper('is-string', ([value]: readonly unknown[]) => typeof value === 'string'); + + const foo = defineSimpleHelper(() => 'Hello, world!'); + + this.registerComponent('TemplateOnly', 'Bar', '[{{is-string @content}}][{{@content}}]'); + + this.render('{{#let this.foo as |foo|}}{{/let}}', { foo }); + this.assertHTML('[true][Hello, world!]'); + this.assertStableRerender(); + } + + // TODO: this should work, but doesn't + + // @test + // 'invoking a helper with quotes in named argument position is not deprecated'() { + // this.registerHelper('is-string', ([value]: readonly unknown[]) => typeof value === 'string'); + + // const foo = defineSimpleHelper(() => 'Hello, world!'); + + // this.registerComponent('TemplateOnly', 'Bar', '[{{is-string @content}}][{{@content}}]'); + + // this.render('{{#let this.foo as |foo|}}{{/let}}', { foo }); + // this.assertHTML('[true][Hello, world!]'); + // this.assertStableRerender(); + // } +} + +jitSuite(ArgumentLessHelperParenLessInvokeTest); diff --git a/packages/@glimmer-workspace/integration-tests/test/syntax/general-errors-test.ts b/packages/@glimmer-workspace/integration-tests/test/syntax/general-errors-test.ts new file mode 100644 index 00000000000..71a4a918572 --- /dev/null +++ b/packages/@glimmer-workspace/integration-tests/test/syntax/general-errors-test.ts @@ -0,0 +1,320 @@ +import { + jitSuite, + preprocess, + RenderTest, + syntaxErrorFor, + test, +} from '@glimmer-workspace/integration-tests'; + +class SyntaxErrors extends RenderTest { + static suiteName = 'general syntax errors'; + + @test + 'context switching using ../ is not allowed'() { + this.assert.throws( + () => { + preprocess('

    {{../value}}

    ', { meta: { moduleName: 'test-module' } }); + }, + syntaxErrorFor( + 'Changing context using "../" is not supported in Glimmer', + '../value', + 'test-module', + 1, + 10 + ) + ); + } + + @test + 'mixing . and / is not allowed'() { + this.assert.throws( + () => { + preprocess('

    {{a/b.c}}

    ', { meta: { moduleName: 'test-module' } }); + }, + syntaxErrorFor( + "Mixing '.' and '/' in paths is not supported in Glimmer; use only '.' to separate property paths", + 'a/b.c', + 'test-module', + 1, + 10 + ) + ); + } + + @test + 'explicit self ref with ./ is not allowed'() { + this.assert.throws( + () => { + preprocess('

    {{./value}}

    ', { meta: { moduleName: 'test-module' } }); + }, + syntaxErrorFor( + 'Using "./" is not supported in Glimmer and unnecessary', + './value', + 'test-module', + 1, + 10 + ) + ); + } + + @test + 'Block params in HTML syntax - requires a space between as and pipes'() { + this.assert.throws( + () => { + preprocess('foo', { meta: { moduleName: 'test-module' } }); + }, + syntaxErrorFor( + 'Invalid block parameters syntax: expecting at least one space character between "as" and "|"', + 'as|', + 'test-module', + 1, + 7 + ) + ); + } + + @test + 'Block params in HTML syntax - Throws exception if given zero parameters'() { + this.assert.throws( + () => { + preprocess('foo', { meta: { moduleName: 'test-module' } }); + }, + syntaxErrorFor( + 'Invalid block parameters syntax: empty parameters list, expecting at least one identifier', + 'as ||', + 'test-module', + 1, + 7 + ) + ); + + this.assert.throws( + () => { + preprocess('foo', { meta: { moduleName: 'test-module' } }); + }, + syntaxErrorFor( + 'Invalid block parameters syntax: empty parameters list, expecting at least one identifier', + 'as | |', + 'test-module', + 1, + 7 + ) + ); + } + + @test + 'Block params in HTML syntax - invalid mustaches in block params list'() { + this.assert.throws( + () => { + preprocess('foo', { meta: { moduleName: 'test-module' } }); + }, + syntaxErrorFor( + 'Invalid block parameters syntax: mustaches cannot be used inside parameters list', + '{{foo}}', + 'test-module', + 1, + 11 + ) + ); + + this.assert.throws( + () => { + preprocess('foo', { meta: { moduleName: 'test-module' } }); + }, + syntaxErrorFor( + 'Invalid block parameters syntax: mustaches cannot be used inside parameters list', + '{{bar}}', + 'test-module', + 1, + 14 + ) + ); + + this.assert.throws( + () => { + preprocess('foo', { meta: { moduleName: 'test-module' } }); + }, + syntaxErrorFor( + 'Invalid block parameters syntax: mustaches cannot be used inside parameters list', + '{{bar}}', + 'test-module', + 1, + 15 + ) + ); + + this.assert.throws( + () => { + preprocess('foo', { meta: { moduleName: 'test-module' } }); + }, + syntaxErrorFor( + 'Invalid block parameters syntax: modifiers cannot follow parameters list', + '{{bar}}', + 'test-module', + 1, + 16 + ) + ); + } + + @test + 'Block params in HTML syntax - EOF in block params list'() { + this.assert.throws( + () => { + preprocess('" or "/>" after parameters list', + 'as |', + 'test-module', + 1, + 7 + ) + ); + + this.assert.throws( + () => { + preprocess('" or "/>" after parameters list', + 'as |foo', + 'test-module', + 1, + 7 + ) + ); + + this.assert.throws( + () => { + preprocess('" or "/>" after parameters list', + 'as |foo|', + 'test-module', + 1, + 7 + ) + ); + } + + @test + 'Block params in HTML syntax - Throws an error on invalid block params syntax'() { + this.assert.throws( + () => { + preprocess('{{x}},{{y}}', { meta: { moduleName: 'test-module' } }); + }, + syntaxErrorFor( + 'Invalid block parameters syntax: expecting "|" but the tag was closed prematurely', + 'as |x y>', + 'test-module', + 1, + 7 + ) + ); + + this.assert.throws( + () => { + preprocess('{{x}},{{y}}', { + meta: { moduleName: 'test-module' }, + }); + }, + syntaxErrorFor( + 'Invalid block parameters syntax: expecting the tag to be closed with ">" or "/>" after parameters list', + 'wat', + 'test-module', + 1, + 14 + ) + ); + + this.assert.throws( + () => { + preprocess('{{x}},{{y}}', { meta: { moduleName: 'test-module' } }); + }, + syntaxErrorFor( + 'Invalid block parameters syntax: expecting the tag to be closed with ">" or "/>" after parameters list', + 'y|', + 'test-module', + 1, + 14 + ) + ); + } + + @test + 'Block params in HTML syntax - Throws an error on invalid identifiers for params'() { + this.assert.throws( + () => { + preprocess('', { meta: { moduleName: 'test-module' } }); + }, + syntaxErrorFor( + 'Invalid block parameters syntax: invalid identifier name `foo.bar`', + 'foo.bar', + 'test-module', + 1, + 13 + ) + ); + + this.assert.throws( + () => { + preprocess('', { meta: { moduleName: 'test-module' } }); + }, + syntaxErrorFor( + 'Invalid block parameters syntax: invalid identifier name `"foo"`', + '"foo"', + 'test-module', + 1, + 13 + ) + ); + + this.assert.throws( + () => { + preprocess('', { meta: { moduleName: 'test-module' } }); + }, + syntaxErrorFor( + 'Invalid block parameters syntax: invalid identifier name `foo[bar]`', + 'foo[bar]', + 'test-module', + 1, + 11 + ) + ); + } + + @test + 'Block params in HTML syntax - Throws an error on missing `as`'() { + this.assert.throws( + () => { + preprocess('', { meta: { moduleName: 'test-module' } }); + }, + syntaxErrorFor( + 'Invalid block parameters syntax: block parameters must be preceded by the `as` keyword', + '|x|', + 'test-module', + 1, + 7 + ) + ); + + this.assert.throws( + () => { + preprocess('<:baz |x|>', { + meta: { moduleName: 'test-module' }, + }); + }, + syntaxErrorFor( + 'Invalid block parameters syntax: block parameters must be preceded by the `as` keyword', + '|x|', + 'test-module', + 1, + 13 + ) + ); + } +} + +jitSuite(SyntaxErrors); diff --git a/packages/@glimmer-workspace/integration-tests/test/syntax/if-unless-test.ts b/packages/@glimmer-workspace/integration-tests/test/syntax/if-unless-test.ts new file mode 100644 index 00000000000..ee0dfd6ebcf --- /dev/null +++ b/packages/@glimmer-workspace/integration-tests/test/syntax/if-unless-test.ts @@ -0,0 +1,219 @@ +import { + jitSuite, + preprocess, + RenderTest, + syntaxErrorFor, + test, +} from '@glimmer-workspace/integration-tests'; + +const types = ['if', 'unless']; + +for (const type of types) { + class SyntaxErrors extends RenderTest { + static suiteName = `if/unless (${type}) keyword syntax errors`; + + @test + '{{#${type}}} throws if it received named args'() { + this.assert.throws( + () => { + preprocess(`{{#${type} condition=true}}{{/${type}}}`, { + meta: { moduleName: 'test-module' }, + }); + }, + syntaxErrorFor( + `{{#${type}}} cannot receive named parameters, received condition`, + `{{#${type} condition=true}}{{/${type}}}`, + 'test-module', + 1, + 0 + ) + ); + } + + @test + '{{#${type}}} throws if it received no positional params'() { + this.assert.throws( + () => { + preprocess(`{{#${type}}}{{/${type}}}`, { meta: { moduleName: 'test-module' } }); + }, + syntaxErrorFor( + `{{#${type}}} requires a condition as its first positional parameter, did not receive any parameters`, + `{{#${type}}}{{/${type}}}`, + 'test-module', + 1, + 0 + ) + ); + } + + @test + '{{#${type}}} throws if it received more than one positional param'() { + this.assert.throws( + () => { + preprocess(`{{#${type} true false}}{{/${type}}}`, { + meta: { moduleName: 'test-module' }, + }); + }, + syntaxErrorFor( + `{{#${type}}} can only receive one positional parameter in block form, the conditional value. Received 2 parameters`, + `{{#${type} true false}}{{/${type}}}`, + 'test-module', + 1, + 0 + ) + ); + } + + @test + '{{${type}}} throws if it received named args'() { + this.assert.throws( + () => { + preprocess(`{{${type} condition=true}}`, { + meta: { moduleName: 'test-module' }, + }); + }, + syntaxErrorFor( + `(${type}) cannot receive named parameters, received condition`, + `{{${type} condition=true}}`, + 'test-module', + 1, + 0 + ) + ); + } + + @test + '{{${type}}} throws if it received no positional params'() { + this.assert.throws( + () => { + preprocess(`{{${type}}}`, { meta: { moduleName: 'test-module' } }); + }, + syntaxErrorFor( + `When used inline, (${type}) requires at least two parameters 1. the condition that determines the state of the (${type}), and 2. the value to return if the condition is ${ + type === 'if' ? 'true' : 'false' + }. Did not receive any parameters`, + `{{${type}}}`, + 'test-module', + 1, + 0 + ) + ); + } + + @test + '{{${type}}} throws if it received only one positional param'() { + this.assert.throws( + () => { + preprocess(`{{${type} true}}`, { meta: { moduleName: 'test-module' } }); + }, + syntaxErrorFor( + `When used inline, (${type}) requires at least two parameters 1. the condition that determines the state of the (${type}), and 2. the value to return if the condition is ${ + type === 'if' ? 'true' : 'false' + }. Received only one parameter, the condition`, + `{{${type} true}}`, + 'test-module', + 1, + 0 + ) + ); + } + + @test + '{{${type}}} throws if it received more than 3 positional params'() { + this.assert.throws( + () => { + preprocess(`{{${type} true false true false}}`, { meta: { moduleName: 'test-module' } }); + }, + syntaxErrorFor( + `When used inline, (${type}) can receive a maximum of three positional parameters 1. the condition that determines the state of the (${type}), 2. the value to return if the condition is ${ + type === 'if' ? 'true' : 'false' + }, and 3. the value to return if the condition is ${ + type === 'if' ? 'false' : 'true' + }. Received 4 parameters`, + `{{${type} true false true false}}`, + 'test-module', + 1, + 0 + ) + ); + } + + @test + '(${type}) throws if it received named args'() { + this.assert.throws( + () => { + preprocess(`{{foo (${type} condition=true)}}`, { + meta: { moduleName: 'test-module' }, + }); + }, + syntaxErrorFor( + `(${type}) cannot receive named parameters, received condition`, + `(${type} condition=true)`, + 'test-module', + 1, + 6 + ) + ); + } + + @test + '(${type}) throws if it received no positional params'() { + this.assert.throws( + () => { + preprocess(`{{foo (${type})}}`, { meta: { moduleName: 'test-module' } }); + }, + syntaxErrorFor( + `When used inline, (${type}) requires at least two parameters 1. the condition that determines the state of the (${type}), and 2. the value to return if the condition is ${ + type === 'if' ? 'true' : 'false' + }. Did not receive any parameters`, + `(${type})`, + 'test-module', + 1, + 6 + ) + ); + } + + @test + '(${type}) throws if it received only one positional param'() { + this.assert.throws( + () => { + preprocess(`{{foo (${type} true)}}`, { meta: { moduleName: 'test-module' } }); + }, + syntaxErrorFor( + `When used inline, (${type}) requires at least two parameters 1. the condition that determines the state of the (${type}), and 2. the value to return if the condition is ${ + type === 'if' ? 'true' : 'false' + }. Received only one parameter, the condition`, + `(${type} true)`, + 'test-module', + 1, + 6 + ) + ); + } + + @test + '(${type}) throws if it received more than 3 positional params'() { + this.assert.throws( + () => { + preprocess(`{{foo (${type} true false true false)}}`, { + meta: { moduleName: 'test-module' }, + }); + }, + syntaxErrorFor( + `When used inline, (${type}) can receive a maximum of three positional parameters 1. the condition that determines the state of the (${type}), 2. the value to return if the condition is ${ + type === 'if' ? 'true' : 'false' + }, and 3. the value to return if the condition is ${ + type === 'if' ? 'false' : 'true' + }. Received 4 parameters`, + `(${type} true false true false)`, + 'test-module', + 1, + 6 + ) + ); + } + } + + jitSuite(SyntaxErrors); +} diff --git a/packages/@glimmer-workspace/integration-tests/test/syntax/keyword-errors-test.ts b/packages/@glimmer-workspace/integration-tests/test/syntax/keyword-errors-test.ts new file mode 100644 index 00000000000..682a2f35f91 --- /dev/null +++ b/packages/@glimmer-workspace/integration-tests/test/syntax/keyword-errors-test.ts @@ -0,0 +1,214 @@ +import type { KeywordType } from '@glimmer/syntax'; +import { KEYWORDS_TYPES } from '@glimmer/syntax'; +import { jitSuite, preprocess, RenderTest, test } from '@glimmer-workspace/integration-tests'; + +type KeywordName = keyof typeof KEYWORDS_TYPES; +const TYPES: Record = KEYWORDS_TYPES; +const KEYWORDS = Object.keys(KEYWORDS_TYPES) as KeywordName[]; + +const BLOCK_KEYWORDS = KEYWORDS.filter((key) => TYPES[key].includes('Block')); +const APPEND_KEYWORDS = KEYWORDS.filter((key) => TYPES[key].includes('Append')); +const CALL_KEYWORDS = KEYWORDS.filter((key) => TYPES[key].includes('Call')); +const MODIFIER_KEYWORDS = KEYWORDS.filter((key) => TYPES[key].includes('Modifier')); + +for (const keyword of KEYWORDS) { + class KeywordSyntaxErrors extends RenderTest { + static suiteName = `\`${keyword}\` keyword syntax errors`; + + @test + 'keyword can be used as a value in non-strict mode'() { + preprocess(`{{some-helper ${keyword}}}`, { meta: { moduleName: 'test-module' } }); + } + + @test + 'keyword can be used as a value in strict mode'() { + preprocess(`{{some-helper ${keyword}}}`, { + strictMode: true, + locals: ['some-helper', keyword], + meta: { moduleName: 'test-module' }, + }); + } + + @test + 'keyword can be yielded as a parameter in other keywords in non-strict mode'() { + preprocess( + ` + {{#let this.value as |${keyword}|}} + {{some-helper ${keyword}}} + {{/let}} + `, + { meta: { moduleName: 'test-module' } } + ); + } + + @test + 'keyword can be yielded as a parameter in other keywords in strict mode'() { + preprocess( + ` + {{#let this.value as |${keyword}|}} + {{some-helper ${keyword}}} + {{/let}} + `, + { strictMode: true, locals: ['some-helper'], meta: { moduleName: 'test-module' } } + ); + } + + @test + 'keyword can be yielded as a parameter in curly invocation in non-strict mode'() { + preprocess( + ` + {{#my-component this.value as |${keyword}|}} + {{some-helper ${keyword}}} + {{/my-component}} + `, + { meta: { moduleName: 'test-module' } } + ); + } + + @test + 'keyword can be yielded as a parameter in curly invocation in strict mode'() { + preprocess( + ` + {{#my-component this.value as |${keyword}|}} + {{some-helper ${keyword}}} + {{/my-component}} + `, + { + strictMode: true, + locals: ['my-component', 'some-helper'], + meta: { moduleName: 'test-module' }, + } + ); + } + + @test + 'keyword can be yielded as a parameter in component blocks in non-strict mode'() { + preprocess( + ` + + {{some-helper ${keyword}}} + + `, + { meta: { moduleName: 'test-module' } } + ); + } + + @test + 'keyword can be yielded as a parameter in component blocks in strict mode'() { + preprocess( + ` + + {{some-helper ${keyword}}} + + `, + { + strictMode: true, + locals: ['SomeComponent', 'some-helper'], + meta: { moduleName: 'test-module' }, + } + ); + } + + @test + 'keyword can be yielded as a parameter in component named blocks in non-strict mode'() { + preprocess( + ` + + <:main as |${keyword}|> + {{some-helper ${keyword}}} + + + `, + { meta: { moduleName: 'test-module' } } + ); + } + + @test + 'keyword can be yielded as a parameter in component named blocks in strict mode'() { + preprocess( + ` + + <:main as |${keyword}|> + {{some-helper ${keyword}}} + + + `, + { + strictMode: true, + locals: ['SomeComponent', 'some-helper'], + meta: { moduleName: 'test-module' }, + } + ); + } + + @test + 'non-block keywords cannot be used as blocks'() { + if (BLOCK_KEYWORDS.indexOf(keyword) !== -1) { + return; + } + + this.assert.throws( + () => { + preprocess(`{{#${keyword}}}{{/${keyword}}}`, { meta: { moduleName: 'test-module' } }); + }, + new RegExp( + `The \`${keyword}\` keyword was used incorrectly. It was used as a block statement, but its valid usages are:`, + 'u' + ) + ); + } + + @test + 'non-append keywords cannot be used as appends'() { + if (APPEND_KEYWORDS.indexOf(keyword) !== -1) { + return; + } + + this.assert.throws( + () => { + preprocess(`{{${keyword}}}`, { meta: { moduleName: 'test-module' } }); + }, + new RegExp( + `The \`${keyword}\` keyword was used incorrectly. It was used as an append statement, but its valid usages are:`, + 'u' + ) + ); + } + + @test + 'non-expr keywords cannot be used as expr'() { + if (CALL_KEYWORDS.indexOf(keyword) !== -1) { + return; + } + + this.assert.throws( + () => { + preprocess(`{{some-helper (${keyword})}}`, { meta: { moduleName: 'test-module' } }); + }, + new RegExp( + `The \`${keyword}\` keyword was used incorrectly. It was used as a call expression, but its valid usages are:`, + 'u' + ) + ); + } + + @test + 'non-modifier keywords cannot be used as modifier'() { + if (MODIFIER_KEYWORDS.indexOf(keyword) !== -1) { + return; + } + + this.assert.throws( + () => { + preprocess(`
    `, { meta: { moduleName: 'test-module' } }); + }, + new RegExp( + `The \`${keyword}\` keyword was used incorrectly. It was used as a modifier, but its valid usages are:`, + 'u' + ) + ); + } + } + + jitSuite(KeywordSyntaxErrors); +} diff --git a/packages/@glimmer-workspace/integration-tests/test/syntax/named-blocks-test.ts b/packages/@glimmer-workspace/integration-tests/test/syntax/named-blocks-test.ts new file mode 100644 index 00000000000..a860a260fc8 --- /dev/null +++ b/packages/@glimmer-workspace/integration-tests/test/syntax/named-blocks-test.ts @@ -0,0 +1,246 @@ +import { + jitSuite, + preprocess, + RenderTest, + syntaxErrorFor, + test, +} from '@glimmer-workspace/integration-tests'; + +class NamedBlocksSyntaxErrors extends RenderTest { + static suiteName = 'named blocks syntax errors'; + + @test + 'Defining block params on a component which has named blocks'() { + this.assert.throws( + () => { + preprocess('<:foo>', { meta: { moduleName: 'test-module' } }); + }, + syntaxErrorFor( + 'Unexpected block params list on component invocation: when passing named blocks, the invocation tag cannot take block params', + '<:foo>', + 'test-module', + 1, + 0 + ) + ); + } + + @test + 'Defining named blocks on a plain element is not allowed'() { + this.assert.throws( + () => { + preprocess('
    <:foo>
    ', { meta: { moduleName: 'test-module' } }); + }, + syntaxErrorFor( + 'Unexpected named block <:foo> inside
    HTML element', + '
    <:foo>
    ', + 'test-module', + 1, + 0 + ) + ); + } + + @test + 'Defining top level named blocks is not allowed'() { + this.assert.throws( + () => { + preprocess('<:foo>', { meta: { moduleName: 'test-module' } }); + }, + syntaxErrorFor( + 'Unexpected named block at the top-level of a template', + '<:foo>', + 'test-module', + 1, + 0 + ) + ); + + this.assert.throws( + () => { + preprocess('{{#if}}<:foo>{{/if}}', { meta: { moduleName: 'test-module' } }); + }, + syntaxErrorFor( + 'Unexpected named block nested in a normal block', + '<:foo>', + 'test-module', + 1, + 7 + ) + ); + } + + @test + 'Passing multiple of the same named block throws an error'() { + this.assert.throws( + () => { + preprocess('<:foo><:foo>', { + meta: { moduleName: 'test-module' }, + }); + }, + syntaxErrorFor( + 'Component had two named blocks with the same name, `<:foo>`. Only one block with a given name may be passed', + '<:foo><:foo>', + 'test-module', + 1, + 0 + ) + ); + } + + @test + 'Throws an error if both inverse and else named blocks are passed, inverse first'() { + this.assert.throws( + () => { + preprocess('<:inverse><:else>', { + meta: { moduleName: 'test-module' }, + }); + }, + syntaxErrorFor( + 'Component has both <:else> and <:inverse> block. <:inverse> is an alias for <:else>', + '<:inverse><:else>', + 'test-module', + 1, + 0 + ) + ); + } + + @test + 'Throws an error if both inverse and else named blocks are passed, else first'() { + this.assert.throws( + () => { + preprocess('<:else><:inverse>', { + meta: { moduleName: 'test-module' }, + }); + }, + syntaxErrorFor( + 'Component has both <:else> and <:inverse> block. <:inverse> is an alias for <:else>', + '<:else><:inverse>', + 'test-module', + 1, + 0 + ) + ); + } + + @test + 'Throws an error if there is content outside of the blocks'() { + this.assert.throws( + () => { + preprocess('Hello!<:foo>', { meta: { moduleName: 'test-module' } }); + }, + syntaxErrorFor( + 'Unexpected content inside component invocation: when using named blocks, the tag cannot contain other content', + 'Hello!<:foo>', + 'test-module', + 1, + 0 + ) + ); + + this.assert.throws( + () => { + preprocess('<:foo>Hello!', { meta: { moduleName: 'test-module' } }); + }, + syntaxErrorFor( + 'Unexpected content inside component invocation: when using named blocks, the tag cannot contain other content', + '<:foo>Hello!', + 'test-module', + 1, + 0 + ) + ); + } + + @test + 'Cannot pass self closing named block'() { + this.assert.throws( + () => { + preprocess('<:foo/>', { meta: { moduleName: 'test-module' } }); + }, + syntaxErrorFor( + '<:foo/> is not a valid named block: named blocks cannot be self-closing', + '<:foo/>', + 'test-module', + 1, + 5 + ) + ); + } + + @test + 'Named blocks must start with a lower case letter'() { + this.assert.throws( + () => { + preprocess('<:Bar>', { meta: { moduleName: 'test-module' } }); + }, + syntaxErrorFor( + '<:Bar> is not a valid named block, and named blocks must begin with a lowercase letter', + '<:Bar>', + 'test-module', + 1, + 5 + ) + ); + + this.assert.throws( + () => { + preprocess('<:1bar><:/1bar>', { meta: { moduleName: 'test-module' } }); + }, + syntaxErrorFor( + 'Invalid named block named detected, you may have created a named block without a name, or you may have began your name with a number. Named blocks must have names that are at least one character long, and begin with a lower case letter', + '<:/1bar>', + 'test-module', + 1, + 12 + ) + ); + } + + @test + 'Named blocks cannot have arguments, attributes, or modifiers'() { + this.assert.throws( + () => { + preprocess('<:bar attr="baz">', { meta: { moduleName: 'test-module' } }); + }, + syntaxErrorFor( + 'named block <:bar> cannot have attributes, arguments, or modifiers', + '<:bar attr="baz">', + 'test-module', + 1, + 5 + ) + ); + + this.assert.throws( + () => { + preprocess('<:bar @arg="baz">', { meta: { moduleName: 'test-module' } }); + }, + syntaxErrorFor( + 'named block <:bar> cannot have attributes, arguments, or modifiers', + '<:bar @arg="baz">', + 'test-module', + 1, + 5 + ) + ); + + this.assert.throws( + () => { + preprocess('<:bar {{modifier}}>', { + meta: { moduleName: 'test-module' }, + }); + }, + syntaxErrorFor( + 'named block <:bar> cannot have attributes, arguments, or modifiers', + '<:bar {{modifier}}>', + 'test-module', + 1, + 5 + ) + ); + } +} + +jitSuite(NamedBlocksSyntaxErrors); diff --git a/packages/@glimmer-workspace/integration-tests/test/syntax/yield-keywords-test.ts b/packages/@glimmer-workspace/integration-tests/test/syntax/yield-keywords-test.ts new file mode 100644 index 00000000000..bd50f336485 --- /dev/null +++ b/packages/@glimmer-workspace/integration-tests/test/syntax/yield-keywords-test.ts @@ -0,0 +1,141 @@ +import { + jitSuite, + preprocess, + RenderTest, + syntaxErrorFor, + test, +} from '@glimmer-workspace/integration-tests'; + +class NamedBlocksSyntaxErrors extends RenderTest { + static suiteName = 'yield keywords syntax errors'; + + @test + 'yield throws if receiving any named args besides `to`'() { + this.assert.throws( + () => { + preprocess('{{yield foo="bar"}}', { meta: { moduleName: 'test-module' } }); + }, + syntaxErrorFor( + "yield only takes a single named argument: 'to'", + 'foo="bar"', + 'test-module', + 1, + 8 + ) + ); + } + + @test + 'you can only yield to a literal string value'() { + this.assert.throws( + () => { + preprocess('{{yield to=this.bar}}', { meta: { moduleName: 'test-module' } }); + }, + syntaxErrorFor( + 'you can only yield to a literal string value', + 'this.bar', + 'test-module', + 1, + 11 + ) + ); + } + + @test + 'has-block throws if receiving any named args'() { + this.assert.throws( + () => { + preprocess('{{has-block foo="bar"}}', { meta: { moduleName: 'test-module' } }); + }, + syntaxErrorFor( + '(has-block) does not take any named arguments', + '{{has-block foo="bar"}}', + 'test-module', + 1, + 0 + ) + ); + } + + @test + 'has-block throws if receiving multiple positional'() { + this.assert.throws( + () => { + preprocess('{{has-block "foo" "bar"}}', { meta: { moduleName: 'test-module' } }); + }, + syntaxErrorFor( + '(has-block) only takes a single positional argument', + '{{has-block "foo" "bar"}}', + 'test-module', + 1, + 0 + ) + ); + } + + @test + 'has-block throws if receiving a value besides a string'() { + this.assert.throws( + () => { + preprocess('{{has-block this.bar}}', { meta: { moduleName: 'test-module' } }); + }, + syntaxErrorFor( + '(has-block) can only receive a string literal as its first argument', + '{{has-block this.bar}}', + 'test-module', + 1, + 0 + ) + ); + } + + @test + 'has-block-params throws if receiving any named args'() { + this.assert.throws( + () => { + preprocess('{{has-block-params foo="bar"}}', { meta: { moduleName: 'test-module' } }); + }, + syntaxErrorFor( + '(has-block-params) does not take any named arguments', + '{{has-block-params foo="bar"}}', + 'test-module', + 1, + 0 + ) + ); + } + + @test + 'has-block-params throws if receiving multiple positional'() { + this.assert.throws( + () => { + preprocess('{{has-block-params "foo" "bar"}}', { meta: { moduleName: 'test-module' } }); + }, + syntaxErrorFor( + '(has-block-params) only takes a single positional argument', + '{{has-block-params "foo" "bar"}}', + 'test-module', + 1, + 0 + ) + ); + } + + @test + 'has-block-params throws if receiving a value besides a string'() { + this.assert.throws( + () => { + preprocess('{{has-block-params this.bar}}', { meta: { moduleName: 'test-module' } }); + }, + syntaxErrorFor( + '(has-block-params) can only receive a string literal as its first argument', + '{{has-block-params this.bar}}', + 'test-module', + 1, + 0 + ) + ); + } +} + +jitSuite(NamedBlocksSyntaxErrors); diff --git a/packages/@glimmer-workspace/integration-tests/test/updating-content-matrix-test.ts b/packages/@glimmer-workspace/integration-tests/test/updating-content-matrix-test.ts new file mode 100644 index 00000000000..3ba8dbfd928 --- /dev/null +++ b/packages/@glimmer-workspace/integration-tests/test/updating-content-matrix-test.ts @@ -0,0 +1,388 @@ +import type { SimpleElement, SimpleNode } from '@glimmer/interfaces'; +import type { SafeString } from '@glimmer/runtime'; +import type { RenderDelegate, RenderTestConstructor } from '@glimmer-workspace/integration-tests'; +import { NS_SVG } from '@glimmer/constants'; +import { jitSuite, RenderTest } from '@glimmer-workspace/integration-tests'; + +function makeSafeString(value: string): SafeString { + return new SafeStringImpl(value); +} + +class SafeStringImpl implements SafeString { + constructor(private string: string) {} + toHTML() { + return this.string; + } + toString() { + return this.string; + } +} + +class ContentTest extends RenderTest { + static suiteName = 'Updating - Content'; + + makeElement(tag: string, content: string): SimpleElement { + const el = this.delegate.createElement(tag); + el.appendChild(this.delegate.createTextNode(content)); + return el; + } + + makeSVGElement(tag: string, content: string): SimpleElement { + const el = this.delegate.createElementNS(NS_SVG, tag); + el.appendChild(this.delegate.createTextNode(content)); + return el; + } + + makeFragment(nodes: SimpleNode[]) { + const frag = this.delegate.createDocumentFragment(); + nodes.forEach((node) => frag.appendChild(node)); + return frag; + } +} + +// Test cases to matrix: +// const helper returns const SafeString +// non-const +// safe string +// unsafe string +// swapping between safe and unsafe +// swapping between unsafe and safe + +type ContentValue = + | string + | SafeString + | null + | undefined + | number + | boolean + | Element + | DocumentFragment; + +interface ContentTestCase { + name: string; + template: string; + values: Array<{ + input: + | ContentValue + | ((context: ContentTest, isHTML: boolean) => ContentValue) + | { toString(): string }; + expected: string | ((context: ContentTest, isHTML: boolean) => string); + description: string; + }>; +} + +function generateContentTestCase( + suite: RenderTestConstructor, + tc: ContentTestCase +): void { + [ + { + name: 'HTML context, as the only child', + isHTML: true, + before: '
    ', + after: '
    ', + }, + { + name: 'HTML context, as a sibling to adjecent text nodes', + isHTML: true, + before: '
    before', + after: 'after
    ', + }, + { + name: 'HTML context, as a sibling to adjecent elements', + isHTML: true, + before: '
    before', + after: 'after
    ', + }, + { + name: 'SVG foreignObject context, as the only child', + isHTML: true, + before: '', + after: '', + }, + { + name: 'SVG foreignObject context, as a sibling to adjecent text nodes', + isHTML: true, + before: 'before', + after: 'after', + }, + { + name: 'SVG foreignObject context, as a sibling to adjecent elements', + isHTML: true, + before: 'before', + after: 'after', + }, + { + name: 'SVG context, as the only child', + isHTML: false, + before: '', + after: '', + }, + { + name: 'SVG context, as a sibling to adjecent text nodes', + isHTML: false, + before: 'before', + after: 'after', + }, + { + name: 'SVG context, as a sibling to adjecent elements', + isHTML: false, + before: 'before', + after: 'after', + }, + ].forEach((wrapper) => { + const test = function (this: ContentTest) { + const template = wrapper.before + tc.template + wrapper.after; + tc.values.forEach(({ input: _input, expected: _expected, description }, index) => { + let input: unknown; + let expected: string; + + if (typeof _input === 'function') { + input = _input(this, wrapper.isHTML); + } else { + input = _input; + } + + if (typeof _expected === 'function') { + expected = _expected(this, wrapper.isHTML); + } else { + expected = _expected; + } + + if (index === 0) { + this.render(template, { value: input }); + this.assertHTML( + wrapper.before + expected + wrapper.after, + `expected initial render (${description})` + ); + } else { + this.rerender({ value: input }); + this.assertHTML( + wrapper.before + expected + wrapper.after, + `expected updated render (${description})` + ); + } + }); + }; + + (test as any).isTest = true; + (suite as any).prototype[`updating ${tc.name} produces expected result in ${wrapper.name}`] = + test; + }); +} + +generateContentTestCase(ContentTest, { + name: 'double curlies', + template: '{{this.value}}', + values: [ + { + input: 'hello', + expected: 'hello', + description: 'plain string', + }, + { + input: 'hello', + expected: '<b>hello</b>', + description: 'string containing HTML', + }, + { + input: null, + expected: '', + description: 'null literal', + }, + { + input: undefined, + expected: '', + description: 'undefined literal', + }, + { + input: '', + expected: '', + description: 'empty string', + }, + { + input: ' ', + expected: ' ', + description: 'blank string', + }, + { + input: (_test, isHTML) => makeSafeString(isHTML ? 'hello' : 'hello'), + expected: (_test, isHTML) => (isHTML ? 'hello' : 'hello'), + description: 'safe string containing HTML', + }, + { + input: makeSafeString(''), + expected: '', + description: 'empty safe string', + }, + { + input: makeSafeString(' '), + expected: ' ', + description: 'blank safe string', + }, + { + input: (test, isHTML) => + isHTML ? test.makeElement('p', 'hello') : test.makeSVGElement('text', 'hello'), + expected: (_test, isHTML) => (isHTML ? '

    hello

    ' : 'hello'), + description: 'DOM node containing an element with text', + }, + { + input: (test, isHTML) => { + if (isHTML) { + return test.makeFragment([test.makeElement('p', 'one'), test.makeElement('p', 'two')]); + } else { + return test.makeFragment([ + test.makeSVGElement('text', 'one'), + test.makeSVGElement('text', 'two'), + ]); + } + }, + expected: (_test, isHTML) => + isHTML ? '

    one

    two

    ' : 'onetwo', + description: 'DOM fragment containing multiple nodes', + }, + { + input: 'not modified', + expected: 'not modified', + description: 'plain string (not modified, first render)', + }, + { + input: 'not modified', + expected: 'not modified', + description: 'plain string (not modified, second render)', + }, + { + input: 0, + expected: '0', + description: 'number literal (0)', + }, + { + input: true, + expected: 'true', + description: 'boolean literal (true)', + }, + { + input: { + toString() { + return 'I am an Object'; + }, + }, + expected: 'I am an Object', + description: 'object with a toString function', + }, + { + input: 'hello', + expected: 'hello', + description: 'reset', + }, + ], +}); + +generateContentTestCase(ContentTest, { + name: 'triple curlies', + template: '{{{this.value}}}', + values: [ + { + input: 'hello', + expected: 'hello', + description: 'plain string', + }, + { + input: (_test, isHTML) => (isHTML ? 'hello' : 'hello'), + expected: (_test, isHTML) => (isHTML ? 'hello' : 'hello'), + description: 'string containing HTML', + }, + { + input: null, + expected: '', + description: 'null literal', + }, + { + input: undefined, + expected: '', + description: 'undefined literal', + }, + { + input: '', + expected: '', + description: 'empty string', + }, + { + input: ' ', + expected: ' ', + description: 'blank string', + }, + { + input: (_test, isHTML) => makeSafeString(isHTML ? 'hello' : 'hello'), + expected: (_test, isHTML) => (isHTML ? 'hello' : 'hello'), + description: 'safe string containing HTML', + }, + { + input: makeSafeString(''), + expected: '', + description: 'empty safe string', + }, + { + input: makeSafeString(' '), + expected: ' ', + description: 'blank safe string', + }, + { + input: (test, isHTML) => + isHTML ? test.makeElement('p', 'hello') : test.makeSVGElement('text', 'hello'), + expected: (_test, isHTML) => (isHTML ? '

    hello

    ' : 'hello'), + description: 'DOM node containing an element with text', + }, + { + input: (test, isHTML) => { + if (isHTML) { + return test.makeFragment([test.makeElement('p', 'one'), test.makeElement('p', 'two')]); + } else { + return test.makeFragment([ + test.makeSVGElement('text', 'one'), + test.makeSVGElement('text', 'two'), + ]); + } + }, + expected: (_test, isHTML) => + isHTML ? '

    one

    two

    ' : 'onetwo', + description: 'DOM fragment containing multiple nodes', + }, + { + input: 'not modified', + expected: 'not modified', + description: 'plain string (not modified, first render)', + }, + { + input: 'not modified', + expected: 'not modified', + description: 'plain string (not modified, second render)', + }, + { + input: 0, + expected: '0', + description: 'number literal (0)', + }, + { + input: true, + expected: 'true', + description: 'boolean literal (true)', + }, + { + input: { + toString() { + return 'I am an Object'; + }, + }, + expected: 'I am an Object', + description: 'object with a toString function', + }, + { + input: 'hello', + expected: 'hello', + description: 'reset', + }, + ], +}); + +jitSuite(ContentTest); diff --git a/packages/@glimmer-workspace/integration-tests/test/updating-modifiers-test.ts b/packages/@glimmer-workspace/integration-tests/test/updating-modifiers-test.ts new file mode 100644 index 00000000000..d0cfdb0a87c --- /dev/null +++ b/packages/@glimmer-workspace/integration-tests/test/updating-modifiers-test.ts @@ -0,0 +1,106 @@ +import type { SimpleElement } from '@glimmer/interfaces'; +import { jitSuite, RenderTest, test } from '@glimmer-workspace/integration-tests'; + +import { assert } from './support'; + +function makeSyncDataAttrModifier(hooks: string[]) { + return class SyncDataAttrModifier { + declare element: SimpleElement; + didInsertElement([param]: string[]) { + this.element.setAttribute('data-modifier', `installed - ${param}`); + hooks.push('didInsertElement'); + } + + didUpdate([param]: string[]) { + this.element.setAttribute('data-modifier', `updated - ${param}`); + hooks.push('didUpdate'); + } + + willDestroyElement() { + hooks.push('willDestroyElement'); + } + }; +} + +class UpdatingModifiers extends RenderTest { + static suiteName = 'Updating Element Modifier'; + + @test + 'Updating a element modifier'() { + let hooks: string[] = []; + + this.registerModifier('foo', makeSyncDataAttrModifier(hooks)); + + this.render('
    ', { + bar: 'Super Metroid', + }); + + this.assertHTML( + '
    ', + 'initial render' + ); + assert.deepEqual(hooks, ['didInsertElement'], 'hooks fired correctly on initial render'); + + this.rerender(); + + this.assertHTML( + '
    ', + 'modifier updated' + ); + assert.deepEqual(hooks, ['didInsertElement'], 'hooks not fired on rerender without changes'); + + this.rerender({ bar: 'Super Mario' }); + this.assertHTML('
    ', 'no change'); + assert.deepEqual(hooks, ['didInsertElement', 'didUpdate'], 'hooks fired correctly on rerender'); + } + + @test + "Const input doesn't trigger update in a element modifier"() { + let hooks: string[] = []; + + this.registerModifier('foo', makeSyncDataAttrModifier(hooks)); + + this.render('
    ', {}); + this.assertHTML('
    ', 'initial render'); + assert.deepEqual(hooks, ['didInsertElement'], 'hooks fired correctly on initial render'); + + this.rerender(); + + this.assertHTML('
    ', 'no change'); + assert.deepEqual(hooks, ['didInsertElement'], 'hooks fired correctly on update'); + } + + @test + 'Destructor is triggered on element modifiers'() { + let hooks: string[] = []; + + this.registerModifier('foo', makeSyncDataAttrModifier(hooks)); + + this.render('{{#if this.bar}}
    {{else}}
    {{/if}}', { + bar: true, + }); + + this.assertHTML('
    ', 'initial render'); + assert.deepEqual(hooks, ['didInsertElement'], 'hooks fired correctly on initial render'); + + this.rerender({ bar: false }); + + this.assertHTML('
    ', 'no more modifier'); + assert.deepEqual( + hooks, + ['didInsertElement', 'willDestroyElement'], + 'hooks fired correctly on rerender' + ); + + this.rerender({ bar: true }); + + this.assertHTML('
    ', 'back to default render'); + assert.deepEqual( + hooks, + ['didInsertElement', 'willDestroyElement', 'didInsertElement'], + 'hooks fired correctly on rerender' + ); + } +} + +jitSuite(UpdatingModifiers); diff --git a/packages/@glimmer-workspace/integration-tests/test/updating-svg-test.ts b/packages/@glimmer-workspace/integration-tests/test/updating-svg-test.ts new file mode 100644 index 00000000000..86ae5a160b5 --- /dev/null +++ b/packages/@glimmer-workspace/integration-tests/test/updating-svg-test.ts @@ -0,0 +1,408 @@ +import type { SimpleElement } from '@glimmer/interfaces'; +import { NS_HTML, NS_SVG, NS_XLINK } from '@glimmer/constants'; +import { + assertNodeTagName, + jitSuite, + RenderTest, + test, +} from '@glimmer-workspace/integration-tests'; + +import { assert } from './support'; + +class UpdatingSvgTest extends RenderTest { + static suiteName = 'Updating SVG'; + + @test + 'HTML namespace from root element is continued to child templates'() { + this.render('{{#if this.hasCircle}}{{/if}}', { hasCircle: true }); + + const assertNamespaces = () => { + if (assertNodeTagName(this.element.firstChild, 'svg')) { + assert.strictEqual(this.element.firstChild.namespaceURI, NS_SVG); + if (assertNodeTagName(this.element.firstChild.firstChild, 'circle')) { + assert.strictEqual(this.element.firstChild.firstChild.namespaceURI, NS_SVG); + } + } + }; + + this.assertHTML(''); + assertNamespaces(); + this.assertStableRerender(); + + this.rerender({ hasCircle: false }); + this.assertHTML(''); + + this.rerender({ hasCircle: true }); + + this.assertHTML(''); + assertNamespaces(); + } + + @test + 'context.root tag is SVG namespaced'() { + const parent = this.element; + const svg = this.delegate.createElementNS(NS_SVG, 'svg'); + this.element.appendChild(svg); + this.element = svg; + + const assertNamespaces = () => { + if (assertNodeTagName(parent.firstChild, 'svg')) { + assert.strictEqual(parent.firstChild.namespaceURI, NS_SVG); + if (assertNodeTagName(parent.firstChild.firstChild, 'foreignObject')) { + assert.strictEqual(parent.firstChild.firstChild.namespaceURI, NS_SVG); + } + } + }; + + this.render('{{#if this.hasForeignObject}}
    {{/if}}', { + hasForeignObject: true, + }); + + this.assertHTML('
    ', parent); + assertNamespaces(); + this.assertStableRerender(); + + this.rerender({ hasForeignObject: false }); + + this.assertHTML('', parent); + + this.rerender({ hasForeignObject: true }); + + this.assertHTML('
    ', parent); + assertNamespaces(); + } + + @test + 'elements nested inside have an XHTML namespace'() { + this.render('{{#if this.hasDiv}}
    {{/if}}
    ', { + hasDiv: true, + }); + + const assertNamespaces = () => { + if (assertNodeTagName(this.element.firstChild, 'svg')) { + assert.strictEqual(this.element.firstChild.namespaceURI, NS_SVG); + if (assertNodeTagName(this.element.firstChild.firstChild, 'foreignObject')) { + assert.strictEqual(this.element.firstChild.firstChild.namespaceURI, NS_SVG); + if (assertNodeTagName(this.element.firstChild.firstChild.firstChild, 'div')) { + assert.strictEqual(this.element.firstChild.firstChild.firstChild.namespaceURI, NS_HTML); + } + } + } + }; + + this.assertHTML('
    '); + assertNamespaces(); + this.assertStableRerender(); + + this.rerender({ hasDiv: false }); + + this.assertHTML(''); + + this.rerender({ hasDiv: true }); + + this.assertHTML('
    '); + assertNamespaces(); + } + + @test + 'Namespaced attribute with a quoted expression'() { + this.render('content', { title: 'svg-title' }); + + const assertNamespaces = () => { + if (assertNodeTagName(this.element.firstChild, 'svg')) { + assert.strictEqual(this.element.firstChild.namespaceURI, NS_SVG); + const [attr] = this.guardArray( + { attributes: this.element.firstChild.attributes }, + { min: 1 } + ); + assert.strictEqual(attr.namespaceURI, NS_XLINK); + } + }; + + this.assertHTML(`content`); + assertNamespaces(); + this.assertStableRerender(); + + this.rerender({ title: 'mmun' }); + + this.assertHTML(`content`); + assertNamespaces(); + + this.rerender({ title: 'svg-title' }); + + this.assertHTML(`content`); + assertNamespaces(); + } + + @test + ' tag and expression as sibling'() { + this.render('{{this.name}}', { name: 'svg-title' }); + + const assertNamespace = () => { + if (assertNodeTagName(this.element.firstChild, 'svg')) { + assert.strictEqual(this.element.firstChild.namespaceURI, NS_SVG); + } + }; + + this.assertHTML(`svg-title`); + assertNamespace(); + this.assertStableRerender(); + + this.rerender({ name: null }); + + this.assertHTML(``); + assertNamespace(); + + this.rerender({ name: 'svg-title' }); + + this.assertHTML(`svg-title`); + assertNamespace(); + } + + @test + ' tag and unsafe expression as sibling'() { + this.render('{{{this.name}}}', { name: 'Biff' }); + + const assertNamespaces = (isUnsafe: boolean) => { + if (assertNodeTagName(this.element.firstChild, 'svg')) { + assert.strictEqual(this.element.firstChild.namespaceURI, NS_SVG); + } + if (isUnsafe && assertNodeTagName(this.element.lastChild, 'i')) { + assert.strictEqual(this.element.lastChild.namespaceURI, NS_HTML); + } + }; + + this.assertHTML(`Biff`); + assertNamespaces(true); + this.assertStableRerender(); + + this.rerender({ name: 'ef4' }); + + this.assertHTML(`ef4`); + assertNamespaces(false); + + this.rerender({ name: 'Biff' }); + + this.assertHTML(`Biff`); + assertNamespaces(true); + } + + @test + 'unsafe expression nested inside a namespace'() { + this.render('{{{this.content}}}
    ', { + content: '', + }); + + const assertNamespaces = (withElement: (svg: SimpleElement) => void) => { + if (assertNodeTagName(this.element.firstChild, 'svg')) { + assert.strictEqual(this.element.firstChild.namespaceURI, NS_SVG); + withElement(this.element.firstChild as SimpleElement); + } + if (assertNodeTagName(this.element.lastChild, 'div')) { + assert.strictEqual(this.element.lastChild.namespaceURI, NS_HTML); + } + }; + + this.assertHTML(`
    `); + assertNamespaces((svg) => { + if (assertNodeTagName(svg.firstChild, 'path')) { + assert.strictEqual( + svg.firstChild.namespaceURI, + NS_SVG, + 'initial render path has SVG namespace' + ); + } + }); + + this.rerender(); + + this.assertHTML(`
    `); + assertNamespaces((svg) => { + if (assertNodeTagName(svg.firstChild, 'path')) { + assert.strictEqual(svg.firstChild.namespaceURI, NS_SVG, 'path has SVG namespace'); + } + }); + + this.rerender({ + content: '', + }); + + this.assertHTML(`
    `); + assertNamespaces((svg) => { + if (assertNodeTagName(svg.firstChild, 'foreignObject')) { + assert.strictEqual( + svg.firstChild.namespaceURI, + NS_SVG, + 'initial render path has SVG namespace' + ); + if (assertNodeTagName(svg.firstChild.firstChild, 'span')) { + assert.strictEqual(svg.firstChild.firstChild.namespaceURI, NS_HTML, 'span has XHTML NS'); + } + } + }); + + this.rerender({ + content: '', + }); + + this.assertHTML(`
    `); + assertNamespaces((svg) => { + if (assertNodeTagName(svg.firstChild, 'path')) { + assert.strictEqual( + svg.firstChild.namespaceURI, + NS_SVG, + 'initial render path has SVG namespace' + ); + } + if (assertNodeTagName(svg.lastChild, 'circle')) { + assert.strictEqual( + svg.lastChild.namespaceURI, + NS_SVG, + 'initial render path has SVG namespace' + ); + } + }); + + this.rerender({ content: '' }); + + this.assertHTML(`
    `); + assertNamespaces((svg) => { + if (assertNodeTagName(svg.firstChild, 'path')) { + assert.strictEqual( + svg.firstChild.namespaceURI, + NS_SVG, + 'initial render path has SVG namespace' + ); + } + }); + } + + @test + 'expression nested inside a namespace'() { + this.render('
    {{this.content}}
    ', { + content: 'Milly', + }); + + const assertNamespaces = () => { + if (assertNodeTagName(this.element.firstChild, 'div')) { + assert.strictEqual(this.element.firstChild.namespaceURI, NS_HTML); + if (assertNodeTagName(this.element.firstChild.firstChild, 'svg')) { + assert.strictEqual(this.element.firstChild.firstChild.namespaceURI, NS_SVG); + } + } + }; + + this.assertHTML(`
    Milly
    `); + assertNamespaces(); + this.assertStableRerender(); + + this.rerender({ content: 'Moe' }); + + this.assertHTML(`
    Moe
    `); + assertNamespaces(); + + this.rerender({ content: 'Milly' }); + + this.assertHTML(`
    Milly
    `); + assertNamespaces(); + } + + @test + 'expression nested inside a namespaced context.root element'() { + this.render('{{this.content}}', { content: 'Maurice' }); + + const assertSvg = (withSVG?: (svg: SVGSVGElement) => void) => { + if (assertNodeTagName(this.element.firstChild, 'svg')) { + assert.strictEqual(this.element.firstChild.namespaceURI, NS_SVG); + if (withSVG) withSVG(this.element.firstChild); + } + }; + + this.assertHTML(`Maurice`); + assertSvg(); + this.assertStableRerender(); + + this.rerender({ content: null }); + + assertSvg((svg) => { + assert.strictEqual(svg.firstChild && svg.firstChild.textContent, ''); + }); + + this.rerender({ content: 'Maurice' }); + + this.assertHTML(`Maurice`); + assertSvg(); + } + + @test + 'HTML namespace is created in child templates'() { + this.render('{{#if this.isTrue}}{{else}}
    {{/if}}', { + isTrue: true, + }); + + const assertNamespaces = (isTrue: boolean) => { + if (isTrue) { + if (assertNodeTagName(this.element.firstChild, 'svg')) { + assert.strictEqual(this.element.firstChild.namespaceURI, NS_SVG); + } + } else { + if (assertNodeTagName(this.element.firstChild, 'div')) { + assert.strictEqual(this.element.firstChild.namespaceURI, NS_HTML); + if (assertNodeTagName(this.element.firstChild.firstChild, 'svg')) { + assert.strictEqual(this.element.firstChild.firstChild.namespaceURI, NS_SVG); + } + } + } + }; + + this.assertHTML(``); + assertNamespaces(true); + this.assertStableRerender(); + + this.rerender({ isTrue: false }); + + this.assertHTML(`
    `); + assertNamespaces(false); + + this.rerender({ isTrue: true }); + + this.assertHTML(``); + assertNamespaces(true); + } + + @test + 'HTML namespace is continued to child templates'() { + this.render('
    {{#if this.isTrue}}{{/if}}
    ', { isTrue: true }); + + const assertNamespaces = (isTrue: boolean) => { + if (assertNodeTagName(this.element.firstChild, 'div')) { + assert.strictEqual(this.element.firstChild.namespaceURI, NS_HTML); + if (assertNodeTagName(this.element.firstChild.firstChild, 'svg')) { + assert.strictEqual(this.element.firstChild.firstChild.namespaceURI, NS_SVG); + if ( + isTrue && + assertNodeTagName(this.element.firstChild.firstChild.firstChild, 'circle') + ) { + assert.strictEqual(this.element.firstChild.firstChild.firstChild.namespaceURI, NS_SVG); + } + } + } + }; + + this.assertHTML(`
    `); + assertNamespaces(true); + this.assertStableRerender(); + + this.rerender({ isTrue: false }); + + this.assertHTML(`
    `); + assertNamespaces(false); + + this.rerender({ isTrue: true }); + + this.assertHTML(`
    `); + assertNamespaces(true); + } +} + +jitSuite(UpdatingSvgTest); diff --git a/packages/@glimmer-workspace/integration-tests/test/updating-test.ts b/packages/@glimmer-workspace/integration-tests/test/updating-test.ts new file mode 100644 index 00000000000..46f2c627834 --- /dev/null +++ b/packages/@glimmer-workspace/integration-tests/test/updating-test.ts @@ -0,0 +1,2061 @@ +import type { Nullable, SimpleElement, SimpleNode } from '@glimmer/interfaces'; +import type { SafeString } from '@glimmer/runtime'; +import type { JitRenderDelegate } from '@glimmer-workspace/integration-tests'; +import { expect } from '@glimmer/debug-util'; +import { associateDestroyableChild, registerDestructor } from '@glimmer/destroyable'; +import { createComputeRef, createConstRef, createPrimitiveRef } from '@glimmer/reference'; +import { consumeTag, createTag, dirtyTag } from '@glimmer/validator'; +import { + assertNodeTagName, + getElementByClassName, + getElementsByTagName, + GlimmerishComponent, + jitSuite, + RenderTest, + stripTight, + test, + tracked, + trimLines, +} from '@glimmer-workspace/integration-tests'; + +import { assert } from './support'; +import { DEBUG } from '@glimmer/env'; + +function makeSafeString(value: string): SafeString { + return new SafeStringImpl(value); +} + +class SafeStringImpl implements SafeString { + constructor(private string: string) {} + toHTML() { + return this.string; + } + toString() { + return this.string; + } +} + +class UpdatingTest extends RenderTest { + static suiteName = 'Updating'; + + declare delegate: JitRenderDelegate; + + @test + 'updating a single curly'() { + this.render('

    {{this.value}}

    ', { value: 'hello world' }); + this.assertHTML('

    hello world

    ', 'Initial render'); + this.assertStableRerender(); + + this.rerender({ value: 'goodbye world' }); + this.assertHTML('

    goodbye world

    ', 'After updating and dirtying'); + this.assertStableNodes(); + } + + @test + 'updating a single curly with siblings'() { + this.render('
    hello {{this.value}}world
    ', { value: 'brave new ' }); + this.assertHTML('
    hello brave new world
    '); + this.assertStableRerender(); + + this.rerender({ value: 'another ' }); + this.assertHTML('
    hello another world
    '); + this.assertStableNodes(); + + this.rerender({ value: 'brave new ' }); + this.assertHTML('
    hello brave new world
    '); + this.assertStableNodes(); + } + + @test + 'null and undefined produces empty text nodes'() { + this.render('

    {{this.v1}}

    {{this.v2}}

    ', { + v1: null, + v2: undefined, + }); + this.assertHTML('

    ', 'Initial render'); + this.assertStableRerender(); + + this.rerender({ v1: 'hello' }); + this.assertHTML('

    hello

    ', 'After updating and dirtying'); + this.assertStableRerender(); + + this.rerender({ v2: 'world' }); + this.assertHTML('

    hello

    world

    ', 'After updating and dirtying'); + this.assertStableRerender(); + + this.rerender({ v1: null, v2: undefined }); + this.assertHTML('

    ', 'Initial render'); + this.assertStableRerender(); + } + + @test + 'weird paths'() { + let state = { + '': 'empty string', + '1': '1', + undefined: 'undefined', + null: 'null', + true: 'true', + false: 'false', + this: 'this', + 'foo.bar': 'foo.bar', + nested: null as unknown, + }; + + state.nested = state; + + this.render( + stripTight` +
    + [{{this.['']}}] + [{{this.[1]}}] + [{{this.[undefined]}}] + [{{this.[null]}}] + [{{this.[true]}}] + [{{this.[false]}}] + [{{this.[this]}}] + [{{this.[foo.bar]}}] + + [{{this.nested.['']}}] + [{{this.nested.[1]}}] + [{{this.nested.[undefined]}}] + [{{this.nested.[null]}}] + [{{this.nested.[true]}}] + [{{this.nested.[false]}}] + [{{this.nested.[this]}}] + [{{this.nested.[foo.bar]}}] +
    + `, + state + ); + + this.assertHTML(stripTight` +
    + [] + [1] + [undefined] + [null] + [true] + [false] + [this] + [foo.bar] + + [] + [1] + [undefined] + [null] + [true] + [false] + [this] + [foo.bar] +
    + `); + + this.assertStableRerender(); + + state[''] = 'EMPTY STRING'; + state['1'] = 'ONE'; + state['undefined'] = 'UNDEFINED'; + state['null'] = 'NULL'; + state['true'] = 'TRUE'; + state['false'] = 'FALSE'; + state['this'] = 'THIS'; + state['foo.bar'] = 'FOO.BAR'; + this.rerender(state); + + this.assertHTML(stripTight` +
    + [] + [ONE] + [UNDEFINED] + [NULL] + [TRUE] + [FALSE] + [THIS] + [FOO.BAR] + + [] + [ONE] + [UNDEFINED] + [NULL] + [TRUE] + [FALSE] + [THIS] + [FOO.BAR] +
    + `); + + state = { + '': 'empty string', + '1': '1', + undefined: 'undefined', + null: 'null', + true: 'true', + false: 'false', + this: 'this', + 'foo.bar': 'foo.bar', + nested: null, + }; + state.nested = state; + + this.rerender(state); + + this.assertHTML(stripTight` +
    + [] + [1] + [undefined] + [null] + [true] + [false] + [this] + [foo.bar] + + [] + [1] + [undefined] + [null] + [true] + [false] + [this] + [foo.bar] +
    + `); + } + + @test + 'updating a single trusting curly'() { + this.render('
    {{{this.value}}}
    ', { value: '

    hello world

    ' }); + + this.assertHTML(`

    hello world

    `, 'Initial render'); + this.assertStableRerender(); + + this.rerender({ value: 'goodbye world' }); + + this.assertHTML(`
    goodbye world
    `, 'Initial render'); + this.assertStableRerender(); + + this.rerender({ + value: 'a good man is hard to find', + }); + + this.assertHTML(`
    a good man is hard to find
    `, 'more complex'); + this.assertStableRerender(); + } + + @test + 'updating a single trusting curly with siblings'() { + this.render('
    hello {{{this.value}}}world
    ', { + value: 'brave new ', + }); + + this.assertHTML('
    hello brave new world
    ', 'Initial render'); + this.assertStableRerender(); + + this.rerender({ value: 'big wide ' }); + this.assertHTML('
    hello big wide world
    ', 'Initial render'); + this.assertStableRerender(); + + this.rerender({ value: 'another ' }); + this.assertHTML('
    hello another world
    ', 'Initial render'); + this.assertStableRerender(); + + this.rerender({ value: 'brave new ' }); + this.assertHTML('
    hello brave new world
    ', 'Initial render'); + this.assertStableRerender(); + } + + @test + 'updating a single trusting curly with previous sibling'() { + this.render('
    hello {{{this.value}}}
    ', { + value: 'brave new ', + }); + + this.assertHTML('
    hello brave new
    ', 'Initial render'); + this.assertStableRerender(); + + this.rerender({ value: 'another ' }); + this.assertHTML('
    hello another
    '); + this.assertStableRerender(); + + this.rerender({ value: 'brave new ' }); + this.assertHTML('
    hello brave new
    '); + this.assertStableNodes(); + } + + // This is to catch a regression about not caching lastValue correctly + @test + 'Cycling between two values in a trusting curly'() { + let a = '

    A

    '; + let b = '

    B

    '; + + this.render('
    {{{this.value}}}
    ', { value: a }); + + this.assertHTML('

    A

    ', 'Initial render'); + + this.rerender({ value: b }); + this.assertHTML('

    B

    ', 'Updating'); + + // Change it back + this.rerender({ value: a }); + this.assertHTML('

    A

    ', 'Updating'); + + // Change it back + this.rerender({ value: b }); + this.assertHTML('

    B

    ', 'Updating'); + } + + @test + 'updating a curly with a safe and unsafe string'() { + interface SafeString { + string: string; + toHTML(): string; + toString(): string; + } + + let safeString = { + string: '

    hello world

    ', + toHTML: function (this: SafeString) { + return this.string; + }, + toString: function (this: SafeString) { + return this.string; + }, + }; + let unsafeString = 'Big old world!'; + + this.render('
    {{this.value}}
    ', { + value: safeString, + }); + + this.assertHTML('

    hello world

    ', 'Initial render'); + this.assertStableRerender(); + + this.rerender({ value: unsafeString }); + + this.assertHTML( + '
    <b>Big old world!</b>
    ', + 'After replacing with unsafe string' + ); + + this.rerender({ value: safeString }); + this.assertHTML('

    hello world

    ', 'Initial render'); + this.assertStableRerender(); + } + + @test + 'updating a triple curly with a safe and unsafe string'() { + let safeString = makeSafeString('

    hello world

    '); + let unsafeString = 'Big old world!'; + + this.render('
    {{{this.value}}}
    ', { + value: safeString, + }); + + this.assertHTML('

    hello world

    ', 'Initial render'); + this.assertStableRerender(); + + this.rerender({ + value: unsafeString, + }); + + this.assertHTML('
    Big old world!
    ', 'Normal strings may contain HTML'); + + this.rerender({ + value: safeString, + }); + + this.assertHTML('

    hello world

    ', 'original input causes no problem'); + } + + @test + 'triple curlies with empty string initial value'() { + this.render('
    {{{this.value}}}
    ', { + value: '', + }); + + this.assertHTML('
    ', 'Initial render'); + this.assertStableRerender(); + + this.rerender({ + value: 'Bold and spicy', + }); + + this.assertHTML('
    Bold and spicy
    ', 'markup is updated'); + + this.rerender({ value: '' }); + + this.assertHTML('
    ', 'back to empty string'); + } + + @test + 'double curlies with const SafeString'() { + let rawString = 'bold and spicy'; + + this.registerInternalHelper('const-foobar', () => { + return createConstRef(makeSafeString(rawString), 'safe-string'); + }); + + this.render('
    {{const-foobar}}
    ', {}); + this.assertHTML('
    bold and spicy
    ', 'initial render'); + this.assertStableRerender(); + } + + @test + 'double curlies with const Node'() { + let rawString = 'bold and spicy'; + + this.registerInternalHelper('const-foobar', () => { + return createConstRef(this.delegate.createTextNode(rawString), 'text-node'); + }); + + this.render('
    {{const-foobar}}
    '); + this.assertHTML('
    <b>bold</b> and spicy
    ', 'initial render'); + this.assertStableRerender(); + } + + @test + 'triple curlies with const SafeString'() { + let rawString = 'bold and spicy'; + + this.registerInternalHelper('const-foobar', () => { + return createConstRef(makeSafeString(rawString), 'safe-string'); + }); + + this.render('
    {{{const-foobar}}}
    '); + this.assertHTML('
    bold and spicy
    ', 'initial render'); + this.assertStableRerender(); + } + + @test + 'triple curlies with const Node'() { + let rawString = 'bold and spicy'; + + this.registerInternalHelper('const-foobar', () => { + return createConstRef(this.delegate.createTextNode(rawString), 'text-node'); + }); + + this.render('
    {{{const-foobar}}}
    '); + this.assertHTML('
    <b>bold</b> and spicy
    ', 'initial render'); + this.assertStableRerender(); + } + + @test + 'helpers can add destroyables'() { + let destroyable = { + count: 0, + }; + + registerDestructor(destroyable, () => { + destroyable.count++; + }); + + this.registerInternalHelper('destroy-me', (_args) => { + let ref = createPrimitiveRef('destroy me!'); + + associateDestroyableChild(ref, destroyable); + + return ref; + }); + + this.render('
    {{destroy-me}}
    ', {}); + + this.assertHTML('
    destroy me!
    ', 'initial render'); + assert.strictEqual(destroyable.count, 0, 'not destroyed'); + + this.rerender(); + + this.assertHTML('
    destroy me!
    ', 'no change'); + assert.strictEqual(destroyable.count, 0, 'not destroyed'); + + this.destroy(); + + assert.strictEqual(destroyable.count, 1, 'is destroyed'); + } + + ////////// + + testStatefulHelper( + assert: typeof QUnit.assert, + arg1: { + template: string; + truthyValue: T; + falsyValue: U; + element?: SimpleElement; + } + ) { + let { template, truthyValue, falsyValue, element } = arg1; + let didCreate = 0; + let didDestroy = 0; + let tag = createTag(); + let currentValue: T | U = truthyValue; + + this.registerInternalHelper('stateful-foo', (_args) => { + didCreate++; + + let ref = createComputeRef(() => { + consumeTag(tag); + return currentValue; + }); + + let destroyable = {}; + + registerDestructor(destroyable, () => didDestroy++); + associateDestroyableChild(ref, destroyable); + + return ref; + }); + + assert.strictEqual(didCreate, 0, 'didCreate: before render'); + assert.strictEqual(didDestroy, 0, 'didDestroy: before render'); + + this.render(template, {}); + + this.assertHTML('Yes', element, 'initial render'); + assert.strictEqual(didCreate, 1, 'didCreate: after initial render'); + assert.strictEqual(didDestroy, 0, 'didDestroy: after initial render'); + + this.rerender(); + + this.assertHTML('Yes', element, 'after no-op re-render'); + assert.strictEqual(didCreate, 1, 'didCreate: after no-op re-render'); + assert.strictEqual(didDestroy, 0, 'didDestroy: after no-op re-render'); + + currentValue = falsyValue; + dirtyTag(tag); + this.rerender(); + + this.assertHTML(element ? '' : '', element, 'after switching to falsy'); + assert.strictEqual(didCreate, 1, 'didCreate: after switching to falsy'); + assert.strictEqual(didDestroy, 0, 'didDestroy: after switching to falsy'); + + currentValue = truthyValue; + dirtyTag(tag); + this.rerender(); + + this.assertHTML('Yes', element, 'after reset'); + assert.strictEqual(didCreate, 1, 'didCreate: after reset'); + assert.strictEqual(didDestroy, 0, 'didDestroy: after reset'); + } + + @test + 'helpers passed as arguments to {{#if}} are not torn down when switching between blocks'() { + let options = { + template: '{{#if (stateful-foo)}}Yes{{/if}}', + truthyValue: true, + falsyValue: false, + }; + + this.testStatefulHelper(assert, options); + } + + @test + 'helpers passed as arguments to {{#unless}} are not torn down when switching between blocks'() { + let options = { + template: '{{#unless (stateful-foo)}}Yes{{/unless}}', + truthyValue: false, + falsyValue: true, + }; + + this.testStatefulHelper(assert, options); + } + + @test + 'helpers passed as arguments to {{#each}} are not torn down when switching between blocks'() { + let options = { + template: '{{#each (stateful-foo) key="@index" as |unused|}}Yes{{/each}}', + truthyValue: [1], + falsyValue: null, + }; + + this.testStatefulHelper(assert, options); + } + + @test + 'helpers passed as arguments to {{component}} are not torn down when switching between blocks'() { + this.registerComponent('Glimmer', 'XYasss', 'Yes'); + + let options = { + template: '{{component (stateful-foo)}}', + truthyValue: 'XYasss', + falsyValue: null, + }; + + this.testStatefulHelper(assert, options); + } + + @test + 'helpers passed as arguments to {{#in-element}} are not torn down when switching between blocks'() { + let externalElement = this.delegate.createElement('div'); + + let options = { + template: '{{#in-element (stateful-foo)}}Yes{{/in-element}}', + truthyValue: externalElement, + falsyValue: null, + element: externalElement, + }; + + this.testStatefulHelper(assert, options); + } + + @test + 'updating a curly with this'() { + this.render('

    {{this.value}}

    ', { value: 'hello world' }); + + this.assertHTML('

    hello world

    '); + this.assertStableRerender(); + + this.rerender({ value: 'goodbye world' }); + + this.assertHTML('

    goodbye world

    '); + } + + @test + 'a simple implementation of a dirtying rerender'() { + this.render( + '
    {{#if this.condition}}

    {{this.value}}

    {{else}}

    Nothing

    {{/if}}
    ', + { + condition: true, + value: 'hello world', + } + ); + + this.assertHTML('

    hello world

    ', 'Initial render'); + this.assertStableRerender(); + + // Even though the #if was stable, a dirty child node is updated + this.rerender({ value: 'goodbye world' }); + this.assertStableNodes(); + + this.rerender({ condition: false }); + this.assertHTML('

    Nothing

    ', 'And then dirtying'); + this.assertStableNodes(); + } + + @test + 'a simple implementation of a dirtying rerender without else'() { + this.render('
    {{#if this.condition}}

    {{this.value}}

    {{/if}}
    ', { + condition: true, + value: 'hello world', + }); + + this.assertHTML('

    hello world

    ', 'Initial render'); + + this.rerender({ condition: false }); + this.assertHTML('
    ', 'If the condition is false, the morph becomes empty'); + + this.rerender({ condition: true }); + this.assertHTML( + '

    hello world

    ', + 'If the condition is true, the morph repopulates' + ); + } + + @test + 'The unless helper without else'() { + this.render('
    {{#unless this.condition}}

    {{this.value}}

    {{/unless}}
    ', { + condition: true, + value: 'hello world', + }); + + this.assertHTML('
    ', 'Initial render'); + + this.rerender({ condition: false }); + this.assertHTML( + '

    hello world

    ', + 'If the condition is false, the morph becomes populated' + ); + + this.rerender({ condition: true }); + this.assertHTML('
    ', 'If the condition is true, the morph unpopulated'); + } + + @test + 'The unless helper with else'() { + this.render( + '
    {{#unless this.condition}}

    {{this.value}}

    {{else}}

    Nothing

    {{/unless}}
    ', + { condition: true, value: 'hello world' } + ); + + this.assertHTML('

    Nothing

    ', 'Initial render'); + + this.rerender({ condition: false }); + this.assertHTML( + '

    hello world

    ', + 'If the condition is false, the default renders' + ); + + this.rerender({ condition: true }); + this.assertHTML('

    Nothing

    ', 'If the condition is true, the else renders'); + } + + @test + 'if keyword in append position'() { + this.render('{{if this.condition "truthy"}}', { + condition: true, + }); + + this.assertHTML('truthy', 'Initial render'); + + this.rerender({ condition: false }); + this.assertHTML('', 'If the condition is false nothing renders'); + + this.rerender({ condition: true }); + this.assertHTML('truthy', 'If the condition is true, the truthy value renders'); + } + + @test + 'if keyword in SubExpression without falsey value returns undefined [GH emberjs/ember.js#19409]'() { + this.registerHelper('to-string', (args) => `${args[0]}`); + + this.render('{{to-string (if this.condition "truthy")}}', { + condition: false, + }); + + this.assertHTML('undefined', 'Initial render'); + } + + @test + 'if keyword in append position with falsy'() { + this.render('{{if this.condition "truthy" "falsy"}}', { + condition: true, + }); + + this.assertHTML('truthy', 'Initial render'); + + this.rerender({ condition: false }); + this.assertHTML('falsy', 'If the condition is false, the falsy value renders'); + + this.rerender({ condition: true }); + this.assertHTML('truthy', 'If the condition is true, the truthy value renders'); + } + + @test + 'unless keyword in append position'() { + this.render('{{unless this.condition "falsy"}}', { + condition: false, + }); + + this.assertHTML('falsy', 'Initial render'); + + this.rerender({ condition: true }); + this.assertHTML('', 'If the condition is true nothing renders'); + + this.rerender({ condition: false }); + this.assertHTML('falsy', 'If the condition is false, the falsy value renders'); + } + + @test + 'unless keyword in append position with truthy'() { + this.render('{{unless this.condition "falsy" "truthy"}}', { + condition: false, + }); + + this.assertHTML('falsy', 'Initial render'); + + this.rerender({ condition: true }); + this.assertHTML('truthy', 'If the condition is true, the truthy value renders'); + + this.rerender({ condition: false }); + this.assertHTML('falsy', 'If the condition is false, the falsy value renders'); + } + + @test + 'if keyword in call position'() { + this.registerComponent('TemplateOnly', 'Foo', '{{@value}}'); + this.render('', { + condition: true, + }); + + this.assertHTML('truthy', 'Initial render'); + + this.rerender({ condition: false }); + this.assertHTML('', 'If the condition is false nothing renders'); + + this.rerender({ condition: true }); + this.assertHTML('truthy', 'If the condition is true, the truthy value renders'); + } + + @test + 'if keyword in call position with falsy'() { + this.registerComponent('TemplateOnly', 'Foo', '{{@value}}'); + this.render('', { + condition: true, + }); + + this.assertHTML('truthy', 'Initial render'); + + this.rerender({ condition: false }); + this.assertHTML('falsy', 'If the condition is false, the falsy value renders'); + + this.rerender({ condition: true }); + this.assertHTML('truthy', 'If the condition is true, the truthy value renders'); + } + + @test + 'unless keyword in call position'() { + this.registerComponent('TemplateOnly', 'Foo', '{{@value}}'); + this.render('', { + condition: false, + }); + + this.assertHTML('falsy', 'Initial render'); + + this.rerender({ condition: true }); + this.assertHTML('', 'If the condition is true nothing renders'); + + this.rerender({ condition: false }); + this.assertHTML('falsy', 'If the condition is false, the falsy value renders'); + } + + @test + 'unless keyword in call position with truthy'() { + this.registerComponent('TemplateOnly', 'Foo', '{{@value}}'); + this.render('', { + condition: false, + }); + + this.assertHTML('falsy', 'Initial render'); + + this.rerender({ condition: true }); + this.assertHTML('truthy', 'If the condition is true, the truthy value renders'); + + this.rerender({ condition: false }); + this.assertHTML('falsy', 'If the condition is false, the falsy value renders'); + } + + @test + 'a conditional that is false on the first run'() { + this.render('
    {{#if this.condition}}

    {{this.value}}

    {{/if}}
    ', { + condition: false, + value: 'hello world', + }); + + this.assertHTML('
    ', 'Initial render'); + + this.rerender({ condition: true }); + this.assertHTML( + '

    hello world

    ', + 'If the condition is true, the morph populates' + ); + + this.rerender({ condition: false }); + this.assertHTML('
    ', 'If the condition is false, the morph is empty'); + } + + @test + 'block arguments'() { + class Name { + constructor(first: string, last: string) { + this.first = first; + this.last = last; + } + + @tracked first = 'Godfrey'; + @tracked last = 'Godfrey'; + } + + const person = { name: new Name('Godfrey', 'Chan') }; + + this.render('
    {{#let this.person.name.first as |f|}}{{f}}{{/let}}
    ', { + person, + }); + + this.assertHTML('
    Godfrey
    ', 'Initial render'); + + person.name.first = 'Godfreak'; + this.rerender(); + + this.assertHTML('
    Godfreak
    ', 'After updating'); + + this.rerender({ person: { name: { first: 'Godfrey', last: 'Chan' } } }); + + this.assertHTML('
    Godfrey
    ', 'After reset'); + } + + @test({ skip: !DEBUG }) + 'missing helper'(assert: Assert) { + this.registerHelper('hello', () => 'hello'); + + assert.throws(() => { + this.delegate.compileTemplate('{{helo world}}'); + }, /Error: Attempted to resolve `helo`, which was expected to be a component or helper, but nothing was found./u); + } + + @test + 'block arguments should have higher precedence than helpers'() { + // Note: This test intentionally tests property fallback + this.registerHelper('foo', () => 'foo-helper'); + this.registerHelper('bar', () => 'bar-helper'); + this.registerHelper('echo', (args) => args[0]); + + let template = trimLines` +
    + foo: "{{foo}}"; + bar: "{{bar}}"; + value: "{{this.value}}"; + echo foo: "{{echo this.foo}}"; + echo bar: "{{echo this.bar}}"; + echo value: "{{echo this.value}}"; + + ----- + + {{#let this.value as |foo|}} + foo: "{{foo}}"; + bar: "{{bar}}"; + value: "{{this.value}}"; + echo foo: "{{echo foo}}"; + echo bar: "{{echo this.bar}}"; + echo value: "{{echo this.value}}"; + + ----- + + {{#let foo as |bar|}} + foo: "{{foo}}"; + bar: "{{bar}}"; + value: "{{this.value}}"; + echo foo: "{{echo foo}}"; + echo bar: "{{echo bar}}"; + echo value: "{{echo this.value}}"; + {{/let}} + {{/let}} + + ----- + + {{#let this.value as |bar|}} + foo: "{{foo}}"; + bar: "{{bar}}"; + value: "{{this.value}}"; + echo foo: "{{echo this.foo}}"; + echo bar: "{{echo bar}}"; + echo value: "{{echo this.value}}"; + {{/let}} +
    + `; + + this.render(template, { foo: 'foo-value', bar: 'bar-value', value: 'value-value' }); + + this.assertHTML( + trimLines` +
    + foo: "foo-helper"; + bar: "bar-helper"; + value: "value-value"; + echo foo: "foo-value"; + echo bar: "bar-value"; + echo value: "value-value"; + + ----- + + foo: "value-value"; + bar: "bar-helper"; + value: "value-value"; + echo foo: "value-value"; + echo bar: "bar-value"; + echo value: "value-value"; + + ----- + + foo: "value-value"; + bar: "value-value"; + value: "value-value"; + echo foo: "value-value"; + echo bar: "value-value"; + echo value: "value-value"; + + ----- + + foo: "foo-helper"; + bar: "value-value"; + value: "value-value"; + echo foo: "foo-value"; + echo bar: "value-value"; + echo value: "value-value"; +
    `, + 'Initial render' + ); + + this.assertStableRerender(); + + this.rerender({ value: 'NEW-VALUE' }); + + this.assertHTML( + trimLines` +
    + foo: "foo-helper"; + bar: "bar-helper"; + value: "NEW-VALUE"; + echo foo: "foo-value"; + echo bar: "bar-value"; + echo value: "NEW-VALUE"; + + ----- + + foo: "NEW-VALUE"; + bar: "bar-helper"; + value: "NEW-VALUE"; + echo foo: "NEW-VALUE"; + echo bar: "bar-value"; + echo value: "NEW-VALUE"; + + ----- + + foo: "NEW-VALUE"; + bar: "NEW-VALUE"; + value: "NEW-VALUE"; + echo foo: "NEW-VALUE"; + echo bar: "NEW-VALUE"; + echo value: "NEW-VALUE"; + + ----- + + foo: "foo-helper"; + bar: "NEW-VALUE"; + value: "NEW-VALUE"; + echo foo: "foo-value"; + echo bar: "NEW-VALUE"; + echo value: "NEW-VALUE"; +
    `, + 'After update' + ); + + this.rerender({ foo: 'foo-value', bar: 'bar-value', value: 'value-value' }); + + this.assertHTML( + trimLines` +
    + foo: "foo-helper"; + bar: "bar-helper"; + value: "value-value"; + echo foo: "foo-value"; + echo bar: "bar-value"; + echo value: "value-value"; + + ----- + + foo: "value-value"; + bar: "bar-helper"; + value: "value-value"; + echo foo: "value-value"; + echo bar: "bar-value"; + echo value: "value-value"; + + ----- + + foo: "value-value"; + bar: "value-value"; + value: "value-value"; + echo foo: "value-value"; + echo bar: "value-value"; + echo value: "value-value"; + + ----- + + foo: "foo-helper"; + bar: "value-value"; + value: "value-value"; + echo foo: "foo-value"; + echo bar: "value-value"; + echo value: "value-value"; +
    `, + 'After reset' + ); + } + + @test + 'block arguments (ensure balanced push/pop)'() { + let person = { name: { first: 'Godfrey', last: 'Chan' } }; + this.render('
    {{#let this.person.name.first as |f|}}{{f}}{{/let}}{{this.f}}
    ', { + person, + f: 'Outer', + }); + + this.assertHTML('
    GodfreyOuter
    ', 'Initial render'); + + person.name.first = 'Godfreak'; + this.rerender({ person }); + + this.assertHTML('
    GodfreakOuter
    ', 'After updating'); + } + + @test + 'block arguments cannot be accessed through {{this}}'() { + this.registerHelper('noop', (params) => params[0]); + + this.render( + stripTight` +
    + [{{#let this.person as |name|}}{{this.name}}{{/let}}] + [{{#let this.person as |name|}}{{#let this.name as |test|}}{{test}}{{/let}}{{/let}}] + [{{#let this.person as |name|}}{{#let (noop this.name) as |test|}}{{test}}{{/let}}{{/let}}] +
    + `, + { person: 'Yehuda', name: 'Godfrey' } + ); + + this.assertHTML('
    [Godfrey][Godfrey][Godfrey]
    ', 'Initial render'); + this.assertStableRerender(); + + this.rerender({ name: 'Godfreak' }); + this.assertHTML('
    [Godfreak][Godfreak][Godfreak]
    ', 'After update'); + + this.rerender({ name: 'Godfrey' }); + this.assertHTML('
    [Godfrey][Godfrey][Godfrey]
    ', 'After reset'); + } + + @test + 'The with helper should consider an empty array truthy'() { + this.render('
    {{#let this.condition as |c|}}{{c.length}}{{/let}}
    ', { + condition: [], + }); + + this.assertHTML('
    0
    ', 'Initial render'); + + this.rerender({ + condition: [1], + }); + + this.assertHTML('
    1
    ', 'After updating'); + } + + @test + 'block helpers whose template has a morph at the edge'() { + this.render('{{#if true}}{{this.value}}{{/if}}', { value: 'hello world' }); + this.assertHTML('hello world'); + + let firstNode = this.element.firstChild; + assert.notStrictEqual(firstNode, null, 'first node should have rendered'); + if (firstNode !== null) { + assert.strictEqual( + firstNode.nodeType, + 3, + 'the first node of the helper should be a text node' + ); + assert.strictEqual(firstNode.nodeValue, 'hello world', 'its content should be hello world'); + + assert.strictEqual(firstNode.nextSibling, null, 'there should only be one nodes'); + } + } + + @test + "clean content doesn't get blown away"() { + this.render('
    {{this.value}}
    ', { value: 'hello' }); + + let firstNode: Nullable = this.element.firstChild; + let textNode: Node | null; + if (assertNodeTagName(firstNode, 'div')) { + textNode = firstNode.firstChild; + assert.strictEqual(textNode && textNode.nodeValue, 'hello'); + } + + this.rerender({ value: 'goodbye' }); + + this.assertHTML('
    goodbye
    '); + + this.rerender({ value: 'hello' }); + + firstNode = this.element.firstChild; + if (assertNodeTagName(firstNode, 'div')) { + textNode = firstNode.firstChild; + assert.strictEqual(textNode && textNode.nodeValue, 'hello'); + } + } + + @test + 'helper calls follow the normal dirtying rules'() { + this.registerHelper('capitalize', (params) => { + let value = params[0]; + if (value !== null && value !== undefined && typeof value === 'string') { + return value.toUpperCase(); + } + return; + }); + + this.render('
    {{capitalize this.value}}
    ', { value: 'hello' }); + this.assertHTML('
    HELLO
    '); + + this.rerender({ + value: 'goodbye', + }); + + this.assertHTML('
    GOODBYE
    '); + this.assertStableRerender(); + + // Checks normalized value, not raw value + this.rerender({ + value: 'GoOdByE', + }); + this.assertHTML('
    GOODBYE
    '); + this.assertStableNodes(); + } + + @test + 'class attribute follow the normal dirtying rules'() { + this.render("
    hello
    ", { value: 'world' }); + + this.assertHTML("
    hello
    ", 'Initial render'); + + this.rerender({ + value: 'universe', + }); + + this.assertHTML("
    hello
    ", 'Revalidating without dirtying'); + this.assertStableRerender(); + + this.rerender({ + value: 'world', + }); + + this.assertHTML("
    hello
    ", 'Revalidating after dirtying'); + } + + @test + 'class attribute w/ concat follow the normal dirtying rules'() { + this.render("
    hello
    ", { value: 'world' }); + + this.assertHTML("
    hello
    "); + this.assertStableRerender(); + + this.rerender({ value: 'universe' }); + this.assertHTML("
    hello
    "); + + this.rerender({ value: null }); + this.assertHTML("
    hello
    "); + + this.rerender({ value: 'world' }); + this.assertHTML("
    hello
    "); + } + + @test + 'class attribute is removed if the binding becomes null or undefined'() { + this.render('
    hello
    ', { value: 'foo' }); + + this.assertHTML("
    hello
    "); + this.assertStableRerender(); + + this.rerender({ value: null }); + this.assertHTML('
    hello
    '); + + this.rerender({ value: 0 }); + this.assertHTML("
    hello
    "); + + this.rerender({ value: undefined }); + this.assertHTML('
    hello
    '); + + this.rerender({ value: 'foo' }); + this.assertHTML("
    hello
    "); + } + + @test + 'attribute nodes follow the normal dirtying rules'() { + this.render("
    hello
    ", { value: 'world' }); + this.assertHTML("
    hello
    ", 'Initial render'); + + this.rerender({ value: 'universe' }); + this.assertHTML("
    hello
    ", 'Revalidating without dirtying'); + this.assertStableRerender(); + + this.rerender({ value: null }); + this.assertHTML('
    hello
    ', 'Revalidating after dirtying'); + + this.rerender({ value: 'world' }); + this.assertHTML("
    hello
    ", 'Revalidating after dirtying'); + } + + @test + 'attribute nodes w/ concat follow the normal dirtying rules'() { + this.render("
    hello
    ", { value: 'world' }); + this.assertHTML("
    hello
    "); + this.assertStableRerender(); + + this.rerender({ value: 'universe' }); + this.assertHTML("
    hello
    "); + + this.rerender({ value: null }); + this.assertHTML("
    hello
    "); + + this.rerender({ value: 'world' }); + this.assertHTML("
    hello
    "); + } + + @test + 'attributes values are normalized correctly'() { + this.render('
    hello
    ', { + value: { + toString() { + return 'world'; + }, + }, + }); + + this.assertHTML("
    hello
    ", 'Initial render'); + this.assertStableRerender(); + + this.rerender({ value: 123 }); + + this.assertHTML("
    hello
    ", 'Revalidating without dirtying'); + this.assertStableRerender(); + + this.rerender({ value: false }); + + this.assertHTML('
    hello
    ', 'Revalidating after dirtying'); + this.assertStableRerender(); + + this.rerender({ + value: { + toString() { + return 'world'; + }, + }, + }); + + this.assertHTML("
    hello
    ", 'Revalidating after dirtying'); + } + + @test + 'namespaced attribute nodes follow the normal dirtying rules'() { + this.render("
    hello
    ", { lang: 'en-us' }); + + this.assertHTML("
    hello
    ", 'Initial render'); + + this.rerender({ lang: 'en-uk' }); + + this.assertHTML("
    hello
    ", 'Revalidating without dirtying'); + this.assertStableRerender(); + } + + @test + 'namespaced attribute nodes w/ concat follow the normal dirtying rules'() { + this.render("
    hello
    ", { locale: 'us' }); + + this.assertHTML("
    hello
    ", 'Initial render'); + this.assertStableRerender(); + + this.rerender({ locale: 'uk' }); + this.assertHTML("
    hello
    ", 'After update'); + + this.rerender({ locale: null }); + this.assertHTML("
    hello
    ", 'After updating to null'); + + this.rerender({ locale: 'us' }); + this.assertHTML("
    hello
    ", 'After reset'); + } + + @test + 'non-standard namespaced attribute nodes follow the normal dirtying rules'() { + this.render("
    hello
    ", { type: 'dedication' }); + this.assertHTML("
    hello
    ", 'Initial render'); + + this.rerender({ type: 'backmatter' }); + this.assertHTML("
    hello
    ", 'Revalidating without dirtying'); + this.assertStableRerender(); + } + + @test + 'non-standard namespaced attribute nodes w/ concat follow the normal dirtying rules'() { + this.render("
    hello
    ", { type: 'backmatter' }); + + this.assertHTML("
    hello
    ", 'Initial render'); + this.assertStableRerender(); + + this.rerender({ type: 'index' }); + this.assertHTML("
    hello
    ", 'After update'); + + this.rerender({ type: null }); + this.assertHTML("
    hello
    ", 'After updating to null'); + + this.rerender({ type: 'backmatter' }); + this.assertHTML("
    hello
    ", 'After reset'); + } + + @test + '