diff --git a/.eslintignore b/.eslintignore index 04940e2f7d9..a0ca1e55c84 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,6 +1,7 @@ **/_actual.js **/expected.js test/*/samples/*/output.js +node_modules # output files animate/*.js diff --git a/.eslintrc.json b/.eslintrc.json index 26b87eab682..722b0e90674 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -21,6 +21,7 @@ "prefer-const": [2, { "destructuring": "all" }], "arrow-spacing": 2, "no-inner-declarations": 0, + "require-atomic-updates": "off", "@typescript-eslint/indent": ["error", "tab", { "SwitchCase": 1, "ignoredNodes": ["TemplateLiteral"] diff --git a/CHANGELOG.md b/CHANGELOG.md index 2c614708478..340ef8c1763 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Svelte changelog +## 3.6.4 + +* Run `onMount` functions in correct order, and before initial `afterUpdate` functions ([#2281](https://github.com/sveltejs/svelte/issues/2281)) +* Fix code transformation for shorthand methods ([#2906](https://github.com/sveltejs/svelte/issues/2906)) +* Fix assignments in inline functions ([#3038](https://github.com/sveltejs/svelte/issues/3038)) + ## 3.6.3 * Fix await block mounting inside removed if block ([#1496](https://github.com/sveltejs/svelte/issues/1496)) diff --git a/package-lock.json b/package-lock.json index 63352dbb0bc..66198800e8b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "svelte", - "version": "3.6.2", + "version": "3.6.3", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -30,6 +30,12 @@ "integrity": "sha512-UdVB1rSL7H8TS8674fH02p5lRbhfIqQ18YKLxLKEnHFztHUH6bhMqjebMxgSTmWVrs5raS5JSLJIKKHFT4WfPg==", "dev": true }, + "@types/eslint-visitor-keys": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", + "integrity": "sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag==", + "dev": true + }, "@types/estree": { "version": "0.0.39", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", @@ -55,45 +61,44 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-1.9.0.tgz", - "integrity": "sha512-FOgfBorxjlBGpDIw+0LaZIXRX6GEEUfzj8LXwaQIUCp+gDOvkI+1WgugJ7SmWiISqK9Vj5r8S7NDKO/LB+6X9A==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-1.11.0.tgz", + "integrity": "sha512-mXv9ccCou89C8/4avKHuPB2WkSZyY/XcTQUXd5LFZAcLw1I3mWYVjUu6eS9Ja0QkP/ClolbcW9tb3Ov/pMdcqw==", "dev": true, "requires": { - "@typescript-eslint/experimental-utils": "1.9.0", - "@typescript-eslint/parser": "1.9.0", + "@typescript-eslint/experimental-utils": "1.11.0", "eslint-utils": "^1.3.1", "functional-red-black-tree": "^1.0.1", "regexpp": "^2.0.1", - "requireindex": "^1.2.0", "tsutils": "^3.7.0" } }, "@typescript-eslint/experimental-utils": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-1.9.0.tgz", - "integrity": "sha512-1s2dY9XxBwtS9IlSnRIlzqILPyeMly5tz1bfAmQ84Ul687xBBve5YsH5A5EKeIcGurYYqY2w6RkHETXIwnwV0A==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-1.11.0.tgz", + "integrity": "sha512-7LbfaqF6B8oa8cp/315zxKk8FFzosRzzhF8Kn/ZRsRsnpm7Qcu25cR/9RnAQo5utZ2KIWVgaALr+ZmcbG47ruw==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "1.9.0" + "@typescript-eslint/typescript-estree": "1.11.0", + "eslint-scope": "^4.0.0" } }, "@typescript-eslint/parser": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-1.9.0.tgz", - "integrity": "sha512-CWgC1XrQ34H/+LwAU7vY5xteZDkNqeAkeidEpJnJgkKu0yqQ3ZhQ7S+dI6MX4vmmM1TKRbOrKuXc6W0fIHhdbA==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-1.11.0.tgz", + "integrity": "sha512-5xBExyXaxVyczrZvbRKEXvaTUFFq7gIM9BynXukXZE0zF3IQP/FxF4mPmmh3gJ9egafZFqByCpPTFm3dk4SY7Q==", "dev": true, "requires": { - "@typescript-eslint/experimental-utils": "1.9.0", - "@typescript-eslint/typescript-estree": "1.9.0", - "eslint-scope": "^4.0.0", + "@types/eslint-visitor-keys": "^1.0.0", + "@typescript-eslint/experimental-utils": "1.11.0", + "@typescript-eslint/typescript-estree": "1.11.0", "eslint-visitor-keys": "^1.0.0" } }, "@typescript-eslint/typescript-estree": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-1.9.0.tgz", - "integrity": "sha512-7Eg0TEQpCkTsEwsl1lIzd6i7L3pJLQFWesV08dS87bNz0NeSjbL78gNAP1xCKaCejkds4PhpLnZkaAjx9SU8OA==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-1.11.0.tgz", + "integrity": "sha512-fquUHF5tAx1sM2OeRCC7wVxFd1iMELWMGCzOSmJ3pLzArj9+kRixdlC4d5MncuzXpjEqc6045p3KwM0o/3FuUA==", "dev": true, "requires": { "lodash.unescape": "4.0.1", @@ -676,7 +681,7 @@ }, "commander": { "version": "2.15.1", - "resolved": "http://registry.npmjs.org/commander/-/commander-2.15.1.tgz", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", "dev": true }, @@ -1035,13 +1040,13 @@ } }, "eslint": { - "version": "5.16.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.16.0.tgz", - "integrity": "sha512-S3Rz11i7c8AA5JPv7xAH+dOyq/Cu/VXHiHXBPOU1k/JAM5dXqQPt3qcrhpHSorXmrpu2g0gkIBVXAqCpzfoZIg==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-6.0.1.tgz", + "integrity": "sha512-DyQRaMmORQ+JsWShYsSg4OPTjY56u1nCjAmICrE8vLWqyLKxhFXOthwMj1SA8xwfrv0CofLNVnqbfyhwCkaO0w==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", - "ajv": "^6.9.1", + "ajv": "^6.10.0", "chalk": "^2.1.0", "cross-spawn": "^6.0.5", "debug": "^4.0.1", @@ -1049,18 +1054,19 @@ "eslint-scope": "^4.0.3", "eslint-utils": "^1.3.1", "eslint-visitor-keys": "^1.0.0", - "espree": "^5.0.1", + "espree": "^6.0.0", "esquery": "^1.0.1", "esutils": "^2.0.2", "file-entry-cache": "^5.0.1", "functional-red-black-tree": "^1.0.1", - "glob": "^7.1.2", + "glob-parent": "^3.1.0", "globals": "^11.7.0", "ignore": "^4.0.6", "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", "inquirer": "^6.2.2", - "js-yaml": "^3.13.0", + "is-glob": "^4.0.0", + "js-yaml": "^3.13.1", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.3.0", "lodash": "^4.17.11", @@ -1068,7 +1074,6 @@ "mkdirp": "^0.5.1", "natural-compare": "^1.4.0", "optionator": "^0.8.2", - "path-is-inside": "^1.0.2", "progress": "^2.0.0", "regexpp": "^2.0.1", "semver": "^5.5.1", @@ -1147,9 +1152,9 @@ } }, "eslint-plugin-import": { - "version": "2.17.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.17.3.tgz", - "integrity": "sha512-qeVf/UwXFJbeyLbxuY8RgqDyEKCkqV7YC+E5S5uOjAp4tOc8zj01JP3ucoBM8JcEqd1qRasJSg6LLlisirfy0Q==", + "version": "2.18.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.18.0.tgz", + "integrity": "sha512-PZpAEC4gj/6DEMMoU2Df01C5c50r7zdGIN52Yfi7CvvWaYssG7Jt5R9nFG5gmqodxNOz9vQS87xk6Izdtpdrig==", "dev": true, "requires": { "array-includes": "^3.0.3", @@ -1224,9 +1229,9 @@ "dev": true }, "espree": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-5.0.1.tgz", - "integrity": "sha512-qWAZcWh4XE/RwzLJejfcofscgMc9CamR6Tn1+XRXNzrvUSSbiAjGOI/fggztjIi7y9VLPqnICMIPiGyr8JaZ0A==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-6.0.0.tgz", + "integrity": "sha512-lJvCS6YbCn3ImT3yKkPe0+tJ+mH6ljhGNjHQH9mRtiO6gjhVAOhVXW1yjnwqGwTkK3bGbye+hb00nFNmu0l/1Q==", "dev": true, "requires": { "acorn": "^6.0.7", @@ -1430,9 +1435,9 @@ } }, "flatted": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.0.tgz", - "integrity": "sha512-R+H8IZclI8AAkSBRQJLVOsxwAoHd6WC40b4QTNWIjzAa6BXOBfQcM587MXDTVPeYaopFNWHUFLx7eNmHDSxMWg==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.1.tgz", + "integrity": "sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg==", "dev": true }, "for-in": { @@ -1561,6 +1566,27 @@ "path-is-absolute": "^1.0.0" } }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, "globals": { "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", @@ -1778,9 +1804,9 @@ } }, "import-fresh": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.0.0.tgz", - "integrity": "sha512-pOnA9tfM3Uwics+SaBLCNyZZZbK+4PTu0OPZtLlMIrv17EdBoC15S9Kn8ckJ9TZTyKb3ywNE5y1yeDxxGA7nTQ==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.1.0.tgz", + "integrity": "sha512-PpuksHKGt8rXfWEr9m9EHIpgyyaltBy8+eF6GJM0QCAxMgxCfucMF3mjecK2QsJr0amJW7gTqh5/wht0z2UhEQ==", "dev": true, "requires": { "parent-module": "^1.0.0", @@ -1810,9 +1836,9 @@ "dev": true }, "inquirer": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.3.1.tgz", - "integrity": "sha512-MmL624rfkFt4TG9y/Jvmt8vdmOo836U7Y0Hxr2aFk3RelZEGX4Igk0KabWrcaaZaTv9uzglOqWh1Vly+FAWAXA==", + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.4.1.tgz", + "integrity": "sha512-/Jw+qPZx4EDYsaT6uz7F4GJRNFMRdKNeUZw3ZnKV8lyuUgz/YWRCSUAJMZSVhSq4Ec0R2oYnyi6b3d4JXcL5Nw==", "dev": true, "requires": { "ansi-escapes": "^3.2.0", @@ -1929,12 +1955,27 @@ "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", "dev": true }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, "is-fullwidth-code-point": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", "dev": true }, + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, "is-module": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", @@ -2357,7 +2398,7 @@ }, "minimist": { "version": "0.0.8", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", "dev": true }, @@ -2782,6 +2823,12 @@ "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", "dev": true }, + "path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", + "dev": true + }, "path-exists": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", @@ -2794,12 +2841,6 @@ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "dev": true }, - "path-is-inside": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", - "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", - "dev": true - }, "path-key": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", @@ -3052,12 +3093,6 @@ "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", "dev": true }, - "requireindex": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/requireindex/-/requireindex-1.2.0.tgz", - "integrity": "sha512-L9jEkOi3ASd9PYit2cwRfyppc9NoABujTP8/5gFcbERmo5jUoAKovIC3fsF17pkTnGsrByysqX+Kxd2OTNI1ww==", - "dev": true - }, "resolve": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.10.0.tgz", @@ -3527,7 +3562,7 @@ }, "safe-regex": { "version": "1.1.0", - "resolved": "http://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", "dev": true, "requires": { @@ -3950,9 +3985,9 @@ "dev": true }, "table": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/table/-/table-5.4.0.tgz", - "integrity": "sha512-nHFDrxmbrkU7JAFKqKbDJXfzrX2UBsWmrieXFTGxiI5e4ncg3VqsZeI4EzNmX0ncp4XNGVeoxIWJXfCIXwrsvw==", + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/table/-/table-5.4.1.tgz", + "integrity": "sha512-E6CK1/pZe2N75rGZQotFOdmzWQ1AILtgYbMAbAjvms0S1l5IDB47zG3nCnFGB/w+7nB3vKofbLXCH7HPBo864w==", "dev": true, "requires": { "ajv": "^6.9.1", diff --git a/package.json b/package.json index 1e278df9ba8..a158083ac54 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "svelte", - "version": "3.6.3", + "version": "3.6.4", "description": "Cybernetically enhanced web apps", "module": "index.mjs", "main": "index", @@ -58,16 +58,16 @@ "devDependencies": { "@types/mocha": "^5.2.0", "@types/node": "=8", - "@typescript-eslint/eslint-plugin": "^1.9.0", - "@typescript-eslint/parser": "^1.9.0", + "@typescript-eslint/eslint-plugin": "^1.11.0", + "@typescript-eslint/parser": "^1.11.0", "acorn": "^6.1.1", "acorn-dynamic-import": "^4.0.0", "agadoo": "^1.0.1", "c8": "^3.4.0", "codecov": "^3.0.0", "css-tree": "1.0.0-alpha22", - "eslint": "^5.16.0", - "eslint-plugin-import": "^2.17.3", + "eslint": "^6.0.1", + "eslint-plugin-import": "^2.18.0", "estree-walker": "^0.6.1", "is-reference": "^1.1.1", "jsdom": "^12.2.0", diff --git a/site/.eslintrc.json b/site/.eslintrc.json index df5e719204b..78216cb5e0e 100644 --- a/site/.eslintrc.json +++ b/site/.eslintrc.json @@ -20,7 +20,8 @@ "prefer-arrow-callback": 2, "prefer-const": [2, { "destructuring": "all" }], "arrow-spacing": 2, - "no-inner-declarations": 0 + "no-inner-declarations": 0, + "require-atomic-updates": 0 }, "env": { "es6": true, @@ -34,6 +35,12 @@ "plugin:import/warnings" ], "plugins": ["svelte3"], + "overrides": [ + { + "files": "*.svelte", + "processor": "svelte3/svelte3" + } + ], "parserOptions": { "ecmaVersion": 9, "sourceType": "module" diff --git a/site/content/blog/2019-04-15-setting-up-your-editor.md b/site/content/blog/2019-04-15-setting-up-your-editor.md index c157682e447..bea7f4c762b 100644 --- a/site/content/blog/2019-04-15-setting-up-your-editor.md +++ b/site/content/blog/2019-04-15-setting-up-your-editor.md @@ -10,4 +10,24 @@ draft: true * eslint-plugin-svelte3 * svelte-vscode -* associating .svelte files with HTML in VSCode, Sublime, Atom, etc etc etc \ No newline at end of file +* associating .svelte files with HTML in VSCode, Sublime, Atom, etc etc etc + +## Vim/Neovim + +To treat all `*.svelte` files as HTML, add the following line to your `init.vim`: + +```bash +au! BufNewFile,BufRead *.svelte set ft=html +``` + +To temporarily turn on HTML syntax highlighting for the current buffer, use: + +```bash +:set ft=html +``` + +To set the filetype for a single file, use a [modeline](https://vim.fandom.com/wiki/Modeline_magic): + +```bash + +``` diff --git a/site/package-lock.json b/site/package-lock.json index 9d4c8c9c8c6..b44cd757efc 100644 --- a/site/package-lock.json +++ b/site/package-lock.json @@ -2125,9 +2125,9 @@ "dev": true }, "eslint-plugin-svelte3": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-svelte3/-/eslint-plugin-svelte3-1.2.0.tgz", - "integrity": "sha512-7tuYh8YdwE9PP96U9qNJUSVMaxxUS/HZEZtEDlNGSAe0g40xd12pJo6lrc5wGxOmXpR6adGy5DnkSSF1UXGDKg==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-svelte3/-/eslint-plugin-svelte3-2.5.0.tgz", + "integrity": "sha512-oFRl4fbI/b1+Wp0igAssyTSkGwTv3iVaZVFSQl+k+4J9vKQ1T0niAM35EMfZ/nm9747Um3Vr032RMtqw3M8GmA==", "dev": true }, "esm": { diff --git a/site/package.json b/site/package.json index 9bace481aef..098450e3557 100644 --- a/site/package.json +++ b/site/package.json @@ -38,7 +38,7 @@ "@sveltejs/svelte-repl": "^0.1.8", "degit": "^2.1.3", "dotenv": "^8.0.0", - "eslint-plugin-svelte3": "^1.0.0", + "eslint-plugin-svelte3": "^2.5.0", "esm": "^3.2.22", "jimp": "^0.6.0", "mocha": "^6.1.3", diff --git a/src/compiler/compile/nodes/shared/Expression.ts b/src/compiler/compile/nodes/shared/Expression.ts index e85c1de5e5b..ee04f83b776 100644 --- a/src/compiler/compile/nodes/shared/Expression.ts +++ b/src/compiler/compile/nodes/shared/Expression.ts @@ -270,7 +270,7 @@ export default class Expression { }); } else { dependencies.add(name); - component.add_reference(name); + component.add_reference(name); // TODO is this redundant/misplaced? } } else if (!is_synthetic && is_contextual(component, template_scope, name)) { code.prependRight(node.start, key === 'key' && parent.shorthand @@ -288,41 +288,7 @@ export default class Expression { this.skip(); } - if (function_expression) { - if (node.type === 'AssignmentExpression') { - const names = node.left.type === 'MemberExpression' - ? [get_object(node.left).name] - : extract_names(node.left); - - if (node.operator === '=' && nodes_match(node.left, node.right)) { - const dirty = names.filter(name => { - return !scope.declarations.has(name); - }); - - if (dirty.length) component.has_reactive_assignments = true; - - code.overwrite(node.start, node.end, dirty.map(n => component.invalidate(n)).join('; ')); - } else { - names.forEach(name => { - if (scope.declarations.has(name)) return; - - const variable = component.var_lookup.get(name); - if (variable && variable.hoistable) return; - - pending_assignments.add(name); - }); - } - } else if (node.type === 'UpdateExpression') { - const { name } = get_object(node.argument); - - if (scope.declarations.has(name)) return; - - const variable = component.var_lookup.get(name); - if (variable && variable.hoistable) return; - - pending_assignments.add(name); - } - } else { + if (!function_expression) { if (node.type === 'AssignmentExpression') { // TODO should this be a warning/error? `

