diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 237f4c9cc3..eda5ecd5b2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -10,7 +10,9 @@ jobs: steps: - uses: actions/checkout@v3 - uses: ljharb/actions/node/install@d9f477827ed71a259056764107f74afc29febcae - name: 'nvm install lts/* && npm ci' + name: 'nvm install lts/* && npm ci --no-audit' + env: + NPM_CONFIG_AUDIT: false with: node-version: lts/* use-npm-ci: true diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 424c2d3f97..a567db1f65 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -14,7 +14,9 @@ jobs: steps: - uses: actions/checkout@v3 - uses: ljharb/actions/node/install@d9f477827ed71a259056764107f74afc29febcae - name: 'nvm install lts/* && npm ci' + name: 'nvm install lts/* && npm ci --no-audit' + env: + NPM_CONFIG_AUDIT: false with: node-version: lts/* use-npm-ci: true diff --git a/.github/workflows/enforce-format.yml b/.github/workflows/enforce-format.yml index d2358e0e47..d40c94ff9b 100644 --- a/.github/workflows/enforce-format.yml +++ b/.github/workflows/enforce-format.yml @@ -10,7 +10,9 @@ jobs: steps: - uses: actions/checkout@v3 - uses: ljharb/actions/node/install@d9f477827ed71a259056764107f74afc29febcae - name: 'nvm install lts/* && npm ci' + name: 'nvm install lts/* && npm ci --no-audit' + env: + NPM_CONFIG_AUDIT: false with: node-version: lts/* use-npm-ci: true diff --git a/.github/workflows/ipr.yml b/.github/workflows/ipr.yml index 608b514867..cc313dfb42 100644 --- a/.github/workflows/ipr.yml +++ b/.github/workflows/ipr.yml @@ -16,7 +16,9 @@ jobs: steps: - uses: actions/checkout@v3 - uses: ljharb/actions/node/install@d9f477827ed71a259056764107f74afc29febcae - name: 'nvm install lts/* && npm ci' + name: 'nvm install lts/* && npm ci --no-audit' + env: + NPM_CONFIG_AUDIT: false with: node-version: lts/* use-npm-ci: true diff --git a/.github/workflows/preview-build.yml b/.github/workflows/preview-build.yml index d2dd361ea5..55a4474dc2 100644 --- a/.github/workflows/preview-build.yml +++ b/.github/workflows/preview-build.yml @@ -10,7 +10,9 @@ jobs: steps: - uses: actions/checkout@v3 - uses: ljharb/actions/node/install@d9f477827ed71a259056764107f74afc29febcae - name: 'nvm install lts/* && npm ci' + name: 'nvm install lts/* && npm ci --no-audit' + env: + NPM_CONFIG_AUDIT: false with: node-version: lts/* use-npm-ci: true diff --git a/.github/workflows/preview.yml b/.github/workflows/preview.yml index c3ab4f7f83..1f1e69a4b6 100644 --- a/.github/workflows/preview.yml +++ b/.github/workflows/preview.yml @@ -20,7 +20,9 @@ jobs: steps: - uses: actions/checkout@v3 - uses: ljharb/actions/node/install@d9f477827ed71a259056764107f74afc29febcae - name: 'nvm install lts/* && npm ci' + name: 'nvm install lts/* && npm ci --no-audit' + env: + NPM_CONFIG_AUDIT: false with: node-version: lts/* use-npm-ci: true diff --git a/.github/workflows/publish-biblio.yml b/.github/workflows/publish-biblio.yml index dad842ff86..bca1c1919f 100644 --- a/.github/workflows/publish-biblio.yml +++ b/.github/workflows/publish-biblio.yml @@ -24,7 +24,7 @@ jobs: registry-url: 'https://registry.npmjs.org' - name: Install dependencies - run: npm ci + run: npm ci --no-audit - name: Publish biblio run: scripts/publish-biblio.sh diff --git a/.github/workflows/spellcheck.yml b/.github/workflows/spellcheck.yml new file mode 100644 index 0000000000..6a02292048 --- /dev/null +++ b/.github/workflows/spellcheck.yml @@ -0,0 +1,24 @@ +name: 'ecma-262' + +on: [pull_request] + +jobs: + spellcheck: + name: 'check for newly-introduced spelling errors' + runs-on: ubuntu-latest + + steps: + - run: sudo apt-get install aspell + - uses: actions/checkout@v3 + with: + # Number of commits to fetch. 0 indicates all history for all branches and tags. + # Default: 1 + fetch-depth: 0 + - uses: ljharb/actions/node/install@d9f477827ed71a259056764107f74afc29febcae + name: 'nvm install lts/* && npm ci --no-audit' + env: + NPM_CONFIG_AUDIT: false + with: + node-version: lts/* + use-npm-ci: true + - run: node scripts/spellcheck.mjs origin/"${GITHUB_BASE_REF}" diff --git a/.gitignore b/.gitignore index 1d3e390a13..21fcbc8f9d 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ node_modules/ out/ vendor/esmeta test*.js +aspell.txt # lockfiles we don't use are ignored npm-shrinkwrap.json diff --git a/img/figure-2.svg b/img/figure-2.svg index fe1ac95e65..ef20a19c0f 100644 --- a/img/figure-2.svg +++ b/img/figure-2.svg @@ -83,14 +83,14 @@ - - - + + + - Function.prototype + Function.prototype - @@hasInstance() + %Symbol.hasInstance%() apply() bind() call() @@ -104,7 +104,7 @@ %GeneratorFunction.prototype% - @@toStringTag = + %Symbol.toStringTag% = "GeneratorFunction" @@ -127,26 +127,26 @@ - - - + + + - %IteratorPrototype% + %IteratorPrototype% - @@iterator() : object + %Symbol.iterator%() : object - - - - + + + + - %GeneratorPrototype% + %GeneratorPrototype% - @@toStringTag = "Generator" + %Symbol.toStringTag% = "Generator" next() : object @@ -189,7 +189,7 @@ - + %GeneratorFunction.prototype% @@ -242,12 +242,12 @@ - - - + + + - - + + @@ -272,8 +272,8 @@ constructor prototype - - constructor + + constructor prototype diff --git a/package-lock.json b/package-lock.json index bd2ac49ed1..1998122c78 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "1.0.0", "license": "SEE LICENSE IN https://tc39.es/ecma262/#sec-copyright-and-software-license", "devDependencies": { - "ecmarkup": "^18.3.1", + "ecmarkup": "^19.1.0", "glob": "^7.1.6", "jsdom": "^15.0.0", "pagedjs": "^0.4.3", @@ -1243,10 +1243,11 @@ } }, "node_modules/ecmarkup": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/ecmarkup/-/ecmarkup-18.3.1.tgz", - "integrity": "sha512-ouyfwgVjtvyF9AdAQnI9krCWNE5srK90XGPym8vs6WPtjUso6Pq887DwAYBDbga9lrfwezWo5n8hGu9amYYu1g==", + "version": "19.1.0", + "resolved": "https://registry.npmjs.org/ecmarkup/-/ecmarkup-19.1.0.tgz", + "integrity": "sha512-+mh2vIcRCJtr8poJl64yulZkSSWpd7TQpORj+WVRmFe5omdS33eF94XjPa8QN0TiNz7gaCwJygKUF4COO142mA==", "dev": true, + "license": "MIT", "dependencies": { "chalk": "^4.1.2", "command-line-args": "^5.2.0", diff --git a/package.json b/package.json index 99a69bd79c..e0695f3569 100644 --- a/package.json +++ b/package.json @@ -23,10 +23,8 @@ "author": "ECMA TC39", "license": "SEE LICENSE IN https://tc39.es/ecma262/#sec-copyright-and-software-license", "homepage": "https://tc39.es/ecma262/", - "dependencies": { - }, "devDependencies": { - "ecmarkup": "^18.3.1", + "ecmarkup": "^19.1.0", "glob": "^7.1.6", "jsdom": "^15.0.0", "pagedjs": "^0.4.3", diff --git a/scripts/check-form.js b/scripts/check-form.js index 2282f62540..2c1dd9c2ac 100644 --- a/scripts/check-form.js +++ b/scripts/check-form.js @@ -28,7 +28,7 @@ if (typeof all !== 'undefined' && all !== '--all') { throw '`all` arg, if provided, must be `--all`' } -const sha = String(execSync(`git rev-parse --short ${branch}`)).trim(); +const sha = String(execSync(`git rev-parse ${branch}`)).trim(); const request = async (url, method = 'GET', postData) => { // adapted from https://medium.com/@gevorggalstyan/how-to-promisify-node-js-http-https-requests-76a5a58ed90c diff --git a/scripts/insert_snapshot_warning.js b/scripts/insert_snapshot_warning.js index e2d02e6bfc..92b0f48cc3 100644 --- a/scripts/insert_snapshot_warning.js +++ b/scripts/insert_snapshot_warning.js @@ -2,7 +2,7 @@ const fs = require('fs'); const path = require('path'); -const { JSDOM } = require('jsdom'); +const { JSDOM, VirtualConsole } = require('jsdom'); const { execSync } = require('child_process'); const COMMIT = String(execSync('git rev-parse --verify HEAD')).trim(); @@ -13,21 +13,30 @@ const WARNING_CSS = fs.readFileSync(path.join(__dirname, 'snapshot_warning.css') console.log('Inserting snapshot reference warning...'); -JSDOM.fromFile('./out/index.html', { contentType: 'text/html; charset=utf-8' }).then((dom) => { - const { document } = dom.window; +const virtualConsole = new VirtualConsole(); +virtualConsole.on('error', () => { + // Suppress warnings from e.g. CSS features not supported by JSDOM +}); - const style = document.createElement('style'); - style.textContent = WARNING_CSS; - document.head.append(style); +(async () => { + let files = ['out/index.html', ...fs.readdirSync('out/multipage').filter(f => f.endsWith('.html')).map(f => 'out/multipage/' + f)]; + for (let file of files) { + console.log(file); + let dom = await JSDOM.fromFile(file, { contentType: 'text/html; charset=utf-8', virtualConsole }); + const { document } = dom.window; - // insert WARNING_HTML in beginning of body so it renders - // first even on slower devices and browsers - document.body.insertAdjacentHTML('afterbegin', WARNING_HTML); + const style = document.createElement('style'); + style.textContent = WARNING_CSS; + document.head.append(style); - fs.writeFileSync('./out/index.html', dom.serialize(), 'utf8'); + // insert WARNING_HTML in beginning of body so it renders + // first even on slower devices and browsers + document.body.insertAdjacentHTML('afterbegin', WARNING_HTML); + fs.writeFileSync(file, dom.serialize(), 'utf8'); + } console.log('Done!'); -}).catch((reason) => { - console.error(reason); - process.exitCode = 1; +})().catch(e => { + console.error(e); + process.exit(1); }); diff --git a/scripts/snapshot_warning.html b/scripts/snapshot_warning.html index 3e2043ea2f..e0e3108b76 100644 --- a/scripts/snapshot_warning.html +++ b/scripts/snapshot_warning.html @@ -13,3 +13,13 @@ living specification.

+ diff --git a/scripts/spellcheck.mjs b/scripts/spellcheck.mjs new file mode 100644 index 0000000000..7b9c5ac739 --- /dev/null +++ b/scripts/spellcheck.mjs @@ -0,0 +1,72 @@ +import { promisify } from 'node:util'; +import { exec } from 'node:child_process'; +const execP = promisify(exec); +import { writeFile } from 'node:fs/promises'; + +const MIN_WORD_SIZE = 3; + +const BASE_REF = process.argv[2]; +const ASPELL_OPTS = [ + '--add-html-check=alt,title,caption,variants', + '--ignore-case', + '--master=en_GB-ize', + '--mode=html', + '--run-together', + '--run-together-limit=99', + '--run-together-min=2', + 'list', +].join(' '); + +function makeDict(words) { + return `personal_ws-1.1 en ${words.length}\n${words.join('\n')}`; +} + +function lines(text) { + if (text.length === 0) return []; + return text.split('\n'); +} + +console.log(`base ref: ${BASE_REF}`); + +let { stdout } = await execP(`git show "${BASE_REF}":spec.html | aspell ${ASPELL_OPTS} | sort -fu`); + +let existingWords = lines(stdout.trim()); + +let existingComponents = Array.from(new Set( + existingWords + .flatMap(word => [...word.matchAll(/(?:^[a-z]|[A-Z])[a-z]{2,}/g)]) + .map(([w]) => w.toLowerCase()) +)); + +({ stdout } = await execP(`echo ${existingComponents.map(w => JSON.stringify(w)).join(' ')} | aspell ${ASPELL_OPTS} | sort -fu`)); + +let existingComponentsReduced = lines(stdout.trim()); + +await writeFile('aspell.txt', makeDict(existingComponentsReduced)); + +({ stdout } = await execP(`echo ${existingWords.map(w => JSON.stringify(w)).join(' ')} | aspell --personal=./aspell.txt ${ASPELL_OPTS}`)); + +let novel = [...existingComponentsReduced, ...lines(stdout.trim())].filter(w => w.length >= MIN_WORD_SIZE); +novel.sort(); +console.log(`\npreviously used novel words: ${novel.join(', ')}`); +await writeFile('aspell.txt', makeDict(novel)); + +({ stdout } = await execP(`aspell --personal=./aspell.txt ${ASPELL_OPTS} list w.length >= MIN_WORD_SIZE); + +if (misspellings.length > 0) { + console.log(`\nmisspellings: ${misspellings.join(', ')}`); + let pattern = misspellings.map(w => `-e ${JSON.stringify(w)}`).join(' --or '); + ({ stdout } = await execP(`git grep --line-number --column --fixed-strings --only-matching ${pattern} -- spec.html`)); + + console.log(''); + + let info = lines(stdout.trim()); + for (let warning of info) { + let [match, file, line, col, typo] = warning.match(/^([^:]+):(\d+):(\d+):(.*)$/); + let title = 'Potential Typo'; + let message = `${JSON.stringify(typo)} is not a previously used word or composed of previously used words. Perhaps it is a typo?`; + // https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#setting-a-warning-message + console.log(`::warning file=${file},line=${line},endLine=${line},col=${col},endColumn=${col + typo.length},title=${title}::${message}`); + } +} diff --git a/spec.html b/spec.html index 42a3a067ee..f9cf2f45fa 100644 --- a/spec.html +++ b/spec.html @@ -26,6 +26,29 @@ width: 100%; font-size: 80%; } + + .corner-cell { + position: relative; + height: 2lh; + } + .corner-cell .slash { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: linear-gradient(to bottom left, transparent calc(50% - 1px), gray, transparent calc(50% + 1px)); + } + .corner-cell > .column { + position: absolute; + bottom: 0.4em; + left: 1em; + } + .corner-cell > .row { + position: absolute; + top: 0.4em; + right: 1em; + }