diff --git a/.env b/.env new file mode 100644 index 0000000000..5f4193d478 --- /dev/null +++ b/.env @@ -0,0 +1 @@ +NODE_OPTIONS="--no-warnings" diff --git a/.env.testing b/.env.testing new file mode 100644 index 0000000000..c0d6652113 --- /dev/null +++ b/.env.testing @@ -0,0 +1 @@ +NODE_ENV=development diff --git a/.eslintignore b/.eslintignore index b6326c2727..1e98e7c352 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,10 +1,13 @@ # compiled output /dist/ +**/dist/ /tmp/ # dependencies /bower_components/ /node_modules/ +**/node_modules/ +**/.yalc/ # misc /coverage/ diff --git a/.eslintrc.cjs b/.eslintrc.cjs new file mode 100644 index 0000000000..d581099185 --- /dev/null +++ b/.eslintrc.cjs @@ -0,0 +1,82 @@ +// @ts-check + +const { resolve } = require('path'); + +const cjsTsconfig = resolve(__dirname, 'tsconfig.cjs.json'); + +/** @type {import("eslint").Linter.Config} */ +module.exports = { + root: true, + reportUnusedDisableDirectives: true, + extends: [], + ignorePatterns: [ + 'dist', + 'ts-dist', + 'node_modules', + 'tmp', + '**/node_modules', + '**/dist', + '**/fixtures', + '!**/.eslintrc.cjs', + ], + parser: '@typescript-eslint/parser', + parserOptions: { + ecmaVersion: 'latest', + project: [], + }, + settings: { + 'import/parsers': { + '@typescript-eslint/parser': ['.js', '.cjs', '.mjs', '.mts', '.ts', '.d.ts'], + }, + 'import/resolver': { + typescript: {}, + }, + node: { + allowModules: ['@glimmer/debug', '@glimmer/local-debug-flags'], + tryExtensions: ['.js', '.ts', '.d.ts', '.json'], + }, + }, + plugins: [ + '@typescript-eslint', + 'prettier', + 'qunit', + 'simple-import-sort', + 'unused-imports', + 'prettier', + 'n', + ], + + rules: {}, + overrides: [ + { + files: ['.eslintrc.cjs', '**/.eslintrc.cjs'], + parserOptions: { + project: [cjsTsconfig], + }, + extends: [ + 'plugin:@typescript-eslint/recommended', + 'plugin:import/errors', + 'plugin:import/typescript', + 'plugin:qunit/recommended', + 'prettier', + ], + rules: { + '@typescript-eslint/no-var-requires': 'off', + }, + }, + + { + // these packages need to be fixed to avoid these warnings, but in the + // meantime we should not regress the other packages + files: [ + // this specific test imports from @glimmer/runtime (causing a cyclic + // dependency), it should either be refactored to use the interfaces + // directly (instead of the impls) or moved into @glimmer/runtime + 'packages/@glimmer/reference/test/template-test.ts', + ], + rules: { + 'n/no-extraneous-import': 'warn', + }, + }, + ], +}; diff --git a/.eslintrc.json b/.eslintrc.json deleted file mode 100644 index 47fbd0e54f..0000000000 --- a/.eslintrc.json +++ /dev/null @@ -1,316 +0,0 @@ -{ - "root": true, - "extends": [ - "eslint:recommended", - "plugin:@typescript-eslint/eslint-recommended", - "plugin:qunit/recommended", - "plugin:n/recommended", - "plugin:import/errors", - "prettier" - ], - "ignorePatterns": ["dist", "ts-dist", "node_modules", "tmp", "**/node_modules", "**/dist"], - "parser": "@typescript-eslint/parser", - "parserOptions": { - "ecmaVersion": "latest" - }, - "settings": { - "import/parsers": { - "@typescript-eslint/parser": [".js", ".ts", ".d.ts"] - }, - "import/resolver": { - "typescript": {} - }, - "node": { - "allowModules": ["@glimmer/debug", "@glimmer/local-debug-flags"], - "tryExtensions": [".js", ".ts", ".d.ts", ".json"] - } - }, - "plugins": ["@typescript-eslint", "prettier", "qunit", "simple-import-sort", "unused-imports"], - "rules": { - "@typescript-eslint/no-array-constructor": "error", - "@typescript-eslint/no-empty-function": "error", - "@typescript-eslint/no-unused-vars": "error", - "accessor-pairs": "error", - "array-callback-return": "error", - "block-scoped-var": "error", - // replace ESLint rules with TypeScript-compatible rules - "camelcase": "off", - "capitalized-comments": "off", - "class-methods-use-this": "off", - "complexity": "off", - "consistent-return": "error", - "consistent-this": "error", - "default-case": "error", - "dot-notation": [ - "error", - { - "allowKeywords": true - } - ], - "eqeqeq": "error", - "func-name-matching": "error", - "func-names": "off", - "func-style": ["error", "declaration"], - "guard-for-in": "error", - "id-denylist": "error", - "id-length": "off", - "id-match": "error", - "import/default": "off", - "import/export": "off", - "import/first": ["error"], - "import/newline-after-import": ["error"], - "import/no-duplicates": ["error"], - "import/no-extraneous-dependencies": ["error"], - "import/order": "off", - "init-declarations": "off", - "max-depth": "off", - "max-lines": "off", - "max-nested-callbacks": "error", - "max-params": "off", - "n/callback-return": "error", - "n/global-require": "off", - "n/handle-callback-err": "error", - // this is handled by import/no-extraneous-dependencies - "n/no-extraneous-import": "off", - "n/no-missing-import": "off", - "n/no-mixed-requires": "error", - "n/no-new-require": "error", - "n/no-path-concat": "off", - "n/no-process-env": "off", - "n/no-process-exit": "off", - "n/no-restricted-import": "error", - "n/no-sync": "off", - "n/no-unsupported-features/es-builtins": [ - "error", - { - "version": "16.0.0" - } - ], - "new-cap": "error", - "no-alert": "error", - "no-array-constructor": "off", - "no-await-in-loop": "off", - "no-bitwise": "error", - "no-caller": "error", - "no-console": "error", - "no-continue": "error", - "no-div-regex": "error", - "no-duplicate-imports": "error", - "no-else-return": "error", - "no-empty-function": "off", - "no-eq-null": "error", - "no-eval": "error", - "no-extend-native": "error", - "no-extra-bind": "error", - "no-extra-label": "error", - "no-global-assign": "error", - "no-implicit-globals": "off", - "no-implied-eval": "error", - "no-inline-comments": "error", - "no-invalid-this": "error", - "no-iterator": "error", - "no-label-var": "error", - "no-labels": "error", - "no-lone-blocks": "error", - "no-lonely-if": "error", - "no-loop-func": "error", - "no-magic-numbers": "off", - "no-multi-assign": "error", - "no-multi-spaces": "error", - "no-multi-str": "error", - "no-negated-condition": "error", - "no-nested-ternary": "error", - "no-new": "error", - "no-new-func": "error", - "no-new-object": "error", - "no-new-wrappers": "error", - "no-octal-escape": "error", - "no-param-reassign": "off", - "no-plusplus": "off", - "no-proto": "error", - "no-restricted-globals": "error", - "no-restricted-imports": "error", - "no-restricted-properties": "error", - "no-restricted-syntax": "error", - "no-return-assign": "error", - "no-return-await": "error", - "no-script-url": "error", - "no-self-compare": "error", - "no-sequences": "error", - "no-shadow": "error", - "no-template-curly-in-string": "error", - "no-ternary": "off", - "no-throw-literal": "error", - "no-undef-init": "error", - "no-undefined": "off", - "no-unmodified-loop-condition": "error", - "no-unneeded-ternary": "error", - "no-unsafe-negation": "error", - "no-unused-expressions": "error", - "no-unused-labels": "error", - "no-unused-vars": "off", - "no-use-before-define": "off", - "no-useless-call": "error", - "no-useless-computed-key": "error", - "no-useless-concat": "error", - "no-useless-constructor": "error", - "no-useless-rename": "error", - "no-useless-return": "error", - "no-var": "error", - "no-void": "error", - "no-warning-comments": "error", - "object-shorthand": "error", - "one-var": "off", - "operator-assignment": "error", - "prefer-const": "off", - "prefer-destructuring": [ - "error", - { - "array": false, - "object": false - } - ], - "prefer-numeric-literals": "error", - "prefer-promise-reject-errors": "error", - "prefer-rest-params": "error", - "prefer-spread": "error", - "prefer-template": "off", - "prettier/prettier": "error", - // disabled because we still have a few commented tests - "qunit/no-commented-tests": "off", - // disabled due to false positives - "qunit/no-global-expect": "off", - // disabled because we still use this pattern everywhere - "qunit/no-global-module-test": "off", - // disabled due to false positives - "qunit/no-global-stop-start": "off", - "radix": "error", - "require-await": "error", - "require-jsdoc": "off", - "simple-import-sort/exports": ["error"], - "simple-import-sort/imports": ["error"], - "sort-imports": "off", - "sort-keys": "off", - "sort-vars": "off", - "spaced-comment": ["error", "always"], - "strict": "off", - "symbol-description": "error", - "unused-imports/no-unused-imports": "error", - "unused-imports/no-unused-vars": [ - "warn", - { - "args": "after-used", - "argsIgnorePattern": "^_", - "vars": "all", - "varsIgnorePattern": "^_" - } - ], - "valid-jsdoc": "off", - "vars-on-top": "error", - "yoda": ["error", "never"] - }, - "overrides": [ - { - "extends": [ - "eslint:recommended", - "plugin:@typescript-eslint/recommended", - "plugin:import/errors", - "plugin:import/typescript", - "plugin:qunit/recommended", - "prettier" - ], - "files": [ - "packages/@glimmer/compiler/**/*.ts", - "packages/@glimmer/syntax/lib/**/*.ts", - "packages/@glimmer/syntax/index.ts" - ], - "rules": { - "@typescript-eslint/ban-types": [ - "error", - { - "extendDefaults": true, - "types": { - "object": false - } - } - ], - "@typescript-eslint/no-explicit-any": [ - "error", - { - "ignoreRestArgs": true - } - ], - "@typescript-eslint/unbound-method": [ - "error", - { - "ignoreStatic": true - } - ], - // this is handled by import/errors - "n/no-extraneous-import": "off", - "prefer-const": ["off"], - "qunit/no-global-expect": ["off"] - } - }, - { - "files": ["**/*.d.ts"], - "parserOptions": { - "sourceType": "module" - }, - "rules": { - "n/no-missing-import": "off", - "no-useless-constructor": "off" - } - }, - - { - "env": { - "browser": true, - "es6": true - }, - "extends": ["plugin:import/errors"], - "files": ["benchmark/**/*.js", "benchmark/**/*.d.ts"], - "parserOptions": { - "sourceType": "module" - }, - "rules": { - "n/no-unsupported-features/es-syntax": "off", - "no-console": "off" - } - }, - { - "env": { - "es6": true, - "mocha": true, - "node": true - }, - "files": ["packages/build-utils/@glimmer/*/test/**/*.js"], - "rules": { - "n/no-unpublished-import": "off", - "n/no-unsupported-features/es-syntax": "off", - "no-console": "off" - } - }, - // source packages - { - "files": ["packages/**/*.js"], - "parserOptions": { - "sourceType": "module" - } - }, - - { - // these packages need to be fixed to avoid these warnings, but in the - // meantime we should not regress the other packages - "files": [ - // this specific test imports from @glimmer/runtime (causing a cyclic - // dependency), it should either be refactored to use the interfaces - // directly (instead of the impls) or moved into @glimmer/runtime - "packages/@glimmer/reference/test/template-test.ts" - ], - "rules": { - "n/no-extraneous-import": "warn" - } - } - ] -} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5e025ba72d..3048ffe754 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,7 +18,7 @@ jobs: steps: - uses: actions/checkout@v3 - - uses: NullVoxPopuli/action-setup-pnpm@v2 + - uses: NullVoxPopuli/action-setup-pnpm@NullVoxPopuli-patch-1 lint: name: Linting diff --git a/.gitignore b/.gitignore index ada2025bb1..63554302cb 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ /control-dist/ node_modules/ **/node_modules/ +**/.turbo tmp/ /ts-dist/ **/ts-dist @@ -12,3 +13,4 @@ tmp/ *.pdf instrumentation.*.json .cache +**/.yalc diff --git a/.npmcheckrc b/.npmcheckrc new file mode 100644 index 0000000000..4d07f2dba8 --- /dev/null +++ b/.npmcheckrc @@ -0,0 +1,7 @@ +{ + "depcheck": { + "ignoreMatches": [ + "@handlebars/parser" + ] + } +} diff --git a/.vscode/settings.json b/.vscode/settings.json index 0f6bce1902..fc8e324a56 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -14,27 +14,29 @@ "editor.formatOnSave": true, "eslint.enable": true, "eslint.packageManager": "npm", + "eslint.codeAction.showDocumentation": { + "enable": true + }, + "eslint.codeActionsOnSave.mode": "all", + "eslint.lintTask.enable": true, + "eslint.onIgnoredFiles": "warn", "eslint.workingDirectories": [ { - "mode": "location" + "mode": "auto" } ], - "explorer.excludeGitIgnore": true, + "explorer.excludeGitIgnore": false, "files.exclude": { "**/.DS_Store": true, "**/.git": true, - "**/dist/**": true, "**/node_modules/**": true, - "dist/**": true, "node_modules/**": true }, "files.insertFinalNewline": true, "files.trimTrailingWhitespace": true, "files.watcherExclude": { "**/.git/objects/**": true, - "**/.git/subtree-cache/**": true, - "**/dist/**": true, - "dist": true + "**/.git/subtree-cache/**": true }, "javascript.updateImportsOnFileMove.enabled": "always", "typescript.updateImportsOnFileMove.enabled": "always", @@ -48,5 +50,6 @@ "typescript.tsc.autoDetect": "on", "typescript.tsdk": "node_modules/typescript/lib", "typescript.tsserver.experimental.enableProjectDiagnostics": false, - "typescript.workspaceSymbols.scope": "currentProject" + "typescript.workspaceSymbols.scope": "currentProject", + "eslint.problems.shortenToSingleLine": true } diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000000..c91b044925 --- /dev/null +++ b/.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/packages/build-utils/.eslintrc.cjs b/benchmark/.eslintrc.cjs similarity index 91% rename from packages/build-utils/.eslintrc.cjs rename to benchmark/.eslintrc.cjs index 8209270007..0ce1239d85 100644 --- a/packages/build-utils/.eslintrc.cjs +++ b/benchmark/.eslintrc.cjs @@ -1,21 +1,26 @@ +const { resolve } = require('node:path'); + +const tsconfig = resolve(__dirname, 'tsconfig.json'); + /** @type {import("eslint").Linter.Config} */ module.exports = { root: false, overrides: [ { - files: ['*.d.ts', '*.js'], - excludedFiles: ['*/node_modules'], + files: ['*.{js,ts,d.ts,mts'], parserOptions: { ecmaVersion: 'latest', - project: ['packages/build-utils/tsconfig.json'], + project: [tsconfig], }, extends: ['plugin:@typescript-eslint/recommended-requiring-type-checking'], rules: { + '@typescript-eslint/restrict-plus-operands': 'off', '@typescript-eslint/no-require-imports': 'off', + '@typescript-eslint/no-import-type-side-effects': 'error', '@typescript-eslint/consistent-type-imports': [ 'error', { - fixStyle: 'inline-type-imports', + disallowTypeAnnotations: false, }, ], '@typescript-eslint/consistent-type-exports': [ diff --git a/benchmark/benchmarks/krausest/index.html b/benchmark/benchmarks/krausest/index.html new file mode 100644 index 0000000000..8c330daa39 --- /dev/null +++ b/benchmark/benchmarks/krausest/index.html @@ -0,0 +1,12 @@ + + + + + krausest benchmark + + + + diff --git a/benchmark/benchmarks/krausest/lib/components/Application.hbs.d.ts b/benchmark/benchmarks/krausest/lib/components/Application.hbs.d.ts index 39c5906cec..b6a3edc840 100644 --- a/benchmark/benchmarks/krausest/lib/components/Application.hbs.d.ts +++ b/benchmark/benchmarks/krausest/lib/components/Application.hbs.d.ts @@ -1,2 +1,2 @@ -declare const template: import('@glimmer/interfaces').SerializedTemplateWithLazyBlock; +declare const template: import('../../../../../packages/@glimmer/interfaces').SerializedTemplateWithLazyBlock; export default template; diff --git a/benchmark/benchmarks/krausest/lib/components/Row.hbs.d.ts b/benchmark/benchmarks/krausest/lib/components/Row.hbs.d.ts index 39c5906cec..b6a3edc840 100644 --- a/benchmark/benchmarks/krausest/lib/components/Row.hbs.d.ts +++ b/benchmark/benchmarks/krausest/lib/components/Row.hbs.d.ts @@ -1,2 +1,2 @@ -declare const template: import('@glimmer/interfaces').SerializedTemplateWithLazyBlock; +declare const template: import('../../../../../packages/@glimmer/interfaces').SerializedTemplateWithLazyBlock; export default template; diff --git a/benchmark/benchmarks/krausest/lib/index.js b/benchmark/benchmarks/krausest/lib/index.js index ff342d56a4..5fba1ffdb8 100644 --- a/benchmark/benchmarks/krausest/lib/index.js +++ b/benchmark/benchmarks/krausest/lib/index.js @@ -1,4 +1,4 @@ -import { createBenchmark } from '@glimmer/benchmark-env'; +import { createBenchmark } from '@glimmer-workspace/benchmark-env'; import Application from './components/Application'; import ApplicationTemplate from './components/Application.hbs'; @@ -7,7 +7,7 @@ import RowTemplate from './components/Row.hbs'; import buildData from './utils/data'; /** - * @param {HTMLElement | import('@simple-dom/interface').SimpleElement} element + * @param {HTMLElement | import('../../../../packages/@glimmer/interfaces').SimpleElement} element * @param {boolean} isInteractive */ export default async function render(element, isInteractive) { diff --git a/benchmark/benchmarks/krausest/lib/utils/data.js b/benchmark/benchmarks/krausest/lib/utils/data.js index 385f5b71eb..1bc633c868 100644 --- a/benchmark/benchmarks/krausest/lib/utils/data.js +++ b/benchmark/benchmarks/krausest/lib/utils/data.js @@ -1,4 +1,4 @@ -import { createCell } from '@glimmer/benchmark-env'; +import { createCell } from '@glimmer-workspace/benchmark-env'; export class Item { /** @type {number} */ @@ -7,7 +7,6 @@ export class Item { /** @type {string} */ label; - // eslint-disable-next-line no-invalid-this _selected = createCell(this, 'selected', false); /** @@ -32,7 +31,6 @@ export class Item { * @param {number} max */ function _random(max) { - // eslint-disable-next-line no-bitwise return (Math.random() * max) | 0; } diff --git a/benchmark/benchmarks/krausest/package.json b/benchmark/benchmarks/krausest/package.json new file mode 100644 index 0000000000..b34108a115 --- /dev/null +++ b/benchmark/benchmarks/krausest/package.json @@ -0,0 +1,26 @@ +{ + "private": true, + "name": "@glimmer-workspace/krausest", + "dependencies": { + "@glimmer-workspace/benchmark-env": "workspace:^", + "@glimmer/interfaces": "workspace:^", + "@simple-dom/document": "^1.4.0", + "@simple-dom/serializer": "^1.4.0", + "@simple-dom/void-map": "^1.4.0", + "@glimmer/compiler": "workspace:^" + }, + "devDependencies": { + "vite": "^4.3.5", + "@types/node": "^18.16.7" + }, + "engines": { + "node": ">=18.0.0" + }, + "config": { + "tsconfig": "../../tsconfig.json" + }, + "scripts": { + "test:lint": "eslint .", + "test:types": "tsc --noEmit -p ../../tsconfig.json" + } +} \ No newline at end of file diff --git a/benchmark/benchmarks/krausest/vite.config.mts b/benchmark/benchmarks/krausest/vite.config.mts new file mode 100644 index 0000000000..3c4e573d03 --- /dev/null +++ b/benchmark/benchmarks/krausest/vite.config.mts @@ -0,0 +1,24 @@ +import fs from 'node:fs'; + +import { precompile } from '@glimmer/compiler'; +import { defineConfig, type Plugin } from 'vite'; + +export default defineConfig({ + plugins: [benchmark()], +}); + +function benchmark(): Plugin { + return { + name: '@glimmer/benchmark', + load(id) { + /** @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/benchmark/benchmarks/krausest/yalc.lock b/benchmark/benchmarks/krausest/yalc.lock new file mode 100644 index 0000000000..18c9d06057 --- /dev/null +++ b/benchmark/benchmarks/krausest/yalc.lock @@ -0,0 +1,10 @@ +{ + "version": "v1", + "packages": { + "@glimmer/compiler": { + "signature": "46d50e94d7d37d54f6d9ba4314abf1be", + "file": true, + "replaced": "workspace:^" + } + } +} \ No newline at end of file diff --git a/benchmark/bin/control.js b/benchmark/bin/control.js index 5f8ee55ca0..c476f26c0a 100644 --- a/benchmark/bin/control.js +++ b/benchmark/bin/control.js @@ -1,4 +1,4 @@ -// eslint-disable-next-line n/no-unpublished-require + const express = require('express'); const app = express(); diff --git a/benchmark/bin/experiment.js b/benchmark/bin/experiment.js index bcb574e2fd..11bbb5ca0b 100644 --- a/benchmark/bin/experiment.js +++ b/benchmark/bin/experiment.js @@ -1,4 +1,4 @@ -// eslint-disable-next-line n/no-unpublished-require + const express = require('express'); const app = express(); diff --git a/benchmark/lib/build.js b/benchmark/lib/build.js index 14a924871e..03a806f23f 100644 --- a/benchmark/lib/build.js +++ b/benchmark/lib/build.js @@ -1,6 +1,11 @@ -/* eslint-disable no-inline-comments */ +// @ts-check + + const path = require('path'); -const rollup = require('rollup'); +const rollup = /** @type {{rollup: import("rollup").rollup}} */ ( + /** @type {unknown} */ + (require('rollup')) +); const sourcemap = /** @type {import("@rollup/plugin-terser").default} */ ( /** @type {unknown} */ (require('rollup-plugin-sourcemaps')) @@ -37,7 +42,7 @@ async function build(dist, out) { }), terser({ compress: { - // eslint-disable-next-line @typescript-eslint/naming-convention + negate_iife: false, sequences: 0, }, diff --git a/benchmark/package.json b/benchmark/package.json index 8054c40f58..18853414d7 100644 --- a/benchmark/package.json +++ b/benchmark/package.json @@ -3,7 +3,7 @@ "version": "0.84.3", "private": true, "dependencies": { - "@glimmer/benchmark-env": "workspace:^", + "@glimmer-workspace/benchmark-env": "workspace:^", "@simple-dom/document": "^1.4.0", "@simple-dom/serializer": "^1.4.0", "@simple-dom/void-map": "^1.4.0" @@ -17,7 +17,7 @@ "@types/symlink-or-copy": "^1.2.0", "express": "^4.18.2", "fs-extra": "^11.1.1", - "rollup": "^3.21.3", + "rollup": "^3.21.6", "rollup-plugin-sourcemaps": "^0.6.3", "symlink-or-copy": "^1.3.1" } diff --git a/benchmark/tsconfig.json b/benchmark/tsconfig.json index 1a50ab8914..bb93e8772f 100644 --- a/benchmark/tsconfig.json +++ b/benchmark/tsconfig.json @@ -3,10 +3,12 @@ "composite": true, "strict": true, "baseUrl": ".", + "allowJs": true, + "checkJs": true, "target": "es2020", - "module": "NodeNext", - "moduleResolution": "nodenext", + "module": "esnext", + "moduleResolution": "bundler", "verbatimModuleSyntax": true, "suppressImplicitAnyIndexErrors": false, @@ -19,10 +21,21 @@ "outDir": "../ts-dist/bench" }, - "include": ["./index.js", "./lib/**/*.js", "./bin/**/*.js"], + "include": [ + "./index.js", + "./lib/**/*.js", + "./bin/**/*.js", + "./benchmarks/krausest/*.js", + "./benchmarks/krausest/lib/**/*.js", + "./benchmarks/krausest/vite.config.mts" + ], + "exclude": ["**/.yalc"], "references": [ { "path": "../packages/@glimmer/tsconfig.json" + }, + { + "path": "../packages/@glimmer-workspace/tsconfig.json" } ] } diff --git a/bin/.eslintrc.cjs b/bin/.eslintrc.cjs new file mode 100644 index 0000000000..ff785c7aa5 --- /dev/null +++ b/bin/.eslintrc.cjs @@ -0,0 +1,36 @@ +const { resolve } = require('path'); + +const tsconfig = resolve(__dirname, 'tsconfig.json'); + +// node files +module.exports = { + root: false, + env: { + es6: true, + node: true, + }, + overrides: [ + { + files: ['*.{ts,js,d.ts}'], + parserOptions: { + ecmaVersion: 'latest', + project: [tsconfig], + }, + extends: ['plugin:@typescript-eslint/recommended'], + + rules: { + 'dot-notation': 'off', + 'no-console': 'off', + 'no-continue': 'off', + 'n/no-unsupported-features/es-syntax': [ + 'error', + { + ignores: [], + version: '>=16.0.0', + }, + ], + 'n/shebang': 'off', + }, + }, + ], +}; diff --git a/bin/.eslintrc.json b/bin/.eslintrc.json deleted file mode 100644 index db02bfda69..0000000000 --- a/bin/.eslintrc.json +++ /dev/null @@ -1,26 +0,0 @@ -// node files -{ - "root": false, - "env": { - "es6": true, - "node": true - }, - "parserOptions": { - "ecmaVersion": "latest", - "project": ["bin/tsconfig.json"] - }, - "extends": ["plugin:@typescript-eslint/recommended"], - - "rules": { - "dot-notation": "off", - "no-console": "off", - "n/no-unsupported-features/es-syntax": [ - "error", - { - "ignores": [], - "version": ">=16.0.0" - } - ], - "n/shebang": "off" - } -} diff --git a/bin/package.json b/bin/package.json index 1cb23732e7..7b52d9822e 100644 --- a/bin/package.json +++ b/bin/package.json @@ -1,17 +1,28 @@ { + "name": "@glimmer-workspace/bin", "private": true, "dependencies": { "puppeteer-chromium-resolver": "^20.0.0", "chalk": "^5.2.0", "execa": "^7.1.1", "js-yaml": "^4.1.0", - "glob": "^10.2.2", + "glob": "^10.2.3", "@types/glob": "^8.1.0", "@types/js-yaml": "^4.0.5", - "@types/node": "^20.1.1", + "@types/node": "^18.16.7", "@types/puppeteer-chromium-resolver": "workspace:^" }, + "devDependencies": { + "esno": "^0.16.3" + }, "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" + }, + "config": { + "tsconfig": "./tsconfig.json" + }, + "scripts": { + "test:lint": "eslint .", + "test:types": "tsc --noEmit -p ./tsconfig.json" } -} +} \ No newline at end of file diff --git a/bin/packages.mts b/bin/packages.mts new file mode 100644 index 0000000000..0a49eca317 --- /dev/null +++ b/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/bin/run-types-tests.mjs b/bin/run-types-tests.mjs index dd2907247b..a96b64607a 100755 --- a/bin/run-types-tests.mjs +++ b/bin/run-types-tests.mjs @@ -23,24 +23,10 @@ async function main() { for (const pkg of packages) { try { console.log(`# Smoke testing ${pkg.name}`); - await execa( - 'tsc', - [ - '--noEmit', - '--target', - 'ES2015', - '--module', - 'esnext', - '--moduleResolution', - 'nodenext', - '-p', - resolve(root, 'tsconfig.dist.json'), - ], - { - cwd: resolve(pkg.path, 'dist'), - preferLocal: true, - } - ); + 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); diff --git a/bin/tsconfig.json b/bin/tsconfig.json index b069d6c72d..cba49b2922 100644 --- a/bin/tsconfig.json +++ b/bin/tsconfig.json @@ -22,5 +22,5 @@ "noPropertyAccessFromIndexSignature": true, "noUncheckedIndexedAccess": true }, - "include": ["*.mjs"] + "include": ["*.mjs", "*.mts", "*.ts"] } diff --git a/bin/update-package-json.mts b/bin/update-package-json.mts new file mode 100644 index 0000000000..a5196ad04f --- /dev/null +++ b/bin/update-package-json.mts @@ -0,0 +1,177 @@ +import { existsSync, readFileSync, writeFileSync } from 'node:fs'; +import { resolve } from 'node:path'; + +import chalk from 'chalk'; + +import { type Package, 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: PackageJSON = JSON.parse( + readFileSync(`${pkg.path}/package.json`, { encoding: 'utf-8' }) + ); + 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/bin/yalc-publish.mts b/bin/yalc-publish.mts new file mode 100644 index 0000000000..82da0f4b33 --- /dev/null +++ b/bin/yalc-publish.mts @@ -0,0 +1,13 @@ +import { execSync } from 'node:child_process'; + +import chalk from 'chalk'; + +import { packages } from './packages.mjs'; + +for (const pkg of packages('@glimmer')) { + console.log(`${chalk.gray('# publishing')} ${chalk.cyanBright(pkg.name)}`); + execSync('yalc publish --push', { + cwd: pkg.path, + stdio: 'inherit', + }); +} diff --git a/build/.eslintrc.json b/build/.eslintrc.json deleted file mode 100644 index f9f025563d..0000000000 --- a/build/.eslintrc.json +++ /dev/null @@ -1,16 +0,0 @@ -// node files -{ - "root": false, - "env": { - "es6": true, - "node": true - }, - "parserOptions": { - "ecmaVersion": "latest", - "project": ["build/tsconfig.json"] - }, - - "rules": { - "no-console": "off" - } -} diff --git a/build/debug.js b/build/debug.js deleted file mode 100644 index b854d201b3..0000000000 --- a/build/debug.js +++ /dev/null @@ -1,85 +0,0 @@ -// @ts-check - -const fs = require('node:fs'); -const toml = require('toml'); -const prettier = require('prettier'); -const { normalizeAll, buildEnum, buildMetas, strip } = require('@glimmer/debug'); - -function parse(file) { - let opcodes = fs.readFileSync(file, { encoding: 'utf8' }); - let raw = toml.parse(opcodes); - return normalizeAll(raw); -} - -let parsed = parse('./packages/@glimmer/vm/lib/opcodes.toml'); - -let machine = buildEnum('MachineOp', parsed.machine, 0, 15); -let syscall = buildEnum('Op', parsed.syscall, 16); - -write( - './packages/@glimmer/vm/lib/opcodes.ts', - `import { Op, MachineOp } from '@glimmer/interfaces';\n\n` + - machine.predicate + - '\n' + - syscall.predicate -); - -write( - './packages/@glimmer/interfaces/lib/vm-opcodes.d.ts', - machine.enumString + '\n\n' + syscall.enumString -); - -let debugMetadata = strip` - import { MachineOp, Op, Option } from '@glimmer/interfaces'; - import { NormalizedMetadata } from './metadata'; - - function fillNulls(count: number): T[] { - let arr = new Array(count); - - for (let i = 0; i < count; i++) { - arr[i] = null; - } - - return arr; - } - - export function opcodeMetadata(op: MachineOp | Op, isMachine: 0 | 1): Option { - let value = isMachine ? MACHINE_METADATA[op] : METADATA[op]; - - return value || null; - } - - const METADATA: Option[] = fillNulls(Op.Size); - const MACHINE_METADATA: Option[] = fillNulls(MachineOp.Size); -`; - -debugMetadata += buildMetas('MACHINE_METADATA', parsed.machine); -debugMetadata += buildMetas('METADATA', parsed.syscall); - -write('./packages/@glimmer/debug/lib/opcode-metadata.ts', debugMetadata); - -function write(file, contents) { - console.log(`Generating ${file}`); - - format( - file, - strip` -/* This file is generated by build/debug.js */ - -${contents} - ` - ); -} - -/* - Formats the string in accordance with our prettier rules to avoid - test failures. -*/ -function format(file, contents) { - let options = prettier.resolveConfig.sync(file); - let newContents = prettier.format(contents, Object.assign({}, options, { filepath: file })); - - if (newContents !== contents) { - fs.writeFileSync(file, newContents, { encoding: 'utf8' }); - } -} diff --git a/build/package.json b/build/package.json deleted file mode 100644 index 0562e8112e..0000000000 --- a/build/package.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "private": true, - "dependencies": { - "@glimmer/debug": "workspace:^", - "toml": "^3.0.0", - "prettier": "^2.8.8" - }, - "devDependencies": { - "@types/prettier": "^2.7.2", - "@types/node": "^20.1.1" - } -} diff --git a/build/tsconfig.json b/build/tsconfig.json deleted file mode 100644 index 72e5e046e5..0000000000 --- a/build/tsconfig.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "compilerOptions": { - "composite": true, - "baseUrl": ".", - "allowJs": true, - "outDir": "../ts-dist/build", - "skipLibCheck": true - }, - "files": ["debug.js"], - "references": [{ "path": "../packages/@glimmer/tsconfig.json" }] -} diff --git a/index.html b/index.html index d923761d6a..1c25f9143b 100644 --- a/index.html +++ b/index.html @@ -1,39 +1,43 @@ - - - - Glimmer Test Suite - - - - - + - - + await pkg(); + } + QUnit.start(); + + diff --git a/lib/local-linker/package.json b/lib/local-linker/package.json index cca3e5de2f..c14b21fbe4 100644 --- a/lib/local-linker/package.json +++ b/lib/local-linker/package.json @@ -1,6 +1,6 @@ { "name": "local-linker", - "version": "workspace:^", + "version": "0.84.3", "private": true, "keywords": [ "ember-addon" diff --git a/package.json b/package.json index e2d8d29925..0940583164 100644 --- a/package.json +++ b/package.json @@ -16,30 +16,27 @@ "browserstack:connect": "ember browserstack:connect", "browserstack:disconnect": "ember browserstack:disconnect", "browserstack:results": "ember browserstack:results", - "build": "rollup -c rollup.config.mjs", + "build": "dotenv -- turbo build", + "build:control": "rollup -c rollup.config.mjs", "build:flags": "RETAIN_FLAGS=true ember build --env production --suppress-sizes", - "build:typecheck": "tsc -p tsconfig.json --noEmit --pretty false", "lint": "npm-run-all lint:*", - "lint:files": "eslint . --cache", + "lint:files": "dotenv -- turbo lint", "force:lint:files": "eslint .", - "lint:types": "tsc -p tsconfig.json --noEmit", + "lint:types": "tsc -b", "start": "ember serve --port=7357", "test": "node bin/run-tests.mjs", "test:browserstack": "ember test --test-port=7774 --host 127.0.0.1 --config-file=testem-browserstack.js", "test:node": "node bin/run-node-tests.mjs", "test:babel-plugins": "yarn workspace @glimmer/vm-babel-plugins test", "test:smoke": "SMOKE_TESTS=true ember test", - "test:types": "node bin/run-types-tests.mjs" + "test:types": "node bin/run-types-tests.mjs", + "test:typecheck": "tsc -b" }, "pnpm": { "overrides": { "typescript": "$typescript", "@rollup/pluginutils": "^5.0.2", - "@types/node": "$@types/node", - "@simple-dom/document": "$@simple-dom/document", - "@simple-dom/interface": "$@simple-dom/interface", - "@simple-dom/serializer": "$@simple-dom/serializer", - "@simple-dom/void-map": "$@simple-dom/void-map" + "@types/node": "$@types/node" }, "peerDependencyRules": { "allowedVersions": { @@ -49,18 +46,9 @@ } } }, - "dependencies": { - "@handlebars/parser": "~2.0.0", - "@simple-dom/document": "^1.4.0", - "@simple-dom/interface": "^1.4.0", - "@simple-dom/serializer": "^1.4.0", - "@simple-dom/void-map": "^1.4.0", - "fs-extra": "^11.1.1", - "simple-html-tokenizer": "^0.5.11", - "symlink-or-copy": "^1.3.1" - }, "devDependencies": { - "@babel/core": "^7.21.8", + "@glimmer-workspace/eslint-plugin": "workspace:^", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", "@babel/plugin-transform-modules-commonjs": "^7.21.5", "@babel/plugin-transform-runtime": "^7.21.4", "@babel/preset-env": "^7.21.5", @@ -68,24 +56,26 @@ "@babel/runtime": "^7.21.5", "@babel/traverse": "^7.21.5", "@babel/types": "^7.21.5", - "@glimmer/build-support": "workspace:^", + "@glimmer-workspace/build-support": "workspace:^", + "@glimmer-workspace/integration-tests": "workspace:^", "@glimmer/env": "0.1.7", - "@glimmer/integration-tests": "workspace:^", "@rollup/plugin-terser": "^0.4.1", "@types/babel-plugin-macros": "^3.1.0", + "@types/babel__core": "^7.20.0", "@types/babel__traverse": "^7.18.5", - "@types/broccoli-plugin": "^3.0.0", - "@types/node": "^20.1.0", + "@types/eslint": "^8.37.0", + "@types/node": "^18.16.6", "@types/preval.macro": "^3.0.0", "@types/qunit": "workspace:^", - "@typescript-eslint/eslint-plugin": "^5.59.2", - "@typescript-eslint/parser": "^5.59.2", + "@typescript-eslint/eslint-plugin": "^5.59.5", + "@typescript-eslint/parser": "^5.59.5", "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.2.0", "dag-map": "^2.0.2", + "dotenv-cli": "^7.2.1", "ember-cli": "~4.12.1", "ember-cli-browserstack": "^2.0.1", "ensure-posix-path": "^1.1.1", @@ -94,13 +84,12 @@ "eslint-import-resolver-typescript": "^3.5.5", "eslint-plugin-import": "^2.27.5", "eslint-plugin-n": "^15.7.0", - "eslint-plugin-prettier": "^4.2.1", "eslint-plugin-qunit": "^7.3.4", "eslint-plugin-simple-import-sort": "^10.0.0", "eslint-plugin-unused-imports": "^2.0.0", "execa": "^7.1.1", "fast-glob": "^3.2.12", - "glob": "^10.2.2", + "glob": "^10.2.3", "js-yaml": "^4.1.0", "loader.js": "^4.7.0", "mkdirp": "^3.0.1", @@ -111,12 +100,15 @@ "puppeteer-chromium-resolver": "^20.0.0", "qunit": "^2.19.4", "rimraf": "^5.0.0", - "rollup": "^3.21.5", + "rollup": "^3.21.6", "semver": "^7.5.0", "testem-failure-only-reporter": "^1.0.0", "toml": "^3.0.0", + "ts-node": "^10.9.1", + "turbo": "^1.9.3", "typescript": "^5.0.4", - "vite": "^4.3.5" + "vite": "^4.3.5", + "xo": "^0.54.2" }, "publishConfig": { "registry": "https://registry.npmjs.org" @@ -140,7 +132,7 @@ "node": ">=16.0.0" }, "volta": { - "node": "16.20.0", - "pnpm": "8.4.0" + "node": "20.1.0", + "pnpm": "8.5.0" } } diff --git a/packages/@glimmer-workspace/.eslintrc.cjs b/packages/@glimmer-workspace/.eslintrc.cjs new file mode 100644 index 0000000000..fabd8c582a --- /dev/null +++ b/packages/@glimmer-workspace/.eslintrc.cjs @@ -0,0 +1,20 @@ +const { resolve } = require('path'); + +const tsconfig = resolve(__dirname, 'tsconfig.json'); + +/** @type {import("eslint").Linter.Config} */ +module.exports = { + root: false, + overrides: [ + { + files: ['*/index.{js,ts,d.ts}', '*/lib/**/*.{js,ts,d.ts}', '*/test/**/*.{js,ts,d.ts}'], + excludedFiles: ['node_modules', '*/node_modules'], + parserOptions: { + ecmaVersion: 'latest', + project: [tsconfig], + }, + plugins: ['@glimmer-workspace'], + extends: ['plugin:@glimmer-workspace/recommended'], + }, + ], +}; diff --git a/packages/@glimmer/benchmark-env/index.ts b/packages/@glimmer-workspace/benchmark-env/index.ts similarity index 100% rename from packages/@glimmer/benchmark-env/index.ts rename to packages/@glimmer-workspace/benchmark-env/index.ts diff --git a/packages/@glimmer/benchmark-env/lib/benchmark/args-proxy.ts b/packages/@glimmer-workspace/benchmark-env/lib/benchmark/args-proxy.ts similarity index 82% rename from packages/@glimmer/benchmark-env/lib/benchmark/args-proxy.ts rename to packages/@glimmer-workspace/benchmark-env/lib/benchmark/args-proxy.ts index bc58e01f57..d8183833fe 100644 --- a/packages/@glimmer/benchmark-env/lib/benchmark/args-proxy.ts +++ b/packages/@glimmer-workspace/benchmark-env/lib/benchmark/args-proxy.ts @@ -1,11 +1,7 @@ -import { - type CapturedArguments, - type CapturedNamedArguments, - type Reference, -} from '@glimmer/interfaces'; +import type { CapturedArguments, CapturedNamedArguments, Reference } from '@glimmer/interfaces'; import { valueForRef } from '@glimmer/reference'; -import { type ComponentArgs } from '../interfaces'; +import type { ComponentArgs } from '../interfaces'; class ArgsProxy implements ProxyHandler { isExtensible() { @@ -37,7 +33,7 @@ class ArgsProxy implements ProxyHandler { return typeof p === 'string' ? p in target : false; } - get(target: CapturedNamedArguments, p: PropertyKey): any { + get(target: CapturedNamedArguments, p: PropertyKey): unknown { if (typeof p === 'string' && p in target) { return valueForRef(target[p] as Reference); } diff --git a/packages/@glimmer/benchmark-env/lib/benchmark/basic-component-manager.ts b/packages/@glimmer-workspace/benchmark-env/lib/benchmark/basic-component-manager.ts similarity index 89% rename from packages/@glimmer/benchmark-env/lib/benchmark/basic-component-manager.ts rename to packages/@glimmer-workspace/benchmark-env/lib/benchmark/basic-component-manager.ts index 582312074b..2e3e4d2612 100644 --- a/packages/@glimmer/benchmark-env/lib/benchmark/basic-component-manager.ts +++ b/packages/@glimmer-workspace/benchmark-env/lib/benchmark/basic-component-manager.ts @@ -1,15 +1,15 @@ -import { - type Dict, - type Owner, - type Template, - type VMArguments, - type WithCreateInstance, -} from '@glimmer/interfaces'; +import type { + Dict, + Owner, + Template, + VMArguments, + WithCreateInstance, +} from "@glimmer/interfaces"; import { getComponentTemplate } from '@glimmer/manager'; import { createConstRef, type Reference } from '@glimmer/reference'; import { EMPTY_ARGS } from '@glimmer/runtime'; -import { type ComponentArgs } from '../interfaces'; +import type { ComponentArgs } from '../interfaces'; import argsProxy from './args-proxy'; const BASIC_COMPONENT_CAPABILITIES = { diff --git a/packages/@glimmer/benchmark-env/lib/benchmark/create-env-delegate.ts b/packages/@glimmer-workspace/benchmark-env/lib/benchmark/create-env-delegate.ts similarity index 92% rename from packages/@glimmer/benchmark-env/lib/benchmark/create-env-delegate.ts rename to packages/@glimmer-workspace/benchmark-env/lib/benchmark/create-env-delegate.ts index 3b04cef497..6f53f90c2a 100644 --- a/packages/@glimmer/benchmark-env/lib/benchmark/create-env-delegate.ts +++ b/packages/@glimmer-workspace/benchmark-env/lib/benchmark/create-env-delegate.ts @@ -1,7 +1,8 @@ /* eslint-disable no-console */ + import setGlobalContext from '@glimmer/global-context'; -import { type Destroyable, type Destructor, type RenderResult } from '@glimmer/interfaces'; -import { type EnvironmentDelegate } from '@glimmer/runtime'; +import type { Destroyable, Destructor, RenderResult } from '@glimmer/interfaces'; +import type { EnvironmentDelegate } from '@glimmer/runtime'; type Queue = (() => void)[]; @@ -85,7 +86,9 @@ setGlobalContext({ return null; }, - warnIfStyleNotTrusted() {}, + warnIfStyleNotTrusted() { + // noop + }, scheduleDestroy(destroyable: T, destructor: Destructor) { scheduledDestructors.push(() => destructor(destroyable)); @@ -103,7 +106,6 @@ setGlobalContext({ deprecate(msg: string, test: unknown) { if (!test) { - // eslint-disable-next-line no-console console.warn(msg); } }, diff --git a/packages/@glimmer/benchmark-env/lib/benchmark/create-registry.ts b/packages/@glimmer-workspace/benchmark-env/lib/benchmark/create-registry.ts similarity index 91% rename from packages/@glimmer/benchmark-env/lib/benchmark/create-registry.ts rename to packages/@glimmer-workspace/benchmark-env/lib/benchmark/create-registry.ts index 7d8b322d90..4429f376fd 100644 --- a/packages/@glimmer/benchmark-env/lib/benchmark/create-registry.ts +++ b/packages/@glimmer-workspace/benchmark-env/lib/benchmark/create-registry.ts @@ -1,12 +1,12 @@ -import { - type Dict, - type Helper, - type HelperDefinitionState, - type InternalModifierManager, - type ModifierDefinitionState, - type ResolvedComponentDefinition, - type SimpleElement, -} from '@glimmer/interfaces'; +import type { + Dict, + Helper, + HelperDefinitionState, + InternalModifierManager, + ModifierDefinitionState, + ResolvedComponentDefinition, + SimpleElement, +} from "@glimmer/interfaces"; import { getComponentTemplate, getInternalComponentManager, @@ -16,7 +16,7 @@ import { import { programCompilationContext } from '@glimmer/opcode-compiler'; import { artifacts, RuntimeOpImpl } from '@glimmer/program'; -import { type UpdateBenchmark } from '../interfaces'; +import type { UpdateBenchmark } from '../interfaces'; import renderBenchmark from './render-benchmark'; export interface Registry { diff --git a/packages/@glimmer/benchmark-env/lib/benchmark/on-modifier.ts b/packages/@glimmer-workspace/benchmark-env/lib/benchmark/on-modifier.ts similarity index 92% rename from packages/@glimmer/benchmark-env/lib/benchmark/on-modifier.ts rename to packages/@glimmer-workspace/benchmark-env/lib/benchmark/on-modifier.ts index afa9173e94..33597adf88 100644 --- a/packages/@glimmer/benchmark-env/lib/benchmark/on-modifier.ts +++ b/packages/@glimmer-workspace/benchmark-env/lib/benchmark/on-modifier.ts @@ -1,9 +1,9 @@ -import { - type CapturedArguments, - type InternalModifierManager, - type Owner, - type SimpleElement, -} from '@glimmer/interfaces'; +import type { + CapturedArguments, + InternalModifierManager, + Owner, + SimpleElement, +} from "@glimmer/interfaces"; import { type Reference, valueForRef } from '@glimmer/reference'; import { castToBrowser } from '@glimmer/util'; import { createUpdatableTag } from '@glimmer/validator'; diff --git a/packages/@glimmer/benchmark-env/lib/benchmark/render-benchmark.ts b/packages/@glimmer-workspace/benchmark-env/lib/benchmark/render-benchmark.ts similarity index 86% rename from packages/@glimmer/benchmark-env/lib/benchmark/render-benchmark.ts rename to packages/@glimmer-workspace/benchmark-env/lib/benchmark/render-benchmark.ts index df3366c059..d68e878215 100644 --- a/packages/@glimmer/benchmark-env/lib/benchmark/render-benchmark.ts +++ b/packages/@glimmer-workspace/benchmark-env/lib/benchmark/render-benchmark.ts @@ -1,14 +1,14 @@ -import { - type CompileTimeCompilationContext, - type Dict, - type ResolvedComponentDefinition, - type RuntimeArtifacts, - type RuntimeResolver, - type SimpleElement, -} from '@glimmer/interfaces'; +import type { + CompileTimeCompilationContext, + Dict, + ResolvedComponentDefinition, + RuntimeArtifacts, + RuntimeResolver, + SimpleElement, +} from "@glimmer/interfaces"; import { NewElementBuilder, renderComponent, renderSync, runtimeContext } from '@glimmer/runtime'; -import { type UpdateBenchmark } from '../interfaces'; +import type { UpdateBenchmark } from '../interfaces'; import createEnvDelegate, { registerResult } from './create-env-delegate'; import { measureRender } from './util'; diff --git a/packages/@glimmer/benchmark-env/lib/benchmark/util.ts b/packages/@glimmer-workspace/benchmark-env/lib/benchmark/util.ts similarity index 88% rename from packages/@glimmer/benchmark-env/lib/benchmark/util.ts rename to packages/@glimmer-workspace/benchmark-env/lib/benchmark/util.ts index 70e8e52b9a..7d9d8256f8 100644 --- a/packages/@glimmer/benchmark-env/lib/benchmark/util.ts +++ b/packages/@glimmer-workspace/benchmark-env/lib/benchmark/util.ts @@ -1,4 +1,7 @@ -import { type CompileTimeCompilationContext, type CompileTimeComponent } from '@glimmer/interfaces'; +import type { + CompileTimeCompilationContext, + CompileTimeComponent, +} from "@glimmer/interfaces"; import { unwrapHandle } from '@glimmer/util'; export function compileEntry(entry: CompileTimeComponent, context: CompileTimeCompilationContext) { diff --git a/packages/@glimmer/benchmark-env/lib/create-benchmark.ts b/packages/@glimmer-workspace/benchmark-env/lib/create-benchmark.ts similarity index 95% rename from packages/@glimmer/benchmark-env/lib/create-benchmark.ts rename to packages/@glimmer-workspace/benchmark-env/lib/create-benchmark.ts index b518fdc1a7..cf53503a2d 100644 --- a/packages/@glimmer/benchmark-env/lib/create-benchmark.ts +++ b/packages/@glimmer-workspace/benchmark-env/lib/create-benchmark.ts @@ -5,7 +5,7 @@ import { templateOnlyComponent } from '@glimmer/runtime'; import basicComponentManager from './benchmark/basic-component-manager'; import createRegistry from './benchmark/create-registry'; import onModifier from './benchmark/on-modifier'; -import { type Benchmark } from './interfaces'; +import type { Benchmark } from './interfaces'; export default function createBenchmark(): Benchmark { const registry = createRegistry(); diff --git a/packages/@glimmer/benchmark-env/lib/create-cell.ts b/packages/@glimmer-workspace/benchmark-env/lib/create-cell.ts similarity index 95% rename from packages/@glimmer/benchmark-env/lib/create-cell.ts rename to packages/@glimmer-workspace/benchmark-env/lib/create-cell.ts index 5f314dc788..400bf9d357 100644 --- a/packages/@glimmer/benchmark-env/lib/create-cell.ts +++ b/packages/@glimmer-workspace/benchmark-env/lib/create-cell.ts @@ -7,7 +7,7 @@ import { type UpdatableTag, } from '@glimmer/validator'; -import { type Cell } from './interfaces'; +import type { Cell } from './interfaces'; class CellImpl implements Cell { private _meta: TagMeta; diff --git a/packages/@glimmer/benchmark-env/lib/interfaces.ts b/packages/@glimmer-workspace/benchmark-env/lib/interfaces.ts similarity index 92% rename from packages/@glimmer/benchmark-env/lib/interfaces.ts rename to packages/@glimmer-workspace/benchmark-env/lib/interfaces.ts index acd00aed0a..8a4ed82409 100644 --- a/packages/@glimmer/benchmark-env/lib/interfaces.ts +++ b/packages/@glimmer-workspace/benchmark-env/lib/interfaces.ts @@ -1,8 +1,8 @@ -import { - type Dict, - type SerializedTemplateWithLazyBlock, - type SimpleElement, -} from '@glimmer/interfaces'; +import type { + Dict, + SerializedTemplateWithLazyBlock, + SimpleElement, +} from "@glimmer/interfaces"; /** * This abstracts a tracked root. diff --git a/packages/@glimmer/benchmark-env/package.json b/packages/@glimmer-workspace/benchmark-env/package.json similarity index 65% rename from packages/@glimmer/benchmark-env/package.json rename to packages/@glimmer-workspace/benchmark-env/package.json index 1c370dfd54..84d6d43289 100644 --- a/packages/@glimmer/benchmark-env/package.json +++ b/packages/@glimmer-workspace/benchmark-env/package.json @@ -1,8 +1,12 @@ { - "name": "@glimmer/benchmark-env", + "name": "@glimmer-workspace/benchmark-env", "version": "0.84.3", "private": true, - "repository": "https://github.com/glimmerjs/glimmer-vm/tree/master/packages/@glimmer/benchmark-env", + "engines": { + "node": ">=16" + }, + "main": "index.ts", + "repository": "https://github.com/glimmerjs/glimmer-vm/tree/master/packages/@glimmer-workspace/benchmark-env", "dependencies": { "@glimmer/global-context": "workspace:^", "@glimmer/interfaces": "workspace:^", @@ -13,5 +17,9 @@ "@glimmer/runtime": "workspace:^", "@glimmer/util": "workspace:^", "@glimmer/validator": "workspace:^" + }, + "scripts": { + "test:lint": "eslint .", + "test:types": "tsc --noEmit -p ../tsconfig.json" } -} +} \ No newline at end of file diff --git a/packages/build-utils/@glimmer/build/.npmrc b/packages/@glimmer-workspace/build/.npmrc similarity index 100% rename from packages/build-utils/@glimmer/build/.npmrc rename to packages/@glimmer-workspace/build/.npmrc diff --git a/packages/build-utils/@glimmer/build/README.md b/packages/@glimmer-workspace/build/README.md similarity index 100% rename from packages/build-utils/@glimmer/build/README.md rename to packages/@glimmer-workspace/build/README.md diff --git a/packages/build-utils/@glimmer/build/index.d.ts b/packages/@glimmer-workspace/build/index.d.ts similarity index 100% rename from packages/build-utils/@glimmer/build/index.d.ts rename to packages/@glimmer-workspace/build/index.d.ts diff --git a/packages/build-utils/@glimmer/build/index.js b/packages/@glimmer-workspace/build/index.js similarity index 100% rename from packages/build-utils/@glimmer/build/index.js rename to packages/@glimmer-workspace/build/index.js diff --git a/packages/build-utils/@glimmer/build/lib/config.d.ts b/packages/@glimmer-workspace/build/lib/config.d.ts similarity index 100% rename from packages/build-utils/@glimmer/build/lib/config.d.ts rename to packages/@glimmer-workspace/build/lib/config.d.ts diff --git a/packages/build-utils/@glimmer/build/lib/config.js b/packages/@glimmer-workspace/build/lib/config.js similarity index 91% rename from packages/build-utils/@glimmer/build/lib/config.js rename to packages/@glimmer-workspace/build/lib/config.js index 9d79eef5c9..2cb782079b 100644 --- a/packages/build-utils/@glimmer/build/lib/config.js +++ b/packages/@glimmer-workspace/build/lib/config.js @@ -11,7 +11,8 @@ import ts from 'typescript'; import importMeta from './import-meta.js'; import inline from './inline.js'; -const { ImportsNotUsedAsValues, ModuleKind, ModuleResolutionKind, ScriptTarget } = ts; +// eslint-disable-next-line import/no-named-as-default-member +const { ModuleKind, ModuleResolutionKind, ScriptTarget, ImportsNotUsedAsValues } = ts; const { default: commonjs } = await import('@rollup/plugin-commonjs'); const { default: nodeResolve } = await import('@rollup/plugin-node-resolve'); @@ -57,24 +58,12 @@ const EXTERNAL = true; */ export function tsconfig(updates) { return { - strict: true, declaration: true, declarationMap: true, - useDefineForClassFields: true, - allowSyntheticDefaultImports: true, - esModuleInterop: true, - resolveJsonModule: true, + verbatimModuleSyntax: true, module: ModuleKind.NodeNext, moduleResolution: ModuleResolutionKind.NodeNext, experimentalDecorators: true, - noUnusedLocals: false, - noUnusedParameters: false, - noImplicitReturns: true, - noImplicitAny: true, - importsNotUsedAsValues: ImportsNotUsedAsValues.Error, - isolatedModules: true, - skipLibCheck: true, - skipDefaultLibCheck: true, ...updates, }; } @@ -85,7 +74,13 @@ export function tsconfig(updates) { * @returns {RollupPlugin} */ export function typescript(pkg, config) { - const typeScriptConfig = { ...config }; + const typeScriptConfig = { + ...config, + paths: { + '@glimmer/interfaces': [resolve(pkg.root, '../@glimmer/interfaces/index.d.ts')], + '@glimmer/*': [resolve(pkg.root, '../@glimmer/*/src/dist/index.d.ts')], + }, + }; /** @type {[string, object][]} */ const presets = [['@babel/preset-typescript', { allowDeclareFields: true }]]; @@ -103,10 +98,10 @@ export function typescript(pkg, config) { /** @type {['is' | 'startsWith', string[], 'inline' | 'external'][]} */ const EXTERNAL_OPTIONS = [ - ['is', ['tslib'], 'inline'], + ['is', ['tslib', '@glimmer/local-debug-flags'], 'inline'], ['is', ['@handlebars/parser', 'simple-html-tokenizer', 'babel-plugin-debug-macros'], 'external'], ['startsWith', ['.', '/', '#', '@babel/runtime/'], 'inline'], - ['startsWith', ['@glimmer/', '@simple-dom/'], 'external'], + ['startsWith', ['@glimmer/', '@simple-dom/', '@babel/', 'node:'], 'external'], ]; /** @@ -292,6 +287,7 @@ export class Package { postcss(), typescript(this.#package, { target: ScriptTarget.ES2022, + importsNotUsedAsValues: ImportsNotUsedAsValues.Preserve, }), ], })); @@ -349,15 +345,20 @@ export class Package { const ext = format === 'esm' ? 'js' : 'cjs'; + const experiment = process.env['GLIMMER_EXPERIMENT']; + /** * @param {[string, string]} entry * @returns {import("rollup").RollupOptions} */ function entryPoint([exportName, ts]) { + const file = + experiment === undefined ? `${exportName}.${ext}` : `${exportName}.${experiment}.${ext}`; + return { input: resolve(root, ts), output: { - file: resolve(root, 'dist', `${exportName}.${ext}`), + file: resolve(root, 'dist', file), format, sourcemap: true, exports: format === 'cjs' ? 'named' : 'auto', @@ -391,6 +392,5 @@ async function viteConfig(config) { * @returns {T} */ function parse(string) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-return return JSON.parse(string); } diff --git a/packages/build-utils/@glimmer/build/lib/import-meta.d.ts b/packages/@glimmer-workspace/build/lib/import-meta.d.ts similarity index 100% rename from packages/build-utils/@glimmer/build/lib/import-meta.d.ts rename to packages/@glimmer-workspace/build/lib/import-meta.d.ts diff --git a/packages/build-utils/@glimmer/build/lib/import-meta.js b/packages/@glimmer-workspace/build/lib/import-meta.js similarity index 94% rename from packages/build-utils/@glimmer/build/lib/import-meta.js rename to packages/@glimmer-workspace/build/lib/import-meta.js index da91f55681..f705c5079f 100644 --- a/packages/build-utils/@glimmer/build/lib/import-meta.js +++ b/packages/@glimmer-workspace/build/lib/import-meta.js @@ -8,7 +8,7 @@ const PROD = MODE === 'production'; const STARBEAM_TRACE = process.env['STARBEAM_TRACE'] ?? false; export default createReplacePlugin( - (id) => /\.(j|t)sx?$/.test(id), + (id) => /\.[jt]sx?$/u.test(id), { 'import.meta.env.MODE': process.env['MODE'] ?? 'development', 'import.meta.env.DEV': DEV ? 'true' : 'false', diff --git a/packages/build-utils/@glimmer/build/lib/inline.d.ts b/packages/@glimmer-workspace/build/lib/inline.d.ts similarity index 100% rename from packages/build-utils/@glimmer/build/lib/inline.d.ts rename to packages/@glimmer-workspace/build/lib/inline.d.ts diff --git a/packages/build-utils/@glimmer/build/lib/inline.js b/packages/@glimmer-workspace/build/lib/inline.js similarity index 100% rename from packages/build-utils/@glimmer/build/lib/inline.js rename to packages/@glimmer-workspace/build/lib/inline.js diff --git a/packages/build-utils/@glimmer/build/lib/replace.d.ts b/packages/@glimmer-workspace/build/lib/replace.d.ts similarity index 100% rename from packages/build-utils/@glimmer/build/lib/replace.d.ts rename to packages/@glimmer-workspace/build/lib/replace.d.ts diff --git a/packages/build-utils/@glimmer/build/lib/replace.js b/packages/@glimmer-workspace/build/lib/replace.js similarity index 97% rename from packages/build-utils/@glimmer/build/lib/replace.js rename to packages/@glimmer-workspace/build/lib/replace.js index 31c8e0f509..2e6977c502 100644 --- a/packages/build-utils/@glimmer/build/lib/replace.js +++ b/packages/@glimmer-workspace/build/lib/replace.js @@ -20,7 +20,7 @@ export function createReplacePlugin(test, replacements, sourcemap) { '\\b(' + Object.keys(replacements) .map((str) => { - return str.replace(/[-[\]/{}()*+?.\\^$|]/g, '\\$&'); + return str.replace(/[$()*+\-./?[\\\]^{|}]/gu, '\\$&'); }) .join('|') + ')\\b', diff --git a/packages/build-utils/@glimmer/build/package.json b/packages/@glimmer-workspace/build/package.json similarity index 53% rename from packages/build-utils/@glimmer/build/package.json rename to packages/@glimmer-workspace/build/package.json index e75d169352..b718493554 100644 --- a/packages/build-utils/@glimmer/build/package.json +++ b/packages/@glimmer-workspace/build/package.json @@ -1,40 +1,28 @@ { "private": true, - "name": "@glimmer/build-support", - "version": "1.0.0", + "name": "@glimmer-workspace/build-support", "type": "module", - "main": "index.js", - "types": "index.d.ts", + "version": "1.0.0", + "main": "index.mjs", + "types": "index.d.mts", + "engines": { + "node": ">=16" + }, "exports": { "default": "./index.js" }, - "publishConfig": { - "exports": { - ".": { - "types": "./dist/index.d.ts", - "import": "./dist/index.js", - "default": "./dist/index.cjs" - } - }, - "main": "dist/index.cjs", - "types": "dist/index.d.ts" - }, "starbeam": { "source": "js:typed", "type": "library:build-support" }, "scripts": { - "test:lint": "eslint \"src/**/*.{js,d.ts}\"", - "test:types": "tsc -b" + "test:lint": "eslint .", + "test:types": "tsc --noEmit -p ../tsconfig.json" }, "dependencies": { - "@esbuild-plugins/node-globals-polyfill": "^0.2.3", - "@eslint/eslintrc": "^2.0.2", "@rollup/plugin-commonjs": "^24.1.0", "@rollup/plugin-node-resolve": "^15.0.2", - "@typescript-eslint/parser": "^5.59.1", - "eslint": "^8.39.0", - "eslint-config-prettier": "^8.8.0", + "eslint": "^8.40.0", "eslint-plugin-import": "^2.27.5", "eslint-plugin-json": "^3.1.0", "eslint-plugin-prettier": "^4.2.1", @@ -42,16 +30,15 @@ "eslint-plugin-unused-imports": "^2.0.0", "magic-string": "^0.30.0", "postcss": "^8.4.23", - "rollup": "^3.20.6", + "rollup": "^3.21.6", "rollup-plugin-polyfill-node": "^0.12.0", "rollup-plugin-postcss": "^4.0.2", "rollup-plugin-ts": "^3.2.0", - "rollup-cache": "^1.2.0", "unplugin-fonts": "^1.0.3", - "vite": "4.3.3" + "vite": "4.3.5" }, "devDependencies": { - "@types/node": "18.16.1", + "@types/node": "^18.16.6", "typescript": "*" } } diff --git a/packages/@glimmer-workspace/eslint-plugin/index.js b/packages/@glimmer-workspace/eslint-plugin/index.js new file mode 100644 index 0000000000..e0a5f52cf0 --- /dev/null +++ b/packages/@glimmer-workspace/eslint-plugin/index.js @@ -0,0 +1,114 @@ +// @ts-check + +/** @type {import("eslint").ESLint.Plugin} */ +module.exports = { + meta: { + name: '@glimmer-workspace/eslint-plugin', + version: '1.0.0', + }, + configs: { + recommended: { + plugins: [ + '@typescript-eslint', + 'prettier', + 'qunit', + 'simple-import-sort', + 'unused-imports', + 'prettier', + 'n', + ], + extends: [ + 'eslint:recommended', + 'plugin:@typescript-eslint/recommended', + 'plugin:@typescript-eslint/recommended-requiring-type-checking', + 'plugin:n/recommended', + 'plugin:import/recommended', + 'plugin:qunit/recommended', + 'plugin:regexp/recommended', + 'prettier', + ], + rules: { + 'no-console': 'error', + 'no-debugger': 'error', + 'no-loop-func': 'error', + 'prefer-const': 'off', + 'no-fallthrough': 'off', + 'import/no-relative-packages': 'error', + 'import/default': 'off', + 'qunit/require-expect': ['error', 'never-except-zero'], + // we're using assert.step instead of this sort of thing + 'qunit/no-conditional-assertions': 'off', + 'regexp/require-unicode-regexp': 'error', + 'regexp/unicode-escape': 'error', + 'regexp/sort-character-class-elements': 'error', + 'regexp/prefer-result-array-groups': 'error', + 'regexp/prefer-named-replacement': 'error', + 'regexp/prefer-named-backreference': 'error', + 'regexp/prefer-lookaround': 'error', + 'regexp/use-ignore-case': 'error', + 'regexp/prefer-regexp-test': 'error', + 'regexp/prefer-regexp-exec': 'error', + 'regexp/prefer-quantifier': 'error', + 'require-unicode-regexp': 'off', + 'unused-imports/no-unused-imports': 'error', + 'unused-imports/no-unused-vars': [ + 'warn', + { vars: 'all', varsIgnorePattern: '^_', args: 'after-used', argsIgnorePattern: '^_' }, + ], + 'n/no-unpublished-require': 'off', + '@typescript-eslint/no-explicit-any': 'off', + '@typescript-eslint/ban-types': 'off', + '@typescript-eslint/no-non-null-assertion': 'off', + '@typescript-eslint/consistent-type-imports': [ + 'error', + { + fixStyle: 'separate-type-imports', + }, + ], + '@typescript-eslint/consistent-type-exports': [ + 'error', + { + fixMixedExportsWithInlineTypeSpecifier: true, + }, + ], + '@typescript-eslint/no-import-type-side-effects': 'error', + '@typescript-eslint/naming-convention': [ + 'error', + { + format: ['camelCase', 'PascalCase'], + leadingUnderscore: 'allow', + selector: ['parameter'], + }, + { + format: null, + modifiers: ['const'], + selector: 'variable', + }, + { + format: ['PascalCase'], + leadingUnderscore: 'allow', + selector: ['typeLike'], + }, + { + format: ['PascalCase', 'UPPER_CASE'], + selector: ['typeAlias'], + }, + ], + 'require-await': 'off', + '@typescript-eslint/no-empty-function': 'off', + '@typescript-eslint/no-inferrable-types': 'error', + '@typescript-eslint/no-require-imports': 'error', + '@typescript-eslint/no-unused-vars': '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-call': 'off', + '@typescript-eslint/restrict-template-expressions': 'off', + 'n/no-missing-import': 'off', + 'n/no-unsupported-features/es-syntax': 'off', + 'n/no-unsupported-features/node-builtins': 'off', + }, + }, + }, +}; diff --git a/packages/@glimmer-workspace/eslint-plugin/package.json b/packages/@glimmer-workspace/eslint-plugin/package.json new file mode 100644 index 0000000000..24ec828dd4 --- /dev/null +++ b/packages/@glimmer-workspace/eslint-plugin/package.json @@ -0,0 +1,24 @@ +{ + "name": "@glimmer-workspace/eslint-plugin", + "private": true, + "main": "index.js", + "dependencies": { + "@typescript-eslint/eslint-plugin": "^5.59.5", + "@typescript-eslint/parser": "^5.59.5", + "eslint-config-prettier": "^8.8.0", + "eslint-import-resolver-typescript": "^3.5.5", + "eslint-plugin-import": "^2.27.5", + "eslint-plugin-n": "^15.7.0", + "eslint-plugin-regexp": "^1.15.0", + "eslint-plugin-qunit": "^7.3.4", + "eslint-plugin-simple-import-sort": "^10.0.0", + "eslint-plugin-unused-imports": "^2.0.0" + }, + "peerDependencies": { + "eslint": "^8.40.0" + }, + "devDependencies": { + "eslint": "^8.40.0", + "@types/eslint": "^8.37.0" + } +} diff --git a/packages/@glimmer/integration-tests/index.ts b/packages/@glimmer-workspace/integration-tests/index.ts similarity index 94% rename from packages/@glimmer/integration-tests/index.ts rename to packages/@glimmer-workspace/integration-tests/index.ts index 0fc80c5ae5..83c13f6c91 100644 --- a/packages/@glimmer/integration-tests/index.ts +++ b/packages/@glimmer-workspace/integration-tests/index.ts @@ -25,4 +25,4 @@ export * from './lib/test-helpers/strings'; export * from './lib/test-helpers/test'; export * from './lib/test-helpers/tracked'; export * from './lib/test-helpers/tracked-object'; -export { syntaxErrorFor } from '@glimmer/test-utils'; +export { syntaxErrorFor } from '@glimmer-workspace/test-utils'; diff --git a/packages/@glimmer/integration-tests/lib/base-env.ts b/packages/@glimmer-workspace/integration-tests/lib/base-env.ts similarity index 91% rename from packages/@glimmer/integration-tests/lib/base-env.ts rename to packages/@glimmer-workspace/integration-tests/lib/base-env.ts index fa659fe77f..24dc028025 100644 --- a/packages/@glimmer/integration-tests/lib/base-env.ts +++ b/packages/@glimmer-workspace/integration-tests/lib/base-env.ts @@ -1,4 +1,4 @@ -import { type Destroyable, type Destructor } from '@glimmer/interfaces'; +import type { Destroyable, Destructor } from '@glimmer/interfaces'; import type { EnvironmentDelegate } from '@glimmer/runtime'; interface Scheduled { diff --git a/packages/@glimmer/integration-tests/lib/compile.ts b/packages/@glimmer-workspace/integration-tests/lib/compile.ts similarity index 86% rename from packages/@glimmer/integration-tests/lib/compile.ts rename to packages/@glimmer-workspace/integration-tests/lib/compile.ts index 8ed37c71b4..9238ada29d 100644 --- a/packages/@glimmer/integration-tests/lib/compile.ts +++ b/packages/@glimmer-workspace/integration-tests/lib/compile.ts @@ -1,11 +1,12 @@ import { precompileJSON } from '@glimmer/compiler'; -import { - type SerializedTemplateWithLazyBlock, - type Template, - type TemplateFactory, +import type { + Nullable, + SerializedTemplateWithLazyBlock, + Template, + TemplateFactory, } from '@glimmer/interfaces'; import { templateFactory } from '@glimmer/opcode-compiler'; -import { type PrecompileOptions } from '@glimmer/syntax'; +import type { PrecompileOptions } from '@glimmer/syntax'; // TODO: This fundamentally has little to do with testing and // most tests should just use a more generic preprocess, extracted @@ -17,7 +18,7 @@ export function preprocess(templateSource: string, options?: PrecompileOptions): let templateId = 0; export function createTemplate( - templateSource: string, + templateSource: Nullable, options: PrecompileOptions = {}, scopeValues: Record = {} ): TemplateFactory { diff --git a/packages/@glimmer/integration-tests/lib/components.ts b/packages/@glimmer-workspace/integration-tests/lib/components.ts similarity index 100% rename from packages/@glimmer/integration-tests/lib/components.ts rename to packages/@glimmer-workspace/integration-tests/lib/components.ts diff --git a/packages/@glimmer/integration-tests/lib/components/emberish-curly.ts b/packages/@glimmer-workspace/integration-tests/lib/components/emberish-curly.ts similarity index 90% rename from packages/@glimmer/integration-tests/lib/components/emberish-curly.ts rename to packages/@glimmer-workspace/integration-tests/lib/components/emberish-curly.ts index 24a0ab424d..0dd63560f0 100644 --- a/packages/@glimmer/integration-tests/lib/components/emberish-curly.ts +++ b/packages/@glimmer-workspace/integration-tests/lib/components/emberish-curly.ts @@ -1,23 +1,23 @@ import { registerDestructor } from '@glimmer/destroyable'; -import { - type Bounds, - type CapturedNamedArguments, - type CompilableProgram, - type Destroyable, - type Dict, - type DynamicScope, - type ElementOperations, - type Environment, - type InternalComponentCapabilities, - type Option, - type Owner, - type PreparedArguments, - type Reference, - type Template, - type VMArguments, - type WithCreateInstance, - type WithDynamicLayout, - type WithDynamicTagName, +import type { + Bounds, + CapturedNamedArguments, + CompilableProgram, + Destroyable, + Dict, + DynamicScope, + ElementOperations, + Environment, + InternalComponentCapabilities, + Nullable, + Owner, + PreparedArguments, + Reference, + Template, + VMArguments, + WithCreateInstance, + WithDynamicLayout, + WithDynamicTagName, } from '@glimmer/interfaces'; import { setInternalComponentManager } from '@glimmer/manager'; import { @@ -37,11 +37,11 @@ import { dirtyTagFor, } from '@glimmer/validator'; -import { type TestJitRuntimeResolver } from '../modes/jit/resolver'; -import { type TestComponentConstructor } from './types'; +import type { TestJitRuntimeResolver } from '../modes/jit/resolver'; +import type { TestComponentConstructor } from './types'; export type Attrs = Dict; -export type AttrsDiff = { oldAttrs: Option; newAttrs: Attrs }; +export type AttrsDiff = { oldAttrs: Nullable; newAttrs: Attrs }; export interface EmberishCurlyComponentFactory extends TestComponentConstructor { @@ -59,12 +59,12 @@ export class EmberishCurlyComponent { public dirtinessTag: DirtyableTag = createTag(); public declare layout: Template; public declare name: string; - public tagName: Option = null; - public attributeBindings: Option = null; + public tagName: Nullable = null; + public attributeBindings: Nullable = null; public declare attrs: Attrs; public declare element: Element; public declare bounds: Bounds; - public parentView: Option = null; + public parentView: Nullable = null; public declare args: CapturedNamedArguments; public _guid: string; @@ -165,7 +165,7 @@ export class EmberishCurlyComponentManager prepareArgs( definition: EmberishCurlyComponentFactory, args: VMArguments - ): Option { + ): Nullable { const { positionalParams } = definition || EmberishCurlyComponent; if (typeof positionalParams === 'string') { if (args.named.has(positionalParams)) { @@ -230,7 +230,7 @@ export class EmberishCurlyComponentManager component.args = args; - let dyn: Option = klass.fromDynamicScope || null; + let dyn: Nullable = klass.fromDynamicScope || null; if (dyn) { for (let i = 0; i < dyn.length; i++) { @@ -257,7 +257,7 @@ export class EmberishCurlyComponentManager return selfRef; } - getTagName({ component: { tagName } }: EmberishCurlyComponentState): Option { + getTagName({ component: { tagName } }: EmberishCurlyComponentState): Nullable { if (tagName) { return tagName; } else if (tagName === null) { diff --git a/packages/@glimmer/integration-tests/lib/components/emberish-glimmer.ts b/packages/@glimmer-workspace/integration-tests/lib/components/emberish-glimmer.ts similarity index 93% rename from packages/@glimmer/integration-tests/lib/components/emberish-glimmer.ts rename to packages/@glimmer-workspace/integration-tests/lib/components/emberish-glimmer.ts index cab904c5df..93dc23453f 100644 --- a/packages/@glimmer/integration-tests/lib/components/emberish-glimmer.ts +++ b/packages/@glimmer-workspace/integration-tests/lib/components/emberish-glimmer.ts @@ -1,5 +1,5 @@ import { destroy, isDestroyed, isDestroying, registerDestructor } from '@glimmer/destroyable'; -import { type Arguments, type ComponentManager, type Dict, type Owner } from '@glimmer/interfaces'; +import type { Arguments, ComponentManager, Dict, Owner } from '@glimmer/interfaces'; import { componentCapabilities, setComponentManager } from '@glimmer/manager'; import { setOwner } from '@glimmer/owner'; diff --git a/packages/@glimmer/integration-tests/lib/components/types.ts b/packages/@glimmer-workspace/integration-tests/lib/components/types.ts similarity index 76% rename from packages/@glimmer/integration-tests/lib/components/types.ts rename to packages/@glimmer-workspace/integration-tests/lib/components/types.ts index 8eccb9f3b9..15a1d61a28 100644 --- a/packages/@glimmer/integration-tests/lib/components/types.ts +++ b/packages/@glimmer-workspace/integration-tests/lib/components/types.ts @@ -1,8 +1,8 @@ -import { type Dict } from '@glimmer/interfaces'; -import { type TemplateOnlyComponent } from '@glimmer/runtime'; +import type { Dict } from '@glimmer/interfaces'; +import type { TemplateOnlyComponent } from '@glimmer/runtime'; -import { type EmberishCurlyComponent } from './emberish-curly'; -import { type GlimmerishComponent } from './emberish-glimmer'; +import type { EmberishCurlyComponent } from './emberish-curly'; +import type { GlimmerishComponent } from './emberish-glimmer'; export type ComponentKind = 'Glimmer' | 'Curly' | 'Dynamic' | 'TemplateOnly' | 'Custom' | 'unknown'; diff --git a/packages/@glimmer/integration-tests/lib/dom/assertions.ts b/packages/@glimmer-workspace/integration-tests/lib/dom/assertions.ts similarity index 97% rename from packages/@glimmer/integration-tests/lib/dom/assertions.ts rename to packages/@glimmer-workspace/integration-tests/lib/dom/assertions.ts index a127197e36..98c581b07d 100644 --- a/packages/@glimmer/integration-tests/lib/dom/assertions.ts +++ b/packages/@glimmer-workspace/integration-tests/lib/dom/assertions.ts @@ -1,4 +1,4 @@ -import { type Dict, type SimpleElement, type SimpleNode } from '@glimmer/interfaces'; +import type { Dict, SimpleElement, SimpleNode } from '@glimmer/interfaces'; import { assign, dict, isSimpleElement } from '@glimmer/util'; export interface DebugElement { @@ -7,7 +7,7 @@ export interface DebugElement { } function isDebugElement(el: SimpleNode | Node | DebugElement): el is DebugElement { - return !(el as any).nodeType; + return !('nodeType' in el); } function extract(node: EqualsElement): DebugElement { @@ -169,13 +169,13 @@ export function assertEmberishElement(element: SimpleElement, tagName: string): export function assertEmberishElement(...args: any[]): void { let [element, tagName, attrs, contents] = processAssertComponentArgs(args); - let fullAttrs = assign({ class: classes('ember-view'), id: regex(/^ember\d*$/) }, attrs); + 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 = result.match(/ - -
-
- - - - - - - + +
+
+ + + + + + + + // Bootstrap internal `assign` so it doesn't get clobbered by the debug + // assertion below + require('@glimmer/util'); + + // Recursively merge all the dependencies for this configuration of + // packages to ensure that we only inject each dependency once. + // Testing dependencies are only injected for the packages being tested. + var packagesToTest = getPackagesToTest(); + + + - + var smokeTestFile = '@glimmer-workspace/integration-tests/test/smoke-test'; + if (SMOKE_TESTS) { + requireModule(smokeTestFile); + } else { + Object.keys(requireModule.entries).forEach(function (entry) { + if (entry.match(testMatch) && entry !== smokeTestFile) { + if (notslint && entry.match(/\.lint-test$/)) return; + requireModule(entry); + } + }); + } + + diff --git a/testem-browserstack.js b/testem-browserstack.js index a698ce01f0..3f6cd9860a 100644 --- a/testem-browserstack.js +++ b/testem-browserstack.js @@ -1,4 +1,4 @@ -/* eslint-disable @typescript-eslint/naming-convention */ + 'use strict'; diff --git a/testem.js b/testem.js index 91ef55023c..06f543efce 100644 --- a/testem.js +++ b/testem.js @@ -1,4 +1,4 @@ -/* eslint-disable @typescript-eslint/naming-convention */ + 'use strict'; diff --git a/tsconfig.js.json b/tsconfig.cjs.json similarity index 60% rename from tsconfig.js.json rename to tsconfig.cjs.json index ae06f6584f..b5aadc836f 100644 --- a/tsconfig.js.json +++ b/tsconfig.cjs.json @@ -1,13 +1,15 @@ { "compilerOptions": { "allowJs": true, - "checkJs": false, + "checkJs": true, "target": "esnext", "moduleResolution": "nodenext", "module": "esnext", "skipLibCheck": true, "allowSyntheticDefaultImports": true, "esModuleInterop": true, - "outDir": "ts-dist/build" - } + "outDir": "ts-dist/cjs" + }, + "include": ["**/.eslintrc.cjs"], + "exclude": ["node_modules", "**/node_modules", "ts-dist"] } diff --git a/tsconfig.dist.json b/tsconfig.dist.json index bb881787cd..5627938693 100644 --- a/tsconfig.dist.json +++ b/tsconfig.dist.json @@ -12,7 +12,6 @@ "strict": true, "suppressImplicitAnyIndexErrors": false, "useDefineForClassFields": false, - "verbatimModuleSyntax": true, "exactOptionalPropertyTypes": true, "noImplicitOverride": true, "noPropertyAccessFromIndexSignature": true, diff --git a/tsconfig.json b/tsconfig.json index 86579c027d..d3edf4c2bb 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -10,10 +10,11 @@ "references": [ { "path": "benchmark/tsconfig.json" }, { "path": "bin/tsconfig.json" }, - { "path": "build/tsconfig.json" }, { "path": "packages/@glimmer/tsconfig.json" }, - { "path": "packages/build-utils/tsconfig.json" }, + { "path": "packages/@glimmer/tsconfig.test.json" }, + { "path": "packages/@glimmer-workspace/tsconfig.json" }, { "path": "server/tsconfig.json" }, - { "path": "lib/tsconfig.json" } + { "path": "lib/tsconfig.json" }, + { "path": "tsconfig.cjs.json" } ] } diff --git a/turbo.json b/turbo.json new file mode 100644 index 0000000000..a7c2c84ec4 --- /dev/null +++ b/turbo.json @@ -0,0 +1,26 @@ +{ + "$schema": "https://turbo.build/schema.json", + "pipeline": { + "build": { + "dependsOn": ["^build"], + "outputs": ["dist/**"] + }, + "lint": { + "dependsOn": ["test:lint"] + }, + "test:lint": {}, + "typecheck": { + "inputs": ["dist/**"], + "dependsOn": ["^build", "test:types"] + }, + "test:types": {} + }, + "globalDependencies": [ + "tsconfig.json", + "tsconfig.dist.json", + "*/tsconfig.json", + "packages/*/tsconfig.json", + "packages/@glimmer-workspace/eslint-plugin/**/*" + ], + "globalEnv": ["NODE_OPTIONS"] +} diff --git a/vite.config.mts b/vite.config.mts index 2b35668fba..73a507649e 100644 --- a/vite.config.mts +++ b/vite.config.mts @@ -4,6 +4,7 @@ export default defineConfig({ server: { open: '?hidepassed', }, + mode: 'testing', resolve: { extensions: ['.mjs', '.js', '.mts', '.ts', '.jsx', '.tsx', '.json', '.d.ts'], },