diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0922f36..5e91c7c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,7 +20,7 @@ jobs: gulp make-ts-defs gulp lint gulp bundle:cjs bundle:esm bundle:global - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@v4 with: name: lib path: lib @@ -43,7 +43,7 @@ jobs: with: node-version: ${{ matrix.node-version }} - run: npm install - - uses: actions/download-artifact@v3 + - uses: actions/download-artifact@v4 with: name: lib path: lib @@ -71,7 +71,7 @@ jobs: - uses: denoland/setup-deno@v1 with: deno-version: ${{ matrix.deno-version }} - - uses: actions/download-artifact@v3 + - uses: actions/download-artifact@v4 with: name: lib path: lib diff --git a/gulpfile.js b/gulpfile.js index 7c67ec5..b81d7e7 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -2,7 +2,8 @@ 'use strict'; -const { parallel, series, src, task } = require('gulp'); +const { parallel, series, src, task } = require('gulp'); +const syncReadable = require('sync-readable'); async function bundle(inputPath, format, outputPath, outputPathMin) { @@ -94,111 +95,142 @@ task task ( 'lint', - () => - { - const { createConfig } = require('@origin-1/eslint-config'); - const gulpESLintNew = require('gulp-eslint-new'); - - const JS_EXAMPLE_RULES = + syncReadable + ( + async () => { - '@stylistic/comma-dangle': + const [ - 'error', + { createConfig }, + { EslintEnvProcessor }, + { default: eslintPluginTSTest }, + { default: globals }, + { default: gulpESLintNew }, + ] = + await Promise.all + ( + [ + import('@origin-1/eslint-config'), + import('eslint-plugin-eslint-env'), + import('eslint-plugin-tstest'), + import('globals'), + import('gulp-eslint-new'), + ], + ); + const JS_EXAMPLE_RULES = + { + '@stylistic/comma-dangle': + [ + 'error', + { + 'arrays': 'always-multiline', + 'objects': 'always-multiline', + 'imports': 'always-multiline', + 'exports': 'always-multiline', + 'functions': 'only-multiline', + }, + ], + 'no-unused-vars': + [ + 'error', + { + args: 'none', + caughtErrors: 'all', + ignoreRestSiblings: true, + vars: 'local', + varsIgnorePattern: '^(?:Green|WhiteUnit)Circle$', + }, + ], + '@stylistic/quotes': ['error', 'double'], + }; + const { 'no-unused-vars': noUnusedVars, ...TS_EXAMPLE_RULES } = JS_EXAMPLE_RULES; + TS_EXAMPLE_RULES['@typescript-eslint/no-unused-vars'] = noUnusedVars; + const overrideConfig = + await createConfig + ( { - 'arrays': 'always-multiline', - 'objects': 'always-multiline', - 'imports': 'always-multiline', - 'exports': 'always-multiline', - 'functions': 'only-multiline', + processor: + new EslintEnvProcessor({ disabledRules: { '@stylistic/max-len': 'overlap' } }), }, - ], - 'no-unused-vars': - [ - 'error', { - args: 'none', - caughtErrors: 'all', - ignoreRestSiblings: true, - vars: 'local', - varsIgnorePattern: '^(?:Green|WhiteUnit)Circle$', + files: ['**/*.js'], + ignores: ['src/**/*.js'], + jsVersion: 2022, + languageOptions: { sourceType: 'commonjs' }, }, - ], - '@stylistic/quotes': ['error', 'double'], - }; - const { 'no-unused-vars': noUnusedVars, ...TS_EXAMPLE_RULES } = JS_EXAMPLE_RULES; - TS_EXAMPLE_RULES['@typescript-eslint/no-unused-vars'] = noUnusedVars; - const overrideConfig = - createConfig - ( - { - files: ['*.js', '*.mjs'], - jsVersion: 2022, - }, - { - files: ['*.ts', '*.tstest'], - tsVersion: '4.7.0', - parserOptions: { extraFileExtensions: ['.tstest'], project: 'tsconfig.json' }, - }, - { - files: ['*.mjs', 'src/**/*.js'], - parserOptions: { sourceType: 'module' }, - rules: { 'logical-assignment-operators': 'off' }, - }, - { - files: 'example/**/*.js', - env: { 'node': 'readOnly' }, - rules: JS_EXAMPLE_RULES, - }, - { - files: 'example/**/*.ts', - env: { 'node': 'readOnly' }, - rules: TS_EXAMPLE_RULES, - }, - { - files: 'lib/**/*.d.ts', - rules: { '@stylistic/max-len': 'off' }, - }, - { - files: '*.tstest', - plugins: ['tstest'], - rules: { - '@typescript-eslint/no-extraneous-class': 'off', - '@typescript-eslint/no-misused-new': 'off', - '@typescript-eslint/no-unused-vars': 'off', - '@typescript-eslint/no-useless-constructor': 'off', - 'constructor-super': 'off', - 'spaced-comment': 'off', + files: ['src/**/*.js'], + jsVersion: 2020, }, - }, - ); - const stream = - src - ( - [ - '*.js', - 'example/**/*.{js,ts}', - 'lib/**/*.d.ts', - 'src/**/*.js', - 'test/**/*.{js,mjs,tstest}', - ], - ) - .pipe - ( - gulpESLintNew - ( { - overrideConfig, - reportUnusedDisableDirectives: 'error', - useEslintrc: false, - warnIgnored: true, + files: ['**/*.mjs'], + jsVersion: 2022, }, - ), - ) - .pipe(gulpESLintNew.format('compact')) - .pipe(gulpESLintNew.failAfterError()); - return stream; - }, + { + files: ['**/*.ts', '**/*.tstest'], + tsVersion: '4.7.0', + languageOptions: + { + parserOptions: + { extraFileExtensions: ['.tstest'], project: 'tsconfig.json' }, + }, + }, + { + files: ['example/**/*.js'], + languageOptions: { globals: { ...globals.node } }, + rules: JS_EXAMPLE_RULES, + }, + { + files: ['example/**/*.ts'], + languageOptions: { globals: { ...globals.node } }, + rules: TS_EXAMPLE_RULES, + }, + { + files: ['lib/**/*.d.ts'], + rules: { '@stylistic/max-len': 'off' }, + }, + { + files: ['**/*.tstest'], + plugins: { tstest: eslintPluginTSTest }, + rules: + { + '@stylistic/spaced-comment': 'off', + '@typescript-eslint/no-extraneous-class': 'off', + '@typescript-eslint/no-misused-new': 'off', + '@typescript-eslint/no-unused-vars': 'off', + '@typescript-eslint/no-useless-constructor': 'off', + 'constructor-super': 'off', + }, + }, + ); + const stream = + src + ( + [ + '*.js', + 'example/**/*.{js,ts}', + 'lib/**/*.d.ts', + 'src/**/*.js', + 'test/**/*.{js,mjs,tstest}', + ], + ) + .pipe + ( + gulpESLintNew + ( + { + configType: 'flat', + overrideConfig, + overrideConfigFile: true, + warnIgnored: true, + }, + ), + ) + .pipe(gulpESLintNew.format('compact')) + .pipe(gulpESLintNew.failAfterError()); + return stream; + }, + ), ); task('bundle:cjs', () => bundle('src/polytype-esm.js', 'cjs', 'lib/polytype.cjs')); diff --git a/package.json b/package.json index 158e9e9..bc613c0 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,8 @@ "@origin-1/eslint-config": "latest", "ansi-colors": "latest", "c8js": "latest", - "chai": "latest", + "chai": "4", + "eslint-plugin-eslint-env": "latest", "eslint-plugin-tstest": "file:test/eslint-plugin-tstest", "glob": "latest", "gulp": "latest", @@ -54,6 +55,7 @@ "rollup": "latest", "rollup-plugin-cleanup": "latest", "rollup-plugin-terser": "latest", + "sync-readable": "latest", "typescript": "latest", "typescript_4.7": "npm:typescript@4.7", "typescript_4.8": "npm:typescript@4.8", @@ -61,7 +63,8 @@ "typescript_5.0": "npm:typescript@5.0", "typescript_5.1": "npm:typescript@5.1", "typescript_5.2": "npm:typescript@5.2", - "typescript_5.3": "npm:typescript@5.3" + "typescript_5.3": "npm:typescript@5.3", + "typescript_5.4": "npm:typescript@5.4" }, "engines": { "node": ">=16.0.0" diff --git a/test/deno-spec-runner.mjs b/test/deno-spec-runner.mjs index 398a3a9..ad2e4fb 100644 --- a/test/deno-spec-runner.mjs +++ b/test/deno-spec-runner.mjs @@ -11,7 +11,7 @@ deno run --allow-env --allow-read test/deno-spec-runner.mjs import { expandGlob } from 'https://deno.land/std/fs/expand_glob.ts'; import { dirname, fromFileUrl, toFileUrl } from 'https://deno.land/std/path/mod.ts'; -import chai from 'https://esm.sh/chai'; +import * as chai from 'https://esm.sh/chai'; import 'https://esm.sh/mocha/mocha.js'; globalThis.chai = chai; diff --git a/test/serve.mjs b/test/serve.mjs index 6a241c5..74a6e62 100755 --- a/test/serve.mjs +++ b/test/serve.mjs @@ -52,7 +52,8 @@ createServer 'error', () => { - response.writeHead(404); + if (!response.headersSent) + response.writeHead(404); response.end(); }, ); diff --git a/test/spec-helper.js b/test/spec-helper.js index 2eb2615..3ab317f 100644 --- a/test/spec-helper.js +++ b/test/spec-helper.js @@ -1,6 +1,6 @@ /* eslint no-alert: off */ /* eslint-env mocha, shared-node-browser */ -/* global Deno alert chai document location process require */ +/* global Deno alert chai document location process */ 'use strict'; diff --git a/test/spec/common/function-prototype-bind.spec.js b/test/spec/common/function-prototype-bind.spec.js index 7bcf6dd..0dc67ac 100644 --- a/test/spec/common/function-prototype-bind.spec.js +++ b/test/spec/common/function-prototype-bind.spec.js @@ -140,8 +140,16 @@ describe ( () => Function.prototype.bind.call({ }), [ + // V8 'Bind must be called on a function', + + // Firefox 112 or later + 'Function.prototype.bind called on incompatible Object', + + // Firefox 111 or earlier 'Function.prototype.bind called on incompatible target', + + // Safari '|this| is not a function inside Function.prototype.bind', ], ), diff --git a/test/spec/ts-defs.spec.mjs b/test/spec/ts-defs.spec.mjs index 5a6ac94..d73ff41 100644 --- a/test/spec/ts-defs.spec.mjs +++ b/test/spec/ts-defs.spec.mjs @@ -204,5 +204,6 @@ describe describe('TypeScript 5.1', () => defineTests('typescript_5.1')); describe('TypeScript 5.2', () => defineTests('typescript_5.2')); describe('TypeScript 5.3', () => defineTests('typescript_5.3')); + describe('TypeScript 5.4', () => defineTests('typescript_5.4')); }, ); diff --git a/test/spec/ts-defs/010.tstest b/test/spec/ts-defs/010.tstest index bf63d06..ac85cac 100644 --- a/test/spec/ts-defs/010.tstest +++ b/test/spec/ts-defs/010.tstest @@ -5,5 +5,4 @@ } */ -// eslint-disable-next-line no-duplicate-imports import { SuperConstructorInvokeInfo } from 'polytype'; diff --git a/test/spec/ts-defs/020.tstest b/test/spec/ts-defs/020.tstest index 18b5417..dc3e926 100644 --- a/test/spec/ts-defs/020.tstest +++ b/test/spec/ts-defs/020.tstest @@ -5,5 +5,4 @@ } */ -// eslint-disable-next-line no-duplicate-imports import { SuperConstructorInvokeInfo } from 'polytype/global';