{foo = 1}

` } @@ -442,11 +408,49 @@ export default class Expression { `); } + if (parent && parent.method) { + code.prependRight(node.start, ': '); + } + function_expression = null; dependencies = null; contextual_dependencies = null; } + if (node.type === 'AssignmentExpression') { + const names = node.left.type === 'MemberExpression' + ? [get_object(node.left).name] + : extract_names(node.left); + + if (node.operator === '=' && nodes_match(node.left, node.right)) { + const dirty = names.filter(name => { + return !scope.declarations.has(name); + }); + + if (dirty.length) component.has_reactive_assignments = true; + + code.overwrite(node.start, node.end, dirty.map(n => component.invalidate(n)).join('; ')); + } else { + names.forEach(name => { + if (scope.declarations.has(name)) return; + + const variable = component.var_lookup.get(name); + if (variable && variable.hoistable) return; + + pending_assignments.add(name); + }); + } + } else if (node.type === 'UpdateExpression') { + const { name } = get_object(node.argument); + + if (scope.declarations.has(name)) return; + + const variable = component.var_lookup.get(name); + if (variable && variable.hoistable) return; + + pending_assignments.add(name); + } + if (/Statement/.test(node.type)) { if (pending_assignments.size > 0) { const has_semi = code.original[node.end - 1] === ';'; @@ -459,7 +463,7 @@ export default class Expression { if (/^(Break|Continue|Return)Statement/.test(node.type)) { if (node.argument) { code.overwrite(node.start, node.argument.start, `var $$result = `); - code.appendLeft(node.argument.end, `${insert}; return $$result`); + code.appendLeft(node.end, `${insert}; return $$result`); } else { code.prependRight(node.start, `${insert}; `); } diff --git a/src/compiler/compile/render_dom/wrappers/EachBlock.ts b/src/compiler/compile/render_dom/wrappers/EachBlock.ts index 242d14b7932..42792efce71 100644 --- a/src/compiler/compile/render_dom/wrappers/EachBlock.ts +++ b/src/compiler/compile/render_dom/wrappers/EachBlock.ts @@ -493,7 +493,7 @@ export default class EachBlockWrapper extends Wrapper { const out = block.get_unique_name('out'); block.builders.init.add_block(deindent` - const ${out} = i => @transition_out(${iterations}[i], 1, () => { + const ${out} = i => @transition_out(${iterations}[i], 1, 1, () => { ${iterations}[i] = null; }); `); diff --git a/src/compiler/compile/render_dom/wrappers/IfBlock.ts b/src/compiler/compile/render_dom/wrappers/IfBlock.ts index a783364d030..fe870df862d 100644 --- a/src/compiler/compile/render_dom/wrappers/IfBlock.ts +++ b/src/compiler/compile/render_dom/wrappers/IfBlock.ts @@ -326,7 +326,7 @@ export default class IfBlockWrapper extends Wrapper { const destroy_old_block = deindent` @group_outros(); - @transition_out(${if_blocks}[${previous_block_index}], 1, () => { + @transition_out(${if_blocks}[${previous_block_index}], 1, 1, () => { ${if_blocks}[${previous_block_index}] = null; }); @check_outros(); @@ -439,7 +439,7 @@ export default class IfBlockWrapper extends Wrapper { ${enter} } else if (${name}) { @group_outros(); - @transition_out(${name}, 1, () => { + @transition_out(${name}, 1, 1, () => { ${name} = null; }); @check_outros(); diff --git a/src/compiler/compile/render_dom/wrappers/InlineComponent/index.ts b/src/compiler/compile/render_dom/wrappers/InlineComponent/index.ts index 82e3fcd56b9..8f6aafd5db5 100644 --- a/src/compiler/compile/render_dom/wrappers/InlineComponent/index.ts +++ b/src/compiler/compile/render_dom/wrappers/InlineComponent/index.ts @@ -388,8 +388,8 @@ export default class InlineComponentWrapper extends Wrapper { if (${name}) { @group_outros(); const old_component = ${name}; - @transition_out(old_component.$$.fragment, 1, () => { - @destroy_component(old_component); + @transition_out(old_component.$$.fragment, 1, 0, () => { + @destroy_component(old_component, 1); }); @check_outros(); } diff --git a/src/runtime/internal/Component.ts b/src/runtime/internal/Component.ts index 9221a683b85..92e227e57cc 100644 --- a/src/runtime/internal/Component.ts +++ b/src/runtime/internal/Component.ts @@ -11,11 +11,11 @@ interface T$$ { bound: any; update: () => void; callbacks: any; - after_render: any[]; + after_update: any[]; props: any; fragment: null|any; not_equal: any; - before_render: any[]; + before_update: any[]; context: Map; on_mount: any[]; on_destroy: any[]; @@ -28,13 +28,11 @@ export function bind(component, name, callback) { } export function mount_component(component, target, anchor) { - const { fragment, on_mount, on_destroy, after_render } = component.$$; + const { fragment, on_mount, on_destroy, after_update } = component.$$; fragment.m(target, anchor); - // onMount happens after the initial afterUpdate. Because - // afterUpdate callbacks happen in reverse order (inner first) - // we schedule onMount callbacks before afterUpdate callbacks + // onMount happens before the initial afterUpdate add_render_callback(() => { const new_on_destroy = on_mount.map(run).filter(is_function); if (on_destroy) { @@ -47,7 +45,7 @@ export function mount_component(component, target, anchor) { component.$$.on_mount = []; }); - after_render.forEach(add_render_callback); + after_update.forEach(add_render_callback); } export function destroy_component(component, detaching) { @@ -91,8 +89,8 @@ export function init(component, options, instance, create_fragment, not_equal, p // lifecycle on_mount: [], on_destroy: [], - before_render: [], - after_render: [], + before_update: [], + after_update: [], context: new Map(parent_component ? parent_component.$$.context : []), // everything else @@ -113,7 +111,7 @@ export function init(component, options, instance, create_fragment, not_equal, p $$.update(); ready = true; - run_all($$.before_render); + run_all($$.before_update); $$.fragment = create_fragment($$.ctx); if (options.target) { diff --git a/src/runtime/internal/await_block.ts b/src/runtime/internal/await_block.ts index a8cce36c3f3..3834ff7c313 100644 --- a/src/runtime/internal/await_block.ts +++ b/src/runtime/internal/await_block.ts @@ -18,7 +18,7 @@ export function handle_promise(promise, info) { info.blocks.forEach((block, i) => { if (i !== index && block) { group_outros(); - transition_out(block, 1, () => { + transition_out(block, 1, 1, () => { info.blocks[i] = null; }); check_outros(); diff --git a/src/runtime/internal/keyed_each.ts b/src/runtime/internal/keyed_each.ts index e18ae617705..76708c93dbd 100644 --- a/src/runtime/internal/keyed_each.ts +++ b/src/runtime/internal/keyed_each.ts @@ -6,7 +6,7 @@ export function destroy_block(block, lookup) { } export function outro_and_destroy_block(block, lookup) { - transition_out(block, 1, () => { + transition_out(block, 1, 1, () => { lookup.delete(block.key); }); } diff --git a/src/runtime/internal/lifecycle.ts b/src/runtime/internal/lifecycle.ts index 1b9123eb14e..d659fd2e4a9 100644 --- a/src/runtime/internal/lifecycle.ts +++ b/src/runtime/internal/lifecycle.ts @@ -12,7 +12,7 @@ function get_current_component() { } export function beforeUpdate(fn) { - get_current_component().$$.before_render.push(fn); + get_current_component().$$.before_update.push(fn); } export function onMount(fn) { @@ -20,7 +20,7 @@ export function onMount(fn) { } export function afterUpdate(fn) { - get_current_component().$$.after_render.push(fn); + get_current_component().$$.after_update.push(fn); } export function onDestroy(fn) { diff --git a/src/runtime/internal/scheduler.ts b/src/runtime/internal/scheduler.ts index b5414d80e13..e3d7181fcbe 100644 --- a/src/runtime/internal/scheduler.ts +++ b/src/runtime/internal/scheduler.ts @@ -48,8 +48,9 @@ export function flush() { // then, once components are updated, call // afterUpdate functions. This may cause // subsequent updates... - while (render_callbacks.length) { - const callback = render_callbacks.pop(); + for (let i = 0; i < render_callbacks.length; i += 1) { + const callback = render_callbacks[i]; + if (!seen_callbacks.has(callback)) { callback(); @@ -57,6 +58,8 @@ export function flush() { seen_callbacks.add(callback); } } + + render_callbacks.length = 0; } while (dirty_components.length); while (flush_callbacks.length) { @@ -69,10 +72,10 @@ export function flush() { function update($$) { if ($$.fragment) { $$.update($$.dirty); - run_all($$.before_render); + run_all($$.before_update); $$.fragment.p($$.dirty, $$.ctx); $$.dirty = null; - $$.after_render.forEach(add_render_callback); + $$.after_update.forEach(add_render_callback); } } diff --git a/src/runtime/internal/ssr.ts b/src/runtime/internal/ssr.ts index 266e0d41493..09f9f07ab75 100644 --- a/src/runtime/internal/ssr.ts +++ b/src/runtime/internal/ssr.ts @@ -78,8 +78,8 @@ export function create_ssr_component(fn) { // these will be immediately discarded on_mount: [], - before_render: [], - after_render: [], + before_update: [], + after_update: [], callbacks: blank_object() }; diff --git a/src/runtime/internal/transitions.ts b/src/runtime/internal/transitions.ts index bbb24ba9ee6..91f243b4d6e 100644 --- a/src/runtime/internal/transitions.ts +++ b/src/runtime/internal/transitions.ts @@ -46,7 +46,7 @@ export function transition_in(block, local?: 0 | 1) { } } -export function transition_out(block, local: 0 | 1, callback) { +export function transition_out(block, local: 0 | 1, detach: 0 | 1, callback) { if (block && block.o) { if (outroing.has(block)) return; outroing.add(block); @@ -54,7 +54,7 @@ export function transition_out(block, local: 0 | 1, callback) { outros.callbacks.push(() => { outroing.delete(block); if (callback) { - block.d(1); + if (detach) block.d(1); callback(); } }); diff --git a/test/js/samples/transition-repeated-outro/expected.js b/test/js/samples/transition-repeated-outro/expected.js index 959bd472015..8543d0029b0 100644 --- a/test/js/samples/transition-repeated-outro/expected.js +++ b/test/js/samples/transition-repeated-outro/expected.js @@ -81,7 +81,7 @@ function create_fragment(ctx) { } } else if (if_block) { group_outros(); - transition_out(if_block, 1, () => { + transition_out(if_block, 1, 1, () => { if_block = null; }); check_outros(); diff --git a/test/runtime/samples/await-in-dynamic-component/Widget.svelte b/test/runtime/samples/await-in-dynamic-component/Widget.svelte new file mode 100644 index 00000000000..78118e944d2 --- /dev/null +++ b/test/runtime/samples/await-in-dynamic-component/Widget.svelte @@ -0,0 +1 @@ +{#await null}{/await} \ No newline at end of file diff --git a/test/runtime/samples/await-in-dynamic-component/_config.js b/test/runtime/samples/await-in-dynamic-component/_config.js new file mode 100644 index 00000000000..797298c5549 --- /dev/null +++ b/test/runtime/samples/await-in-dynamic-component/_config.js @@ -0,0 +1,5 @@ +export default { + test({ component }) { + component.flag = false; + } +}; \ No newline at end of file diff --git a/test/runtime/samples/await-in-dynamic-component/main.svelte b/test/runtime/samples/await-in-dynamic-component/main.svelte new file mode 100644 index 00000000000..c395cb44995 --- /dev/null +++ b/test/runtime/samples/await-in-dynamic-component/main.svelte @@ -0,0 +1,6 @@ + + + \ No newline at end of file diff --git a/test/runtime/samples/function-expression-inline/_config.js b/test/runtime/samples/function-expression-inline/_config.js new file mode 100644 index 00000000000..6916be45b1a --- /dev/null +++ b/test/runtime/samples/function-expression-inline/_config.js @@ -0,0 +1,22 @@ +export default { + html: ` + +

1

+

2

+

3

+ `, + + async test({ assert, target, window }) { + const button = target.querySelector('button'); + const click = new window.MouseEvent('click'); + + await button.dispatchEvent(click); + + assert.htmlEqual(target.innerHTML, ` + +

2

+

4

+

6

+ `); + } +}; \ No newline at end of file diff --git a/test/runtime/samples/function-expression-inline/main.svelte b/test/runtime/samples/function-expression-inline/main.svelte new file mode 100644 index 00000000000..f3f98459a78 --- /dev/null +++ b/test/runtime/samples/function-expression-inline/main.svelte @@ -0,0 +1,13 @@ + + + + +{#each list as number} +

{number}

+{/each} \ No newline at end of file diff --git a/test/runtime/samples/lifecycle-render-order-for-children/Item.svelte b/test/runtime/samples/lifecycle-render-order-for-children/Item.svelte new file mode 100755 index 00000000000..91411e1e73a --- /dev/null +++ b/test/runtime/samples/lifecycle-render-order-for-children/Item.svelte @@ -0,0 +1,29 @@ + + +
  • + {logRender()} +
  • diff --git a/test/runtime/samples/lifecycle-render-order-for-children/_config.js b/test/runtime/samples/lifecycle-render-order-for-children/_config.js new file mode 100644 index 00000000000..a1d35d7aa8d --- /dev/null +++ b/test/runtime/samples/lifecycle-render-order-for-children/_config.js @@ -0,0 +1,28 @@ +import order from './order.js'; + +export default { + skip_if_ssr: true, + + test({ assert, component, target }) { + assert.deepEqual(order, [ + '0: beforeUpdate', + '0: render', + '1: beforeUpdate', + '1: render', + '2: beforeUpdate', + '2: render', + '3: beforeUpdate', + '3: render', + '1: onMount', + '1: afterUpdate', + '2: onMount', + '2: afterUpdate', + '3: onMount', + '3: afterUpdate', + '0: onMount', + '0: afterUpdate' + ]); + + order.length = 0; + } +}; diff --git a/test/runtime/samples/lifecycle-render-order-for-children/main.svelte b/test/runtime/samples/lifecycle-render-order-for-children/main.svelte new file mode 100644 index 00000000000..fbb1c937e4d --- /dev/null +++ b/test/runtime/samples/lifecycle-render-order-for-children/main.svelte @@ -0,0 +1,33 @@ + + +{logRender()} + + + diff --git a/test/runtime/samples/lifecycle-render-order-for-children/order.js b/test/runtime/samples/lifecycle-render-order-for-children/order.js new file mode 100644 index 00000000000..109fa8b38ca --- /dev/null +++ b/test/runtime/samples/lifecycle-render-order-for-children/order.js @@ -0,0 +1 @@ +export default []; \ No newline at end of file diff --git a/test/runtime/samples/lifecycle-render-order/_config.js b/test/runtime/samples/lifecycle-render-order/_config.js index 44d7f61da62..5080973cefb 100644 --- a/test/runtime/samples/lifecycle-render-order/_config.js +++ b/test/runtime/samples/lifecycle-render-order/_config.js @@ -3,12 +3,12 @@ import order from './order.js'; export default { skip_if_ssr: true, - test({ assert, component, target }) { + test({ assert }) { assert.deepEqual(order, [ 'beforeUpdate', 'render', - 'afterUpdate', - 'onMount' + 'onMount', + 'afterUpdate' ]); order.length = 0; diff --git a/test/runtime/samples/shorthand-method-in-template/Foo.svelte b/test/runtime/samples/shorthand-method-in-template/Foo.svelte new file mode 100644 index 00000000000..bbe542622d4 --- /dev/null +++ b/test/runtime/samples/shorthand-method-in-template/Foo.svelte @@ -0,0 +1,5 @@ + + +{bar.answer()} \ No newline at end of file diff --git a/test/runtime/samples/shorthand-method-in-template/_config.js b/test/runtime/samples/shorthand-method-in-template/_config.js new file mode 100644 index 00000000000..ddd282644d3 --- /dev/null +++ b/test/runtime/samples/shorthand-method-in-template/_config.js @@ -0,0 +1,3 @@ +export default { + html: '42' +}; \ No newline at end of file diff --git a/test/runtime/samples/shorthand-method-in-template/main.svelte b/test/runtime/samples/shorthand-method-in-template/main.svelte new file mode 100644 index 00000000000..9ebd11aacb0 --- /dev/null +++ b/test/runtime/samples/shorthand-method-in-template/main.svelte @@ -0,0 +1,9 @@ + + + \ No newline at end of file