diff --git a/package-lock.json b/package-lock.json index b8aea534af..617c851fa6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,12 +12,12 @@ "@ampproject/remapping": "^0.3.0", "@jridgewell/sourcemap-codec": "^1.4.14", "@rollup/plugin-commonjs": "^11.0.0", - "@rollup/plugin-json": "^4.0.1", + "@rollup/plugin-json": "^6.0.0", "@rollup/plugin-node-resolve": "^11.2.1", - "@rollup/plugin-replace": "^2.3.0", + "@rollup/plugin-replace": "^5.0.2", "@rollup/plugin-sucrase": "^3.1.0", "@rollup/plugin-typescript": "^2.0.1", - "@rollup/plugin-virtual": "^2.0.0", + "@rollup/plugin-virtual": "^3.0.1", "@sveltejs/eslint-config": "github:sveltejs/eslint-config#v5.8.0", "@types/aria-query": "^5.0.0", "@types/mocha": "^7.0.0", @@ -28,7 +28,7 @@ "agadoo": "^2.0.0", "aria-query": "^5.1.1", "axobject-query": "^3.1.1", - "code-red": "^0.2.5", + "code-red": "^1.0.0", "css-tree": "^2.2.1", "eslint": "^8.26.0", "eslint-plugin-import": "^2.26.0", @@ -38,7 +38,7 @@ "jsdom": "^15.2.1", "kleur": "^4.1.5", "locate-character": "^2.0.5", - "magic-string": "^0.25.3", + "magic-string": "^0.30.0", "mocha": "^7.0.0", "periscopic": "^3.0.4", "puppeteer": "^2.0.0", @@ -244,14 +244,59 @@ } }, "node_modules/@rollup/plugin-json": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@rollup/plugin-json/-/plugin-json-4.0.1.tgz", - "integrity": "sha512-soxllkhOGgchswBAAaTe7X9G80U2tjjHvXv0sBrriLJcC/89PkP59iTrKPOfbz3SjX088mKDmMhAscuyLz8ZSg==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@rollup/plugin-json/-/plugin-json-6.0.0.tgz", + "integrity": "sha512-i/4C5Jrdr1XUarRhVu27EEwjt4GObltD7c+MkCIpO2QIbojw8MUs+CCTqOphQi3Qtg1FLmYt+l+6YeoIf51J7w==", "dev": true, "dependencies": { - "rollup-pluginutils": "^2.5.0" + "@rollup/pluginutils": "^5.0.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/plugin-json/node_modules/@rollup/pluginutils": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.0.2.tgz", + "integrity": "sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==", + "dev": true, + "dependencies": { + "@types/estree": "^1.0.0", + "estree-walker": "^2.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } } }, + "node_modules/@rollup/plugin-json/node_modules/@types/estree": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.0.tgz", + "integrity": "sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ==", + "dev": true + }, + "node_modules/@rollup/plugin-json/node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true + }, "node_modules/@rollup/plugin-node-resolve": { "version": "11.2.1", "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-11.2.1.tgz", @@ -302,22 +347,70 @@ "dev": true }, "node_modules/@rollup/plugin-replace": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@rollup/plugin-replace/-/plugin-replace-2.3.0.tgz", - "integrity": "sha512-rzWAMqXAHC1w3eKpK6LxRqiF4f3qVFaa1sGii6Bp3rluKcwHNOpPt+hWRCmAH6SDEPtbPiLFf0pfNQyHs6Btlg==", + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@rollup/plugin-replace/-/plugin-replace-5.0.2.tgz", + "integrity": "sha512-M9YXNekv/C/iHHK+cvORzfRYfPbq0RDD8r0G+bMiTXjNGKulPnCT9O3Ss46WfhI6ZOCgApOP7xAdmCQJ+U2LAA==", "dev": true, "dependencies": { - "magic-string": "^0.25.2", - "rollup-pluginutils": "^2.6.0" + "@rollup/pluginutils": "^5.0.1", + "magic-string": "^0.27.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } } }, + "node_modules/@rollup/plugin-replace/node_modules/@rollup/pluginutils": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.0.2.tgz", + "integrity": "sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==", + "dev": true, + "dependencies": { + "@types/estree": "^1.0.0", + "estree-walker": "^2.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/plugin-replace/node_modules/@types/estree": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.0.tgz", + "integrity": "sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ==", + "dev": true + }, + "node_modules/@rollup/plugin-replace/node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true + }, "node_modules/@rollup/plugin-replace/node_modules/magic-string": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", - "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.27.0.tgz", + "integrity": "sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA==", "dev": true, "dependencies": { - "sourcemap-codec": "^1.4.8" + "@jridgewell/sourcemap-codec": "^1.4.13" + }, + "engines": { + "node": ">=12" } }, "node_modules/@rollup/plugin-sucrase": { @@ -334,23 +427,39 @@ } }, "node_modules/@rollup/plugin-typescript": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@rollup/plugin-typescript/-/plugin-typescript-2.0.1.tgz", - "integrity": "sha512-UA/bN/DlHN19xdOllXmp7G7pM2ac9dQMg0q2T1rg4Bogzb7oHXj2WGafpiNpEm54PivcJdzGRJvRnI6zCISW3w==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@rollup/plugin-typescript/-/plugin-typescript-2.1.0.tgz", + "integrity": "sha512-7lXKGY06aofrceVez/YnN2axttFdHSqlUBpCJ6ebzDfxwLDKMgSV5lD4ykBcdgE7aK3egxuLkD/HKyRB5L8Log==", "dev": true, "dependencies": { "@rollup/pluginutils": "^3.0.0", - "resolve": "^1.12.2" + "resolve": "^1.13.1" }, "engines": { "node": ">=8.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0", + "tslib": "*", + "typescript": ">=2.1.0" } }, "node_modules/@rollup/plugin-virtual": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@rollup/plugin-virtual/-/plugin-virtual-2.0.0.tgz", - "integrity": "sha512-yUyQjcflsN1DGcUHj3I0NYL6Y6xrna6qjdaGjM93LjFLq8NFowhR0655ICeV9bNDbk+LI4pz7Q6xqeDdj1RdlA==", - "dev": true + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@rollup/plugin-virtual/-/plugin-virtual-3.0.1.tgz", + "integrity": "sha512-fK8O0IL5+q+GrsMLuACVNk2x21g3yaw+sG2qn16SnUd3IlBsQyvWxLMGHmCmXRMecPjGRSZ/1LmZB4rjQm68og==", + "dev": true, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } }, "node_modules/@rollup/pluginutils": { "version": "3.0.1", @@ -381,9 +490,9 @@ "dev": true }, "node_modules/@types/estree": { - "version": "0.0.50", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.50.tgz", - "integrity": "sha512-C6N5s2ZFtuZRj54k2/zyRhNDjJwwcViAM3Nbm8zjBpbqAdZ00mr0CFxvSKeO8Y/e03WVFLpQMdHYVfUd6SB+Hw==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.0.tgz", + "integrity": "sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ==", "dev": true }, "node_modules/@types/json-schema": { @@ -655,9 +764,9 @@ "dev": true }, "node_modules/acorn": { - "version": "8.8.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz", - "integrity": "sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==", + "version": "8.8.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", + "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -1111,17 +1220,16 @@ } }, "node_modules/code-red": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/code-red/-/code-red-0.2.5.tgz", - "integrity": "sha512-x+uQyJLNS1v0+74eXqM7FMPoM1fU/fN3tdexGWtCuVjCfxADt1TuuEGIGlFyCC2vhgINDctDb/rgSn8/ZDfJsQ==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/code-red/-/code-red-1.0.0.tgz", + "integrity": "sha512-x5fNWOBu7Ii38br3iVPuwQcDQM0f2h8ipvqw4qTLlOzYlrFQRz954qR0hPZ8asV5KG/igXNY8CRG6xtDUoKOJQ==", "dev": true, "dependencies": { - "@types/estree": "^0.0.50", - "acorn": "^8.0.5", - "estree-walker": "^3.0.0", - "is-reference": "^3.0.0", - "periscopic": "^3.0.4", - "sourcemap-codec": "^1.4.8" + "@jridgewell/sourcemap-codec": "^1.4.14", + "@types/estree": "^1.0.0", + "acorn": "^8.8.2", + "estree-walker": "^3.0.3", + "periscopic": "^3.1.0" } }, "node_modules/color-convert": { @@ -2292,10 +2400,13 @@ } }, "node_modules/estree-walker": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.1.tgz", - "integrity": "sha512-woY0RUD87WzMBUiZLx8NsYr23N5BKsOMZHhu2hoNRVh6NXGfoiT1KOL8G3UHlJAnEDGmfa5ubNA/AacfG+Kb0g==", - "dev": true + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "dependencies": { + "@types/estree": "^1.0.0" + } }, "node_modules/esutils": { "version": "2.0.3", @@ -3532,12 +3643,15 @@ } }, "node_modules/magic-string": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.3.tgz", - "integrity": "sha512-6QK0OpF/phMz0Q2AxILkX2mFhi7m+WMwTRg0LQKq/WBB0cDP4rYH3Wp4/d3OTXlrPLVJT/RFqj8tFeAR4nk8AA==", + "version": "0.30.0", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.0.tgz", + "integrity": "sha512-LA+31JYDJLs82r2ScLrlz1GjSgu66ZV518eyWT+S8VhyQn/JL0u9MeBOvQMGYiPk1DBiSN9DDMOcXvigJZaViQ==", "dev": true, "dependencies": { - "sourcemap-codec": "^1.4.4" + "@jridgewell/sourcemap-codec": "^1.4.13" + }, + "engines": { + "node": ">=12" } }, "node_modules/mdn-data": { @@ -4028,11 +4142,12 @@ "dev": true }, "node_modules/periscopic": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/periscopic/-/periscopic-3.0.4.tgz", - "integrity": "sha512-SFx68DxCv0Iyo6APZuw/AKewkkThGwssmU0QWtTlvov3VAtPX+QJ4CadwSaz8nrT5jPIuxdvJWB4PnD2KNDxQg==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/periscopic/-/periscopic-3.1.0.tgz", + "integrity": "sha512-vKiQ8RRtkl9P+r/+oefh25C3fhybptkHKCZSPlcXiJux2tJF55GnEj3BVn4A5gKfq9NWWXXrxkHBwVPUfH0opw==", "dev": true, "dependencies": { + "@types/estree": "^1.0.0", "estree-walker": "^3.0.0", "is-reference": "^3.0.0" } @@ -4401,21 +4516,6 @@ "deprecated": "This package has been deprecated and is no longer maintained. Please use @rollup/plugin-virtual.", "dev": true }, - "node_modules/rollup-pluginutils": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz", - "integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==", - "dev": true, - "dependencies": { - "estree-walker": "^0.6.1" - } - }, - "node_modules/rollup-pluginutils/node_modules/estree-walker": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", - "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==", - "dev": true - }, "node_modules/rollup/node_modules/acorn": { "version": "7.4.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", @@ -5451,12 +5551,37 @@ } }, "@rollup/plugin-json": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@rollup/plugin-json/-/plugin-json-4.0.1.tgz", - "integrity": "sha512-soxllkhOGgchswBAAaTe7X9G80U2tjjHvXv0sBrriLJcC/89PkP59iTrKPOfbz3SjX088mKDmMhAscuyLz8ZSg==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@rollup/plugin-json/-/plugin-json-6.0.0.tgz", + "integrity": "sha512-i/4C5Jrdr1XUarRhVu27EEwjt4GObltD7c+MkCIpO2QIbojw8MUs+CCTqOphQi3Qtg1FLmYt+l+6YeoIf51J7w==", "dev": true, "requires": { - "rollup-pluginutils": "^2.5.0" + "@rollup/pluginutils": "^5.0.1" + }, + "dependencies": { + "@rollup/pluginutils": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.0.2.tgz", + "integrity": "sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==", + "dev": true, + "requires": { + "@types/estree": "^1.0.0", + "estree-walker": "^2.0.2", + "picomatch": "^2.3.1" + } + }, + "@types/estree": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.0.tgz", + "integrity": "sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ==", + "dev": true + }, + "estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true + } } }, "@rollup/plugin-node-resolve": { @@ -5499,22 +5624,45 @@ } }, "@rollup/plugin-replace": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@rollup/plugin-replace/-/plugin-replace-2.3.0.tgz", - "integrity": "sha512-rzWAMqXAHC1w3eKpK6LxRqiF4f3qVFaa1sGii6Bp3rluKcwHNOpPt+hWRCmAH6SDEPtbPiLFf0pfNQyHs6Btlg==", + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@rollup/plugin-replace/-/plugin-replace-5.0.2.tgz", + "integrity": "sha512-M9YXNekv/C/iHHK+cvORzfRYfPbq0RDD8r0G+bMiTXjNGKulPnCT9O3Ss46WfhI6ZOCgApOP7xAdmCQJ+U2LAA==", "dev": true, "requires": { - "magic-string": "^0.25.2", - "rollup-pluginutils": "^2.6.0" + "@rollup/pluginutils": "^5.0.1", + "magic-string": "^0.27.0" }, "dependencies": { + "@rollup/pluginutils": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.0.2.tgz", + "integrity": "sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==", + "dev": true, + "requires": { + "@types/estree": "^1.0.0", + "estree-walker": "^2.0.2", + "picomatch": "^2.3.1" + } + }, + "@types/estree": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.0.tgz", + "integrity": "sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ==", + "dev": true + }, + "estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true + }, "magic-string": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", - "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.27.0.tgz", + "integrity": "sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA==", "dev": true, "requires": { - "sourcemap-codec": "^1.4.8" + "@jridgewell/sourcemap-codec": "^1.4.13" } } } @@ -5530,20 +5678,21 @@ } }, "@rollup/plugin-typescript": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@rollup/plugin-typescript/-/plugin-typescript-2.0.1.tgz", - "integrity": "sha512-UA/bN/DlHN19xdOllXmp7G7pM2ac9dQMg0q2T1rg4Bogzb7oHXj2WGafpiNpEm54PivcJdzGRJvRnI6zCISW3w==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@rollup/plugin-typescript/-/plugin-typescript-2.1.0.tgz", + "integrity": "sha512-7lXKGY06aofrceVez/YnN2axttFdHSqlUBpCJ6ebzDfxwLDKMgSV5lD4ykBcdgE7aK3egxuLkD/HKyRB5L8Log==", "dev": true, "requires": { "@rollup/pluginutils": "^3.0.0", - "resolve": "^1.12.2" + "resolve": "^1.13.1" } }, "@rollup/plugin-virtual": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@rollup/plugin-virtual/-/plugin-virtual-2.0.0.tgz", - "integrity": "sha512-yUyQjcflsN1DGcUHj3I0NYL6Y6xrna6qjdaGjM93LjFLq8NFowhR0655ICeV9bNDbk+LI4pz7Q6xqeDdj1RdlA==", - "dev": true + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@rollup/plugin-virtual/-/plugin-virtual-3.0.1.tgz", + "integrity": "sha512-fK8O0IL5+q+GrsMLuACVNk2x21g3yaw+sG2qn16SnUd3IlBsQyvWxLMGHmCmXRMecPjGRSZ/1LmZB4rjQm68og==", + "dev": true, + "requires": {} }, "@rollup/pluginutils": { "version": "3.0.1", @@ -5574,9 +5723,9 @@ "dev": true }, "@types/estree": { - "version": "0.0.50", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.50.tgz", - "integrity": "sha512-C6N5s2ZFtuZRj54k2/zyRhNDjJwwcViAM3Nbm8zjBpbqAdZ00mr0CFxvSKeO8Y/e03WVFLpQMdHYVfUd6SB+Hw==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.0.tgz", + "integrity": "sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ==", "dev": true }, "@types/json-schema": { @@ -5750,9 +5899,9 @@ "dev": true }, "acorn": { - "version": "8.8.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz", - "integrity": "sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==", + "version": "8.8.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", + "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", "dev": true }, "acorn-globals": { @@ -6111,17 +6260,16 @@ } }, "code-red": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/code-red/-/code-red-0.2.5.tgz", - "integrity": "sha512-x+uQyJLNS1v0+74eXqM7FMPoM1fU/fN3tdexGWtCuVjCfxADt1TuuEGIGlFyCC2vhgINDctDb/rgSn8/ZDfJsQ==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/code-red/-/code-red-1.0.0.tgz", + "integrity": "sha512-x5fNWOBu7Ii38br3iVPuwQcDQM0f2h8ipvqw4qTLlOzYlrFQRz954qR0hPZ8asV5KG/igXNY8CRG6xtDUoKOJQ==", "dev": true, "requires": { - "@types/estree": "^0.0.50", - "acorn": "^8.0.5", - "estree-walker": "^3.0.0", - "is-reference": "^3.0.0", - "periscopic": "^3.0.4", - "sourcemap-codec": "^1.4.8" + "@jridgewell/sourcemap-codec": "^1.4.14", + "@types/estree": "^1.0.0", + "acorn": "^8.8.2", + "estree-walker": "^3.0.3", + "periscopic": "^3.1.0" } }, "color-convert": { @@ -7026,10 +7174,13 @@ "dev": true }, "estree-walker": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.1.tgz", - "integrity": "sha512-woY0RUD87WzMBUiZLx8NsYr23N5BKsOMZHhu2hoNRVh6NXGfoiT1KOL8G3UHlJAnEDGmfa5ubNA/AacfG+Kb0g==", - "dev": true + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "requires": { + "@types/estree": "^1.0.0" + } }, "esutils": { "version": "2.0.3", @@ -7961,12 +8112,12 @@ } }, "magic-string": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.3.tgz", - "integrity": "sha512-6QK0OpF/phMz0Q2AxILkX2mFhi7m+WMwTRg0LQKq/WBB0cDP4rYH3Wp4/d3OTXlrPLVJT/RFqj8tFeAR4nk8AA==", + "version": "0.30.0", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.0.tgz", + "integrity": "sha512-LA+31JYDJLs82r2ScLrlz1GjSgu66ZV518eyWT+S8VhyQn/JL0u9MeBOvQMGYiPk1DBiSN9DDMOcXvigJZaViQ==", "dev": true, "requires": { - "sourcemap-codec": "^1.4.4" + "@jridgewell/sourcemap-codec": "^1.4.13" } }, "mdn-data": { @@ -8348,11 +8499,12 @@ "dev": true }, "periscopic": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/periscopic/-/periscopic-3.0.4.tgz", - "integrity": "sha512-SFx68DxCv0Iyo6APZuw/AKewkkThGwssmU0QWtTlvov3VAtPX+QJ4CadwSaz8nrT5jPIuxdvJWB4PnD2KNDxQg==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/periscopic/-/periscopic-3.1.0.tgz", + "integrity": "sha512-vKiQ8RRtkl9P+r/+oefh25C3fhybptkHKCZSPlcXiJux2tJF55GnEj3BVn4A5gKfq9NWWXXrxkHBwVPUfH0opw==", "dev": true, "requires": { + "@types/estree": "^1.0.0", "estree-walker": "^3.0.0", "is-reference": "^3.0.0" } @@ -8643,23 +8795,6 @@ "integrity": "sha512-HCTBpV8MwP5lNzZrHD2moVxHIToHU1EkzkKGVj6Z0DcgUfxrxrZmeQirQeLz2yhnkJqRjwiVywK9CS8jDYakrw==", "dev": true }, - "rollup-pluginutils": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz", - "integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==", - "dev": true, - "requires": { - "estree-walker": "^0.6.1" - }, - "dependencies": { - "estree-walker": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", - "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==", - "dev": true - } - } - }, "run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", diff --git a/package.json b/package.json index 975f171fe6..c04043e346 100644 --- a/package.json +++ b/package.json @@ -122,12 +122,12 @@ "@ampproject/remapping": "^0.3.0", "@jridgewell/sourcemap-codec": "^1.4.14", "@rollup/plugin-commonjs": "^11.0.0", - "@rollup/plugin-json": "^4.0.1", + "@rollup/plugin-json": "^6.0.0", "@rollup/plugin-node-resolve": "^11.2.1", - "@rollup/plugin-replace": "^2.3.0", + "@rollup/plugin-replace": "^5.0.2", "@rollup/plugin-sucrase": "^3.1.0", "@rollup/plugin-typescript": "^2.0.1", - "@rollup/plugin-virtual": "^2.0.0", + "@rollup/plugin-virtual": "^3.0.1", "@sveltejs/eslint-config": "github:sveltejs/eslint-config#v5.8.0", "@types/aria-query": "^5.0.0", "@types/mocha": "^7.0.0", @@ -138,7 +138,7 @@ "agadoo": "^2.0.0", "aria-query": "^5.1.1", "axobject-query": "^3.1.1", - "code-red": "^0.2.5", + "code-red": "^1.0.0", "css-tree": "^2.2.1", "eslint": "^8.26.0", "eslint-plugin-import": "^2.26.0", @@ -148,7 +148,7 @@ "jsdom": "^15.2.1", "kleur": "^4.1.5", "locate-character": "^2.0.5", - "magic-string": "^0.25.3", + "magic-string": "^0.30.0", "mocha": "^7.0.0", "periscopic": "^3.0.4", "puppeteer": "^2.0.0", diff --git a/src/compiler/compile/Component.ts b/src/compiler/compile/Component.ts index f7d8e8f568..0d6a329dcb 100644 --- a/src/compiler/compile/Component.ts +++ b/src/compiler/compile/Component.ts @@ -951,7 +951,7 @@ export default class Component { }); } - warn_on_undefined_store_value_references(node: Node, parent: Node, prop: string, scope: Scope) { + warn_on_undefined_store_value_references(node: Node, parent: Node, prop: string | number | symbol, scope: Scope) { if ( node.type === 'LabeledStatement' && node.label.name === '$' && diff --git a/src/compiler/compile/css/Selector.ts b/src/compiler/compile/css/Selector.ts index c7a1d8c3b1..c2ad450416 100644 --- a/src/compiler/compile/css/Selector.ts +++ b/src/compiler/compile/css/Selector.ts @@ -76,7 +76,7 @@ export default class Selector { this.blocks.forEach((block, i) => { if (i > 0) { if (block.start - c > 1) { - code.overwrite(c, block.start, block.combinator.name || ' '); + code.update(c, block.start, block.combinator.name || ' '); } } @@ -112,7 +112,7 @@ export default class Selector { } if (selector.type === 'TypeSelector' && selector.name === '*') { - code.overwrite(selector.start, selector.end, attr); + code.update(selector.start, selector.end, attr); } else { code.appendLeft(selector.end, attr); } diff --git a/src/compiler/compile/css/Stylesheet.ts b/src/compiler/compile/css/Stylesheet.ts index 9a3cbe9d13..8f54830e6a 100644 --- a/src/compiler/compile/css/Stylesheet.ts +++ b/src/compiler/compile/css/Stylesheet.ts @@ -35,7 +35,7 @@ function minify_declarations( declarations.forEach((declaration, i) => { const separator = i > 0 ? ';' : ''; if ((declaration.node.start - c) > separator.length) { - code.overwrite(c, declaration.node.start, separator); + code.update(c, declaration.node.start, separator); } declaration.minify(code); c = declaration.node.end; @@ -75,7 +75,7 @@ class Rule { if (selector.used) { const separator = started ? ',' : ''; if ((selector.node.start - c) > separator.length) { - code.overwrite(c, selector.node.start, separator); + code.update(c, selector.node.start, separator); } selector.minify(code); @@ -133,7 +133,7 @@ class Declaration { if (block.type === 'Identifier') { const name = block.name; if (keyframes.has(name)) { - code.overwrite(block.start, block.end, keyframes.get(name)); + code.update(block.start, block.end, keyframes.get(name)); } } }); @@ -156,7 +156,7 @@ class Declaration { while (regex_whitespace.test(code.original[start])) start += 1; if (start - c > 1) { - code.overwrite(c, start, ':'); + code.update(c, start, ':'); } } } @@ -204,7 +204,7 @@ class Atrule { code.remove(c, this.node.block.start); } else if (this.node.name === 'supports') { let c = this.node.start + 9; - if (this.node.prelude.start - c > 1) code.overwrite(c, this.node.prelude.start, ' '); + if (this.node.prelude.start - c > 1) code.update(c, this.node.prelude.start, ' '); this.node.prelude.children.forEach((query: CssNode) => { // TODO minify queries c = query.end; @@ -213,7 +213,7 @@ class Atrule { } else { let c = this.node.start + this.node.name.length + 1; if (this.node.prelude) { - if (this.node.prelude.start - c > 1) code.overwrite(c, this.node.prelude.start, ' '); + if (this.node.prelude.start - c > 1) code.update(c, this.node.prelude.start, ' '); c = this.node.prelude.end; } if (this.node.block && this.node.block.start - c > 0) { @@ -255,7 +255,7 @@ class Atrule { }); }); } else { - code.overwrite(start, end, keyframes.get(name)); + code.update(start, end, keyframes.get(name)); } } }); diff --git a/src/compiler/compile/render_dom/Block.ts b/src/compiler/compile/render_dom/Block.ts index 55951c961f..c7b975d0d1 100644 --- a/src/compiler/compile/render_dom/Block.ts +++ b/src/compiler/compile/render_dom/Block.ts @@ -1,4 +1,4 @@ -import Renderer from './Renderer'; +import Renderer, { BindingGroup } from './Renderer'; import Wrapper from './wrappers/shared/Wrapper'; import { b, x } from 'code-red'; import { Node, Identifier, ArrayPattern } from 'estree'; @@ -41,6 +41,7 @@ export default class Block { bindings: Map; binding_group_initialised: Set = new Set(); + binding_groups: Set = new Set(); chunks: { declarations: Array; @@ -251,6 +252,7 @@ export default class Block { } } + this.render_binding_groups(); this.render_listeners(); const properties: Record = {}; @@ -512,4 +514,10 @@ export default class Block { } } } + + render_binding_groups() { + for (const binding_group of this.binding_groups) { + binding_group.render(); + } + } } diff --git a/src/compiler/compile/render_dom/Renderer.ts b/src/compiler/compile/render_dom/Renderer.ts index c00ef95586..ad2d1b092f 100644 --- a/src/compiler/compile/render_dom/Renderer.ts +++ b/src/compiler/compile/render_dom/Renderer.ts @@ -22,6 +22,15 @@ type BitMasks = Array<{ names: string[]; }>; +export interface BindingGroup { + binding_group: (to_reference?: boolean) => Node; + contexts: string[]; + list_dependencies: Set; + keypath: string; + elements: Identifier[]; + render: () => void; +} + export default class Renderer { component: Component; // TODO Maybe Renderer shouldn't know about Component? options: CompileOptions; @@ -33,7 +42,7 @@ export default class Renderer { blocks: Array = []; readonly: Set = new Set(); meta_bindings: Array = []; // initial values for e.g. window.innerWidth, if there's a meta tag - binding_groups: Map Node; is_context: boolean; contexts: string[]; index: number; keypath: string }> = new Map(); + binding_groups: Map = new Map(); block: Block; fragment: FragmentWrapper; @@ -64,10 +73,6 @@ export default class Renderer { this.add_to_context('#slots'); } - if (this.binding_groups.size > 0) { - this.add_to_context('$$binding_groups'); - } - // main block this.block = new Block({ renderer: this, diff --git a/src/compiler/compile/render_dom/wrappers/Element/Attribute.ts b/src/compiler/compile/render_dom/wrappers/Element/Attribute.ts index ca35ea84db..6cb3a00218 100644 --- a/src/compiler/compile/render_dom/wrappers/Element/Attribute.ts +++ b/src/compiler/compile/render_dom/wrappers/Element/Attribute.ts @@ -85,6 +85,7 @@ export default class AttributeWrapper extends BaseAttributeWrapper { if (node.name === 'value') { handle_select_value_binding(this, node.dependencies); + this.parent.has_dynamic_value = true; } } @@ -180,6 +181,17 @@ export default class AttributeWrapper extends BaseAttributeWrapper { `; } + if (this.node.name === 'value' && dependencies.length > 0) { + if (this.parent.bindings.some(binding => binding.node.name === 'group')) { + this.parent.dynamic_value_condition = block.get_unique_name('value_has_changed'); + block.add_variable(this.parent.dynamic_value_condition, x`false`); + updater = b` + ${updater} + ${this.parent.dynamic_value_condition} = true; + `; + } + } + if (dependencies.length > 0) { const condition = this.get_dom_update_conditions(block, block.renderer.dirty(dependencies)); diff --git a/src/compiler/compile/render_dom/wrappers/Element/Binding.ts b/src/compiler/compile/render_dom/wrappers/Element/Binding.ts index 47e3795ec2..e48f3e0030 100644 --- a/src/compiler/compile/render_dom/wrappers/Element/Binding.ts +++ b/src/compiler/compile/render_dom/wrappers/Element/Binding.ts @@ -5,7 +5,7 @@ import InlineComponentWrapper from '../InlineComponent'; import get_object from '../../../utils/get_object'; import replace_object from '../../../utils/replace_object'; import Block from '../../Block'; -import Renderer from '../../Renderer'; +import Renderer, { BindingGroup } from '../../Renderer'; import flatten_reference from '../../../utils/flatten_reference'; import { Node, Identifier } from 'estree'; import add_to_set from '../../../utils/add_to_set'; @@ -26,6 +26,7 @@ export default class BindingWrapper { snippet: Node; is_readonly: boolean; needs_lock: boolean; + binding_group: BindingGroup; constructor(block: Block, node: Binding, parent: ElementWrapper | InlineComponentWrapper) { this.node = node; @@ -45,6 +46,10 @@ export default class BindingWrapper { this.object = get_object(this.node.expression.node).name; + if (this.node.name === 'group') { + this.binding_group = get_binding_group(parent.renderer, this, block); + } + // view to model this.handler = get_event_handler(this, parent.renderer, block, this.object, this.node.raw_expression); @@ -67,6 +72,10 @@ export default class BindingWrapper { } }); + if (this.binding_group) { + this.binding_group.list_dependencies.forEach(dep => dependencies.add(dep)); + } + return dependencies; } @@ -105,6 +114,7 @@ export default class BindingWrapper { const update_conditions: any[] = this.needs_lock ? [x`!${lock}`] : []; const mount_conditions: any[] = []; + let update_or_condition: any = null; const dependency_array = Array.from(this.get_dependencies()); @@ -142,33 +152,12 @@ export default class BindingWrapper { switch (this.node.name) { case 'group': { - const { binding_group, is_context, contexts, index, keypath } = get_binding_group(parent.renderer, this.node, block); - block.renderer.add_to_context('$$binding_groups'); + this.binding_group.elements.push(this.parent.var); - if (is_context && !block.binding_group_initialised.has(keypath)) { - if (contexts.length > 1) { - let binding_group = x`${block.renderer.reference('$$binding_groups')}[${index}]`; - for (const name of contexts.slice(0, -1)) { - binding_group = x`${binding_group}[${block.renderer.reference(name)}]`; - block.chunks.init.push( - b`${binding_group} = ${binding_group} || [];` - ); - } - } - block.chunks.init.push( - b`${binding_group(true)} = [];` - ); - block.binding_group_initialised.add(keypath); + if ((this.parent as ElementWrapper).has_dynamic_value) { + update_or_condition = (this.parent as ElementWrapper).dynamic_value_condition; } - - block.chunks.hydrate.push( - b`${binding_group(true)}.push(${parent.var});` - ); - - block.chunks.destroy.push( - b`${binding_group(true)}.splice(${binding_group(true)}.indexOf(${parent.var}), 1);` - ); break; } @@ -214,7 +203,8 @@ export default class BindingWrapper { if (update_dom) { if (update_conditions.length > 0) { - const condition = update_conditions.reduce((lhs, rhs) => x`${lhs} && ${rhs}`); + let condition = update_conditions.reduce((lhs, rhs) => x`${lhs} && ${rhs}`); + if (update_or_condition) condition = x`${update_or_condition} || (${condition})`; block.chunks.update.push(b` if (${condition}) { @@ -279,7 +269,8 @@ function get_dom_updater( return b`${element.var}.${binding.node.name} = ${binding.snippet};`; } -function get_binding_group(renderer: Renderer, value: Binding, block: Block) { +function get_binding_group(renderer: Renderer, binding: BindingWrapper, block: Block) { + const value = binding.node; const { parts } = flatten_reference(value.raw_expression); let keypath = parts.join('.'); @@ -314,41 +305,75 @@ function get_binding_group(renderer: Renderer, value: Binding, block: Block) { contexts.push(name); } + // create a global binding_group across blocks if (!renderer.binding_groups.has(keypath)) { const index = renderer.binding_groups.size; + // the bind:group depends on the list in the {#each} block as well + // as reordering (removing and adding back to the DOM) may affect the value + const list_dependencies = new Set(); + let parent = value.parent; + while (parent) { + if (parent.type === 'EachBlock') { + for (const dep of parent.expression.dynamic_dependencies()) { + list_dependencies.add(dep); + } + } + parent = parent.parent; + } + + const elements = []; contexts.forEach(context => { renderer.add_to_context(context, true); }); renderer.binding_groups.set(keypath, { - binding_group: (to_reference: boolean = false) => { - let binding_group = '$$binding_groups'; - let _secondary_indexes = contexts; + binding_group: () => { + let obj = x`$$binding_groups[${index}]`; - if (to_reference) { - binding_group = block.renderer.reference(binding_group); - _secondary_indexes = _secondary_indexes.map(name => block.renderer.reference(name)); - } - - if (_secondary_indexes.length > 0) { - let obj = x`${binding_group}[${index}]`; - _secondary_indexes.forEach(secondary_index => { + if (contexts.length > 0) { + contexts.forEach(secondary_index => { obj = x`${obj}[${secondary_index}]`; }); - return obj; - } else { - return x`${binding_group}[${index}]`; } + return obj; }, - is_context: contexts.length > 0, contexts, - index, - keypath + list_dependencies, + keypath, + elements, + render() { + const local_name = block.get_unique_name('binding_group'); + const binding_group = block.renderer.reference('$$binding_groups'); + block.add_variable(local_name); + if (contexts.length > 0) { + const indexes = { type: 'ArrayExpression', elements: contexts.map(name => block.renderer.reference(name)) }; + block.chunks.init.push( + b`${local_name} = @init_binding_group_dynamic(${binding_group}[${index}], ${indexes})` + ); + block.chunks.update.push( + b`if (${block.renderer.dirty(Array.from(list_dependencies))}) ${local_name}.u(${indexes})` + ); + } else { + block.chunks.init.push( + b`${local_name} = @init_binding_group(${binding_group}[${index}])` + ); + } + block.chunks.hydrate.push( + b`${local_name}.p(${elements})` + ); + block.chunks.destroy.push( + b`${local_name}.r()` + ); + } }); } - return renderer.binding_groups.get(keypath); + // register the binding_group for the block + const binding_group = renderer.binding_groups.get(keypath); + block.binding_groups.add(binding_group); + + return binding_group; } function get_event_handler( @@ -386,7 +411,7 @@ function get_event_handler( } } - const value = get_value_from_dom(renderer, binding.parent, binding, block, contextual_dependencies); + const value = get_value_from_dom(renderer, binding.parent, binding, contextual_dependencies); const mutation = b` ${lhs} = ${value}; @@ -402,10 +427,9 @@ function get_event_handler( } function get_value_from_dom( - renderer: Renderer, + _renderer: Renderer, element: ElementWrapper | InlineComponentWrapper, binding: BindingWrapper, - block: Block, contextual_dependencies: Set ) { const { node } = element; @@ -427,7 +451,7 @@ function get_value_from_dom( // if (name === 'group') { if (type === 'checkbox') { - const { binding_group, contexts } = get_binding_group(renderer, binding.node, block); + const { binding_group, contexts } = binding.binding_group; add_to_set(contextual_dependencies, contexts); return x`@get_binding_group_value(${binding_group()}, this.__value, this.checked)`; } diff --git a/src/compiler/compile/render_dom/wrappers/Element/index.ts b/src/compiler/compile/render_dom/wrappers/Element/index.ts index 85ee98b200..5411768605 100644 --- a/src/compiler/compile/render_dom/wrappers/Element/index.ts +++ b/src/compiler/compile/render_dom/wrappers/Element/index.ts @@ -163,6 +163,8 @@ export default class ElementWrapper extends Wrapper { has_dynamic_attribute: boolean; select_binding_dependencies?: Set; + has_dynamic_value: boolean; + dynamic_value_condition: any; var: any; void: boolean; diff --git a/src/runtime/internal/dom.ts b/src/runtime/internal/dom.ts index 5172221f8b..c80bd85aa3 100644 --- a/src/runtime/internal/dom.ts +++ b/src/runtime/internal/dom.ts @@ -13,7 +13,7 @@ export function end_hydrating() { type NodeEx = Node & { claim_order?: number, - hydrate_init? : true, + hydrate_init?: true, actual_end_child?: NodeEx, childNodes: NodeListOf, }; @@ -35,7 +35,7 @@ function init_hydrate(target: NodeEx) { if (target.hydrate_init) return; target.hydrate_init = true; - type NodeEx2 = NodeEx & {claim_order: number}; + type NodeEx2 = NodeEx & { claim_order: number }; // We know that all children have claim_order values since the unclaimed have been detached if target is not let children: ArrayLike = target.childNodes as NodeListOf; @@ -292,7 +292,7 @@ export function listen_and_update(get_handler: ()=>EventListenerOrEventListenerO } export function prevent_default(fn) { - return function(event) { + return function (event) { event.preventDefault(); // @ts-ignore return fn.call(this, event); @@ -300,7 +300,7 @@ export function prevent_default(fn) { } export function stop_propagation(fn) { - return function(event) { + return function (event) { event.stopPropagation(); // @ts-ignore return fn.call(this, event); @@ -316,14 +316,14 @@ export function stop_immediate_propagation(fn) { } export function self(fn) { - return function(event) { + return function (event) { // @ts-ignore if (event.target === this) fn.call(this, event); }; } export function trusted(fn) { - return function(event) { + return function (event) { // @ts-ignore if (event.isTrusted) fn.call(this, event); }; @@ -391,6 +391,53 @@ export function get_binding_group_value(group, __value, checked) { return Array.from(value); } +export function init_binding_group(group) { + let _inputs: HTMLInputElement[]; + return { + /* push */ p(...inputs: HTMLInputElement[]) { + _inputs = inputs; + _inputs.forEach(input => group.push(input)); + }, + + /* remove */ r() { + _inputs.forEach(input => group.splice(group.indexOf(input), 1)); + } + }; +} + +export function init_binding_group_dynamic(group, indexes: number[]) { + let _group: HTMLInputElement[] = get_binding_group(group); + let _inputs: HTMLInputElement[]; + function get_binding_group(group) { + for (let i = 0; i < indexes.length; i++) { + group = group[indexes[i]] = group[indexes[i]] || []; + } + return group; + } + function push() { + _inputs.forEach(input => _group.push(input)); + } + function remove() { + _inputs.forEach(input => _group.splice(_group.indexOf(input), 1)); + } + return { + /* update */ u(new_indexes: number[]) { + indexes = new_indexes; + const new_group = get_binding_group(group); + if (new_group !== _group) { + remove(); + _group = new_group; + push(); + } + }, + /* push */ p(...inputs: HTMLInputElement[]) { + _inputs = inputs; + push(); + }, + /* remove */ r: remove + }; +} + export function to_number(value) { return value === '' ? null : +value; } @@ -424,7 +471,7 @@ export function children(element: Element) { function init_claim_info(nodes: ChildNodeArray) { if (nodes.claim_info === undefined) { - nodes.claim_info = {last_index: 0, total_claimed: 0}; + nodes.claim_info = { last_index: 0, total_claimed: 0 }; } } @@ -704,7 +751,7 @@ export function toggle_class(element, name, toggle) { element.classList[toggle ? 'add' : 'remove'](name); } -export function custom_event(type: string, detail?: T, { bubbles = false, cancelable = false } = {}): CustomEvent { +export function custom_event(type: string, detail?: T, { bubbles = false, cancelable = false } = {}): CustomEvent { const e: CustomEvent = document.createEvent('CustomEvent'); e.initCustomEvent(type, bubbles, cancelable, detail); return e; diff --git a/src/runtime/internal/keyed_each.ts b/src/runtime/internal/keyed_each.ts index 079d5f4499..a5cfaf7fb6 100644 --- a/src/runtime/internal/keyed_each.ts +++ b/src/runtime/internal/keyed_each.ts @@ -1,4 +1,5 @@ import { transition_in, transition_out } from './transitions'; +import { run_all } from './utils'; export function destroy_block(block, lookup) { block.d(1); @@ -32,6 +33,7 @@ export function update_keyed_each(old_blocks, dirty, get_key, dynamic, ctx, list const new_blocks = []; const new_lookup = new Map(); const deltas = new Map(); + const updates = []; i = n; while (i--) { @@ -43,7 +45,8 @@ export function update_keyed_each(old_blocks, dirty, get_key, dynamic, ctx, list block = create_each_block(key, child_ctx); block.c(); } else if (dynamic) { - block.p(child_ctx, dirty); + // defer updates until all the DOM shuffling is done + updates.push(() => block.p(child_ctx, dirty)); } new_lookup.set(key, new_blocks[i] = block); @@ -99,6 +102,8 @@ export function update_keyed_each(old_blocks, dirty, get_key, dynamic, ctx, list while (n) insert(new_blocks[n - 1]); + run_all(updates); + return new_blocks; } diff --git a/test/runtime/samples/binding-input-group-each-10/_config.js b/test/runtime/samples/binding-input-group-each-10/_config.js new file mode 100644 index 0000000000..edfc508f05 --- /dev/null +++ b/test/runtime/samples/binding-input-group-each-10/_config.js @@ -0,0 +1,52 @@ +// https://github.com/sveltejs/svelte/issues/7633 +export default { + async test({ assert, target, component, window }) { + let inputs = target.querySelectorAll('input'); + + assert.equal(inputs[0].checked, true); + assert.equal(inputs[1].checked, false); + assert.equal(inputs[2].checked, false); + + component.moveDown(0); + component.moveDown(1); + await Promise.resolve(); + + assert.htmlEqual( + target.innerHTML, + ` +
+ b +
+
+ c +
+
+ a +
+ ` + ); + + // after shifting order, should still keep the correct radio checked + inputs = target.querySelectorAll('input'); + assert.equal(inputs[0].checked, false); + assert.equal(inputs[1].checked, false); + assert.equal(inputs[2].checked, true); + + (component.current = 'b'); + await Promise.resolve(); + + inputs = target.querySelectorAll('input'); + assert.equal(inputs[0].checked, true); + assert.equal(inputs[1].checked, false); + assert.equal(inputs[2].checked, false); + + component.moveDown(1); + await Promise.resolve(); + + // after shifting order, should still keep the correct radio checked + inputs = target.querySelectorAll('input'); + assert.equal(inputs[0].checked, true); + assert.equal(inputs[1].checked, false); + assert.equal(inputs[2].checked, false); + } +}; diff --git a/test/runtime/samples/binding-input-group-each-10/main.svelte b/test/runtime/samples/binding-input-group-each-10/main.svelte new file mode 100644 index 0000000000..7c81cada9a --- /dev/null +++ b/test/runtime/samples/binding-input-group-each-10/main.svelte @@ -0,0 +1,36 @@ + + +{#each list as item (item.name)} +
+ {item.name} + {#if true} + + {/if} +
+{/each} + diff --git a/test/runtime/samples/binding-input-group-each-11/_config.js b/test/runtime/samples/binding-input-group-each-11/_config.js new file mode 100644 index 0000000000..a90993861a --- /dev/null +++ b/test/runtime/samples/binding-input-group-each-11/_config.js @@ -0,0 +1,88 @@ +// https://github.com/sveltejs/svelte/issues/6112 +export default { + async test({ assert, target, component, window }) { + let inputs = target.querySelectorAll('input'); + + const check = (set) => { + for (let i = 0; i < inputs.length; i++) { + assert.equal(inputs[i].checked, set.has(i)); + } + }; + + assert.htmlEqual( + target.innerHTML, + ` +
1
+
2 +
+ + +
+
+ + +
+
+
3 +
+ + +
+
+ + +
+
+ ` + ); + + check(new Set([0, 2, 5, 6])); + + const event = new window.Event('change'); + + // dom to value + inputs[3].checked = true; + await inputs[3].dispatchEvent(event); + + check(new Set([0, 3, 5, 6])); + assert.equal(component.pipelineOperations[1].operation.args[1].value, 'd'); + + // remove item + component.pipelineOperations = component.pipelineOperations.slice(1); + await Promise.resolve(); + + assert.htmlEqual( + target.innerHTML, + ` +
2 +
+ + +
+
+ + +
+
+
3 +
+ + +
+
+ + +
+
+ ` + ); + + inputs = target.querySelectorAll('input'); + check(new Set([0, 3, 5, 6])); + + inputs[2].checked = true; + await inputs[2].dispatchEvent(event); + + check(new Set([0, 2, 5, 6])); + } +}; diff --git a/test/runtime/samples/binding-input-group-each-11/main.svelte b/test/runtime/samples/binding-input-group-each-11/main.svelte new file mode 100644 index 0000000000..7c759b5bb4 --- /dev/null +++ b/test/runtime/samples/binding-input-group-each-11/main.svelte @@ -0,0 +1,60 @@ + + +{#each pipelineOperations as { operation, id } (id)} +
+ {id} + {#each operation.args as arg} +
+ {#each arg.options as { value }} + + {/each} +
+ {/each} +
+{/each} diff --git a/test/runtime/samples/binding-input-group-each-12/_config.js b/test/runtime/samples/binding-input-group-each-12/_config.js new file mode 100644 index 0000000000..a3d6c92879 --- /dev/null +++ b/test/runtime/samples/binding-input-group-each-12/_config.js @@ -0,0 +1,89 @@ +// https://github.com/sveltejs/svelte/issues/6112 +export default { + async test({ assert, target, component, window }) { + let inputs = target.querySelectorAll('input'); + + const check = (set) => { + for (let i = 0; i < inputs.length; i++) { + assert.equal(inputs[i].checked, set.has(i)); + } + }; + + assert.htmlEqual( + target.innerHTML, + ` +
1
+
2 +
+ + +
+
+ + +
+
+
3 +
+ + +
+
+ + +
+
+ ` + ); + + check(new Set([0, 2])); + + const event = new window.Event('change'); + + // dom to value + inputs[3].checked = true; + await inputs[3].dispatchEvent(event); + + check(new Set([0, 2, 3])); + assert.deepEqual(component.pipelineOperations[1].operation.args[1].value, ['c', 'd']); + + // remove item + component.pipelineOperations = component.pipelineOperations.slice(1); + await Promise.resolve(); + + assert.htmlEqual( + target.innerHTML, + ` +
2 +
+ + +
+
+ + +
+
+
3 +
+ + +
+
+ + +
+
+ ` + ); + + inputs = target.querySelectorAll('input'); + check(new Set([0, 2, 3])); + + inputs[5].checked = true; + await inputs[5].dispatchEvent(event); + + check(new Set([0, 2, 3, 5])); + assert.deepEqual(component.pipelineOperations[1].operation.args[0].value, ['b']); + } +}; diff --git a/test/runtime/samples/binding-input-group-each-12/main.svelte b/test/runtime/samples/binding-input-group-each-12/main.svelte new file mode 100644 index 0000000000..289353778a --- /dev/null +++ b/test/runtime/samples/binding-input-group-each-12/main.svelte @@ -0,0 +1,60 @@ + + +{#each pipelineOperations as { operation, id } (id)} +
+ {id} + {#each operation.args as arg} +
+ {#each arg.options as { value }} + + {/each} +
+ {/each} +
+{/each} diff --git a/test/runtime/samples/binding-input-group-each-13/_config.js b/test/runtime/samples/binding-input-group-each-13/_config.js new file mode 100644 index 0000000000..affb94b8fb --- /dev/null +++ b/test/runtime/samples/binding-input-group-each-13/_config.js @@ -0,0 +1,30 @@ +export default { + async test({ assert, target, window }) { + const [input1, input2] = target.querySelectorAll('input[type=text]'); + const radio = target.querySelector('input[type=radio]'); + + assert.equal(radio.checked, false); + + const event = new window.Event('input'); + + input1.value = 'world'; + await input1.dispatchEvent(event); + assert.equal(radio.checked, true); + + input2.value = 'foo'; + await input2.dispatchEvent(event); + assert.equal(radio.checked, false); + + input1.value = 'foo'; + await input1.dispatchEvent(event); + assert.equal(radio.checked, true); + + input1.value = 'bar'; + await input1.dispatchEvent(event); + assert.equal(radio.checked, false); + + input2.value = 'bar'; + await input2.dispatchEvent(event); + assert.equal(radio.checked, true); + } +}; diff --git a/test/runtime/samples/binding-input-group-each-13/main.svelte b/test/runtime/samples/binding-input-group-each-13/main.svelte new file mode 100644 index 0000000000..592be2ae9d --- /dev/null +++ b/test/runtime/samples/binding-input-group-each-13/main.svelte @@ -0,0 +1,10 @@ + + + + + + + diff --git a/test/runtime/samples/binding-input-group-each-8/_config.js b/test/runtime/samples/binding-input-group-each-8/_config.js new file mode 100644 index 0000000000..b17b801a83 --- /dev/null +++ b/test/runtime/samples/binding-input-group-each-8/_config.js @@ -0,0 +1,78 @@ +// https://github.com/sveltejs/svelte/issues/7884 +export default { + async test({ assert, target, component, window }) { + let inputs = target.querySelectorAll('input'); + + assert.htmlEqual(target.innerHTML, ` +

{"foo":[],"bar":[]}

+

foo

+
    +
  • +
  • +
  • +
+

bar

+
    +
  • +
  • +
  • +
+ `); + + const event = new window.Event('change'); + + inputs[0].checked = true; + await inputs[0].dispatchEvent(event); + inputs[2].checked = true; + await inputs[2].dispatchEvent(event); + inputs[3].checked = true; + await inputs[3].dispatchEvent(event); + + assert.htmlEqual(target.innerHTML, ` +

{"foo":[1,3],"bar":[1]}

+

foo

+
    +
  • +
  • +
  • +
+

bar

+
    +
  • +
  • +
  • +
+ `); + + await component.update(); + + assert.htmlEqual(target.innerHTML, ` +

{"foo":[1,3],"bar":[1],"qux":[]}

+

qux

+
    +
  • +
  • +
  • +
+ `); + + inputs = target.querySelectorAll('input'); + inputs[0].checked = true; + await inputs[0].dispatchEvent(event); + + assert.htmlEqual(target.innerHTML, ` +

{"foo":[1,3],"bar":[1],"qux":[4]}

+

qux

+
    +
  • +
  • +
  • +
+ `); + assert.equal(inputs[0].checked, true); + assert.equal(inputs[1].checked, false); + assert.equal(inputs[2].checked, false); + } +}; + + diff --git a/test/runtime/samples/binding-input-group-each-8/main.svelte b/test/runtime/samples/binding-input-group-each-8/main.svelte new file mode 100644 index 0000000000..a6c5bccac0 --- /dev/null +++ b/test/runtime/samples/binding-input-group-each-8/main.svelte @@ -0,0 +1,36 @@ + + +

+ {JSON.stringify(object)} +

+ +{#each keys as key (key)} +

{key}

+
    + {#each values as value (value)} +
  • + +
  • + {/each} +
+{/each} diff --git a/test/runtime/samples/binding-input-group-each-9/_config.js b/test/runtime/samples/binding-input-group-each-9/_config.js new file mode 100644 index 0000000000..e2b48a83d7 --- /dev/null +++ b/test/runtime/samples/binding-input-group-each-9/_config.js @@ -0,0 +1,49 @@ +// https://github.com/sveltejs/svelte/issues/7633 +export default { + async test({ assert, target, component, window }) { + let inputs = target.querySelectorAll('input'); + + assert.equal(inputs[0].checked, true); + assert.equal(inputs[1].checked, false); + assert.equal(inputs[2].checked, false); + + await component.moveDown(0); + await component.moveDown(1); + + assert.htmlEqual( + target.innerHTML, + ` +
+ b +
+
+ c +
+
+ a +
+ ` + ); + + // after shifting order, should still keep the correct radio checked + inputs = target.querySelectorAll('input'); + assert.equal(inputs[0].checked, false); + assert.equal(inputs[1].checked, false); + assert.equal(inputs[2].checked, true); + + await (component.current = 'b'); + + inputs = target.querySelectorAll('input'); + assert.equal(inputs[0].checked, true); + assert.equal(inputs[1].checked, false); + assert.equal(inputs[2].checked, false); + + await component.moveDown(1); + + // after shifting order, should still keep the correct radio checked + inputs = target.querySelectorAll('input'); + assert.equal(inputs[0].checked, true); + assert.equal(inputs[1].checked, false); + assert.equal(inputs[2].checked, false); + } +}; diff --git a/test/runtime/samples/binding-input-group-each-9/main.svelte b/test/runtime/samples/binding-input-group-each-9/main.svelte new file mode 100644 index 0000000000..ee89123a9a --- /dev/null +++ b/test/runtime/samples/binding-input-group-each-9/main.svelte @@ -0,0 +1,36 @@ + + +{#each list as item} +
+ {item.name} + {#if true} + + {/if} +
+{/each} + diff --git a/test/sourcemaps/samples/compile-option-dev/test.js b/test/sourcemaps/samples/compile-option-dev/test.js index f169ab8832..eec81fc93e 100644 --- a/test/sourcemaps/samples/compile-option-dev/test.js +++ b/test/sourcemaps/samples/compile-option-dev/test.js @@ -18,10 +18,13 @@ export async function test({ assert, css, js }) { // TODO make util fn + move to test index.js const sourcefile = 'input.svelte'; [ - // TODO how to get line + column numbers? + // TODO: get line and col num from input.svelte rather than hardcoding here [css, '--keep-me', 13, 2], - [css, '--done-replace-once', 6, 5], - [css, '--done-replace-twice', 9, 5] + // TODO: these should be 7, 2 and 10, 2 + // we use locate_1 which means lines are 1-indexed and cols are 0-indexed + // each tab is 1 col + [css, '--done-replace-once', 6, 4], + [css, '--done-replace-twice', 9, 4] ] .forEach(([where, content, line, column]) => { assert.deepEqual(