From f244b80f7a80df54aa07f85c35720fa6ca880318 Mon Sep 17 00:00:00 2001 From: Conduitry Date: Fri, 28 Feb 2020 23:07:34 -0500 Subject: [PATCH 1/7] docs: referenced_from_script var value (#4486) --- site/content/docs/04-compile-time.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/site/content/docs/04-compile-time.md b/site/content/docs/04-compile-time.md index 0cb2ac3caf..f9bfa772fe 100644 --- a/site/content/docs/04-compile-time.md +++ b/site/content/docs/04-compile-time.md @@ -113,7 +113,8 @@ const { * `module` is `true` if the value is declared in a `context="module"` script * `mutated` is `true` if the value's properties are assigned to inside the component * `reassigned` is `true` if the value is reassigned inside the component - * `referenced` is `true` if the value is used outside the declaration + * `referenced` is `true` if the value is used in the template + * `referenced_from_script` is `true` if the value is used in the ` + \ No newline at end of file From 8feb85a61fe32ec164ea0358e5966338c5c69e1d Mon Sep 17 00:00:00 2001 From: Tan Li Hau Date: Sun, 1 Mar 2020 00:32:11 +0800 Subject: [PATCH 3/7] fix bitmask overflow for slot (#4485) --- CHANGELOG.md | 1 + src/runtime/internal/utils.ts | 6 ++- .../bitmask-overflow-slot-3/Echo.svelte | 9 ++++ .../bitmask-overflow-slot-3/_config.js | 30 ++++++++++++ .../bitmask-overflow-slot-3/main.svelte | 11 +++++ .../bitmask-overflow-slot-4/Echo.svelte | 11 +++++ .../bitmask-overflow-slot-4/_config.js | 41 ++++++++++++++++ .../bitmask-overflow-slot-4/main.svelte | 12 +++++ .../bitmask-overflow-slot-5/Echo.svelte | 13 +++++ .../bitmask-overflow-slot-5/_config.js | 49 +++++++++++++++++++ .../bitmask-overflow-slot-5/main.svelte | 13 +++++ 11 files changed, 195 insertions(+), 1 deletion(-) create mode 100644 test/runtime/samples/bitmask-overflow-slot-3/Echo.svelte create mode 100644 test/runtime/samples/bitmask-overflow-slot-3/_config.js create mode 100644 test/runtime/samples/bitmask-overflow-slot-3/main.svelte create mode 100644 test/runtime/samples/bitmask-overflow-slot-4/Echo.svelte create mode 100644 test/runtime/samples/bitmask-overflow-slot-4/_config.js create mode 100644 test/runtime/samples/bitmask-overflow-slot-4/main.svelte create mode 100644 test/runtime/samples/bitmask-overflow-slot-5/Echo.svelte create mode 100644 test/runtime/samples/bitmask-overflow-slot-5/_config.js create mode 100644 test/runtime/samples/bitmask-overflow-slot-5/main.svelte diff --git a/CHANGELOG.md b/CHANGELOG.md index 60553037e4..8197888f57 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ * In `vars` array, correctly indicate whether `module` variables are `mutated` or `reassigned` ([#3215](https://github.com/sveltejs/svelte/issues/3215)) * Exclude global variables from `$capture_state` ([#4463](https://github.com/sveltejs/svelte/issues/4463)) +* Fix bitmask overflow for slots ([#4481](https://github.com/sveltejs/svelte/issues/4481)) ## 3.19.1 diff --git a/src/runtime/internal/utils.ts b/src/runtime/internal/utils.ts index 4ba7e18c15..acb88c7669 100644 --- a/src/runtime/internal/utils.ts +++ b/src/runtime/internal/utils.ts @@ -83,7 +83,11 @@ export function get_slot_changes(definition, $$scope, dirty, fn) { if (definition[2] && fn) { const lets = definition[2](fn(dirty)); - if (typeof $$scope.dirty === 'object') { + if ($$scope.dirty === undefined) { + return lets; + } + + if (typeof lets === 'object') { const merged = []; const len = Math.max($$scope.dirty.length, lets.length); for (let i = 0; i < len; i += 1) { diff --git a/test/runtime/samples/bitmask-overflow-slot-3/Echo.svelte b/test/runtime/samples/bitmask-overflow-slot-3/Echo.svelte new file mode 100644 index 0000000000..d3ecf142c9 --- /dev/null +++ b/test/runtime/samples/bitmask-overflow-slot-3/Echo.svelte @@ -0,0 +1,9 @@ + + + + \ No newline at end of file diff --git a/test/runtime/samples/bitmask-overflow-slot-3/_config.js b/test/runtime/samples/bitmask-overflow-slot-3/_config.js new file mode 100644 index 0000000000..93e548e5f7 --- /dev/null +++ b/test/runtime/samples/bitmask-overflow-slot-3/_config.js @@ -0,0 +1,30 @@ +export default { + + html: ` +

_0_1_2_3_4_5_6_7_8_9_10_11_12_13_14_15_16_17_18_19_20_21_22_23_24_25_26_27_28_29_30_31_32_33_34_35_36_37_38_39_40

+

0

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

_0_1_2_3_4_5_6_7_8_9_10_11_12_13_14_15_16_17_18_19_20_21_22_23_24_25_26_27_28_29_30_31_32_33_34_35_36_37_38_39_40

+

1

+ + `); + + // change from outside + component._0 = 'a'; + component._40 = 'b'; + + assert.htmlEqual(target.innerHTML, ` +

a_1_2_3_4_5_6_7_8_9_10_11_12_13_14_15_16_17_18_19_20_21_22_23_24_25_26_27_28_29_30_31_32_33_34_35_36_37_38_39b

+

1

+ + `); + } +}; \ No newline at end of file diff --git a/test/runtime/samples/bitmask-overflow-slot-3/main.svelte b/test/runtime/samples/bitmask-overflow-slot-3/main.svelte new file mode 100644 index 0000000000..ae798e4aee --- /dev/null +++ b/test/runtime/samples/bitmask-overflow-slot-3/main.svelte @@ -0,0 +1,11 @@ + + + +

{_0}{_1}{_2}{_3}{_4}{_5}{_6}{_7}{_8}{_9}{_10}{_11}{_12}{_13}{_14}{_15}{_16}{_17}{_18}{_19}{_20}{_21}{_22}{_23}{_24}{_25}{_26}{_27}{_28}{_29}{_30}{_31}{_32}{_33}{_34}{_35}{_36}{_37}{_38}{_39}{_40}

+

{dummy}

+
+ diff --git a/test/runtime/samples/bitmask-overflow-slot-4/Echo.svelte b/test/runtime/samples/bitmask-overflow-slot-4/Echo.svelte new file mode 100644 index 0000000000..2e1beda492 --- /dev/null +++ b/test/runtime/samples/bitmask-overflow-slot-4/Echo.svelte @@ -0,0 +1,11 @@ + + +

{_0}{_1}{_2}{_3}{_4}{_5}{_6}{_7}{_8}{_9}{_10}{_11}{_12}{_13}{_14}{_15}{_16}{_17}{_18}{_19}{_20}{_21}{_22}{_23}{_24}{_25}{_26}{_27}{_28}{_29}{_30}{_31}{_32}{_33}{_34}{_35}{_36}{_37}{_38}{_39}{_40}

+ + \ No newline at end of file diff --git a/test/runtime/samples/bitmask-overflow-slot-4/_config.js b/test/runtime/samples/bitmask-overflow-slot-4/_config.js new file mode 100644 index 0000000000..cdaa5de77f --- /dev/null +++ b/test/runtime/samples/bitmask-overflow-slot-4/_config.js @@ -0,0 +1,41 @@ +export default { + html: ` +

_0_1_2_3_4_5_6_7_8_9_10_11_12_13_14_15_16_17_18_19_20_21_22_23_24_25_26_27_28_29_30_31_32_33_34_35_36_37_38_39_40

+

0

+

0

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

_0_1_2_3_4_5_6_7_8_9_10_11_12_13_14_15_16_17_18_19_20_21_22_23_24_25_26_27_28_29_30_31_32_33_34_35_36_37_38_39_40

+

0

+

1

+ + `); + + // change from outside + component._0 = 'a'; + + assert.htmlEqual(target.innerHTML, ` +

_0_1_2_3_4_5_6_7_8_9_10_11_12_13_14_15_16_17_18_19_20_21_22_23_24_25_26_27_28_29_30_31_32_33_34_35_36_37_38_39_40

+

a

+

1

+ + `); + + // change from outside through props + component._40 = 'b'; + + assert.htmlEqual(target.innerHTML, ` +

_0_1_2_3_4_5_6_7_8_9_10_11_12_13_14_15_16_17_18_19_20_21_22_23_24_25_26_27_28_29_30_31_32_33_34_35_36_37_38_39b

+

a

+

1

+ + `); + } +}; \ No newline at end of file diff --git a/test/runtime/samples/bitmask-overflow-slot-4/main.svelte b/test/runtime/samples/bitmask-overflow-slot-4/main.svelte new file mode 100644 index 0000000000..7e02487a30 --- /dev/null +++ b/test/runtime/samples/bitmask-overflow-slot-4/main.svelte @@ -0,0 +1,12 @@ + + + +

{_0}

+

{dummy}

+
+ diff --git a/test/runtime/samples/bitmask-overflow-slot-5/Echo.svelte b/test/runtime/samples/bitmask-overflow-slot-5/Echo.svelte new file mode 100644 index 0000000000..dddb3f7642 --- /dev/null +++ b/test/runtime/samples/bitmask-overflow-slot-5/Echo.svelte @@ -0,0 +1,13 @@ + + +

{_0}{_1}{_2}{_3}{_4}{_5}{_6}{_7}{_8}{_9}{_10}{_11}{_12}{_13}{_14}{_15}{_16}{_17}{_18}{_19}{_20}{_21}{_22}{_23}{_24}{_25}{_26}{_27}{_28}{_29}{_30}{_31}{_32}{_33}{_34}{_35}{_36}{_37}{_38}{_39}{_40}

+

{b}

+ + \ No newline at end of file diff --git a/test/runtime/samples/bitmask-overflow-slot-5/_config.js b/test/runtime/samples/bitmask-overflow-slot-5/_config.js new file mode 100644 index 0000000000..7dedb8f7eb --- /dev/null +++ b/test/runtime/samples/bitmask-overflow-slot-5/_config.js @@ -0,0 +1,49 @@ +export default { + html: ` +

_0_1_2_3_4_5_6_7_8_9_10_11_12_13_14_15_16_17_18_19_20_21_22_23_24_25_26_27_28_29_30_31_32_33_34_35_36_37_38_39_40

+

b

+

-0-1-2-3-4-5-6-7-8-9-10-11-12-13-14-15-16-17-18-19-20-21-22-23-24-25-26-27-28-29-30-31-32-33-34-35-36-37-38-39-40

+

0

+

0

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

_0_1_2_3_4_5_6_7_8_9_10_11_12_13_14_15_16_17_18_19_20_21_22_23_24_25_26_27_28_29_30_31_32_33_34_35_36_37_38_39_40

+

b

+

-0-1-2-3-4-5-6-7-8-9-10-11-12-13-14-15-16-17-18-19-20-21-22-23-24-25-26-27-28-29-30-31-32-33-34-35-36-37-38-39-40

+

0

+

1

+ + `); + + // change from outside + component.a = 'AA'; + + assert.htmlEqual(target.innerHTML, ` +

_0_1_2_3_4_5_6_7_8_9_10_11_12_13_14_15_16_17_18_19_20_21_22_23_24_25_26_27_28_29_30_31_32_33_34_35_36_37_38_39_40

+

b

+

-0-1-2-3-4-5-6-7-8-9-10-11-12-13-14-15-16-17-18-19-20-21-22-23-24-25-26-27-28-29-30-31-32-33-34-35-36-37-38-39-40

+

AA

+

1

+ + `); + + // change from outside through props + component.b = 'BB'; + + assert.htmlEqual(target.innerHTML, ` +

_0_1_2_3_4_5_6_7_8_9_10_11_12_13_14_15_16_17_18_19_20_21_22_23_24_25_26_27_28_29_30_31_32_33_34_35_36_37_38_39_40

+

BB

+

-0-1-2-3-4-5-6-7-8-9-10-11-12-13-14-15-16-17-18-19-20-21-22-23-24-25-26-27-28-29-30-31-32-33-34-35-36-37-38-39-40

+

AA

+

1

+ + `); + } +}; \ No newline at end of file diff --git a/test/runtime/samples/bitmask-overflow-slot-5/main.svelte b/test/runtime/samples/bitmask-overflow-slot-5/main.svelte new file mode 100644 index 0000000000..b17d6f7bae --- /dev/null +++ b/test/runtime/samples/bitmask-overflow-slot-5/main.svelte @@ -0,0 +1,13 @@ + + + +

{_0}{_1}{_2}{_3}{_4}{_5}{_6}{_7}{_8}{_9}{_10}{_11}{_12}{_13}{_14}{_15}{_16}{_17}{_18}{_19}{_20}{_21}{_22}{_23}{_24}{_25}{_26}{_27}{_28}{_29}{_30}{_31}{_32}{_33}{_34}{_35}{_36}{_37}{_38}{_39}{_40}

+

{a}

+

{dummy}

+
+ From 37a2d6c6eada0c4e893fb90f3d8faa6eb3036f6f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 29 Feb 2020 11:34:18 -0500 Subject: [PATCH 4/7] Bump codecov from 3.5.0 to 3.6.5 (#4433) Bumps [codecov](https://github.com/codecov/codecov-node) from 3.5.0 to 3.6.5. - [Release notes](https://github.com/codecov/codecov-node/releases) - [Commits](https://github.com/codecov/codecov-node/commits) Signed-off-by: dependabot[bot] --- package-lock.json | 111 +++++++++++++++++++++++++++++++++++++++------- 1 file changed, 96 insertions(+), 15 deletions(-) diff --git a/package-lock.json b/package-lock.json index 3b275078ec..f0f4e17422 100644 --- a/package-lock.json +++ b/package-lock.json @@ -137,6 +137,12 @@ } } }, + "@tootallnate/once": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.0.0.tgz", + "integrity": "sha512-KYyTT/T6ALPkIRd2Ge080X/BsXvy9O0hcWTtMWkPvwAwF99+vn6Dv4GzrFT/Nn1LePr+FFDbRXXlqmsy9lw2zA==", + "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", @@ -609,16 +615,16 @@ } }, "codecov": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/codecov/-/codecov-3.5.0.tgz", - "integrity": "sha512-/OsWOfIHaQIr7aeZ4pY0UC1PZT6kimoKFOFYFNb6wxo3iw12nRrh+mNGH72rnXxNsq6SGfesVPizm/6Q3XqcFQ==", + "version": "3.6.5", + "resolved": "https://registry.npmjs.org/codecov/-/codecov-3.6.5.tgz", + "integrity": "sha512-v48WuDMUug6JXwmmfsMzhCHRnhUf8O3duqXvltaYJKrO1OekZWpB/eH6iIoaxMl8Qli0+u3OxptdsBOYiD7VAQ==", "dev": true, "requires": { - "argv": "^0.0.2", - "ignore-walk": "^3.0.1", - "js-yaml": "^3.13.1", - "teeny-request": "^3.11.3", - "urlgrey": "^0.4.4" + "argv": "0.0.2", + "ignore-walk": "3.0.3", + "js-yaml": "3.13.1", + "teeny-request": "6.0.1", + "urlgrey": "0.4.4" } }, "color-convert": { @@ -1670,6 +1676,37 @@ "whatwg-encoding": "^1.0.1" } }, + "http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "dev": true, + "requires": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + }, + "dependencies": { + "agent-base": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.0.tgz", + "integrity": "sha512-j1Q7cSCqN+AwrmDd+pzgqc0/NpC655x2bUf5ZjRIO77DcNBFmh+OgRNzF6OKdCC9RSCb19fGd99+bhXFdkRNqw==", + "dev": true, + "requires": { + "debug": "4" + } + }, + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + } + } + }, "http-signature": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", @@ -1707,9 +1744,9 @@ "dev": true }, "ignore-walk": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.1.tgz", - "integrity": "sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.3.tgz", + "integrity": "sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw==", "dev": true, "requires": { "minimatch": "^3.0.4" @@ -3362,6 +3399,15 @@ "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=", "dev": true }, + "stream-events": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/stream-events/-/stream-events-1.0.5.tgz", + "integrity": "sha512-E1GUzBSgvct8Jsb3v2X15pjzN1tYebtbLaMg+eBOUOAxgbLoSbT2NS91ckc5lJD1KfLjId+jXJRgo0qnV5Nerg==", + "dev": true, + "requires": { + "stubs": "^3.0.0" + } + }, "string-width": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", @@ -3409,6 +3455,12 @@ "integrity": "sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw==", "dev": true }, + "stubs": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/stubs/-/stubs-3.0.0.tgz", + "integrity": "sha1-6NK6H6nJBXAwPAMLaQD31fiavls=", + "dev": true + }, "sucrase": { "version": "3.10.1", "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.10.1.tgz", @@ -3449,14 +3501,43 @@ } }, "teeny-request": { - "version": "3.11.3", - "resolved": "https://registry.npmjs.org/teeny-request/-/teeny-request-3.11.3.tgz", - "integrity": "sha512-CKncqSF7sH6p4rzCgkb/z/Pcos5efl0DmolzvlqRQUNcpRIruOhY9+T1FsIlyEbfWd7MsFpodROOwHYh2BaXzw==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/teeny-request/-/teeny-request-6.0.1.tgz", + "integrity": "sha512-TAK0c9a00ELOqLrZ49cFxvPVogMUFaWY8dUsQc/0CuQPGF+BOxOQzXfE413BAk2kLomwNplvdtMpeaeGWmoc2g==", "dev": true, "requires": { - "https-proxy-agent": "^2.2.1", + "http-proxy-agent": "^4.0.0", + "https-proxy-agent": "^4.0.0", "node-fetch": "^2.2.0", + "stream-events": "^1.0.5", "uuid": "^3.3.2" + }, + "dependencies": { + "agent-base": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-5.1.1.tgz", + "integrity": "sha512-TMeqbNl2fMW0nMjTEPOwe3J/PRFP4vqeoNuQMG0HlMrtm5QxKqdvAkZ1pRBQ/ulIyDD5Yq0nJ7YbdD8ey0TO3g==", + "dev": true + }, + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "https-proxy-agent": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-4.0.0.tgz", + "integrity": "sha512-zoDhWrkR3of1l9QAL8/scJZyLu8j/gBkcwcaQOZh7Gyh/+uJQzGVETdgT30akuwkpL8HTRfssqI3BZuV18teDg==", + "dev": true, + "requires": { + "agent-base": "5", + "debug": "4" + } + } } }, "test-exclude": { From b6aaa44880892a64712f629bff40f1433d92dfdb Mon Sep 17 00:00:00 2001 From: pushkin Date: Sat, 29 Feb 2020 18:43:53 +0100 Subject: [PATCH 5/7] check for unknown props even if component doesn't have writable props (#4454) --- src/compiler/compile/render_dom/index.ts | 6 +++++- test/js/samples/debug-hoisted/expected.js | 6 ++++++ test/js/samples/debug-no-dependencies/expected.js | 12 +++++++++++- test/js/samples/loop-protect/expected.js | 8 ++++++++ .../samples/dev-warning-unknown-props-2/Foo.svelte | 1 + .../samples/dev-warning-unknown-props-2/_config.js | 9 +++++++++ .../samples/dev-warning-unknown-props-2/main.svelte | 5 +++++ 7 files changed, 45 insertions(+), 2 deletions(-) create mode 100644 test/runtime/samples/dev-warning-unknown-props-2/Foo.svelte create mode 100644 test/runtime/samples/dev-warning-unknown-props-2/_config.js create mode 100644 test/runtime/samples/dev-warning-unknown-props-2/main.svelte diff --git a/src/compiler/compile/render_dom/index.ts b/src/compiler/compile/render_dom/index.ts index 71e8681646..3d1870ccaa 100644 --- a/src/compiler/compile/render_dom/index.ts +++ b/src/compiler/compile/render_dom/index.ts @@ -259,6 +259,9 @@ export default function dom( inject_state; if (has_invalidate) { args.push(x`$$props`, x`$$invalidate`); + } else if (component.compile_options.dev) { + // $$props arg is still needed for unknown prop check + args.push(x`$$props`); } const has_create_fragment = block.has_content(); @@ -300,6 +303,7 @@ export default function dom( const initial_context = renderer.context.slice(0, i + 1); const has_definition = ( + component.compile_options.dev || (instance_javascript && instance_javascript.length > 0) || filtered_props.length > 0 || uses_props || @@ -379,7 +383,7 @@ export default function dom( }); let unknown_props_check; - if (component.compile_options.dev && !component.var_lookup.has('$$props') && writable_props.length) { + if (component.compile_options.dev && !component.var_lookup.has('$$props')) { unknown_props_check = b` const writable_props = [${writable_props.map(prop => x`'${prop.export_name}'`)}]; @_Object.keys($$props).forEach(key => { diff --git a/test/js/samples/debug-hoisted/expected.js b/test/js/samples/debug-hoisted/expected.js index c77168ef4f..190ff12c50 100644 --- a/test/js/samples/debug-hoisted/expected.js +++ b/test/js/samples/debug-hoisted/expected.js @@ -50,6 +50,12 @@ function create_fragment(ctx) { function instance($$self, $$props, $$invalidate) { let obj = { x: 5 }; let kobzol = 5; + const writable_props = []; + + Object.keys($$props).forEach(key => { + if (!~writable_props.indexOf(key) && key.slice(0, 2) !== "$$") console.warn(` was created with unknown prop '${key}'`); + }); + $$self.$capture_state = () => ({ obj, kobzol }); $$self.$inject_state = $$props => { diff --git a/test/js/samples/debug-no-dependencies/expected.js b/test/js/samples/debug-no-dependencies/expected.js index 9985c814a2..a097869e74 100644 --- a/test/js/samples/debug-no-dependencies/expected.js +++ b/test/js/samples/debug-no-dependencies/expected.js @@ -134,10 +134,20 @@ function create_fragment(ctx) { return block; } +function instance($$self, $$props) { + const writable_props = []; + + Object.keys($$props).forEach(key => { + if (!~writable_props.indexOf(key) && key.slice(0, 2) !== "$$") console.warn(` was created with unknown prop '${key}'`); + }); + + return []; +} + class Component extends SvelteComponentDev { constructor(options) { super(options); - init(this, options, null, create_fragment, safe_not_equal, {}); + init(this, options, instance, create_fragment, safe_not_equal, {}); dispatch_dev("SvelteRegisterComponent", { component: this, diff --git a/test/js/samples/loop-protect/expected.js b/test/js/samples/loop-protect/expected.js index 4eccaae7cb..f433bd61a9 100644 --- a/test/js/samples/loop-protect/expected.js +++ b/test/js/samples/loop-protect/expected.js @@ -6,6 +6,7 @@ import { detach_dev, dispatch_dev, element, + globals, init, insert_dev, loop_guard, @@ -13,6 +14,7 @@ import { safe_not_equal } from "svelte/internal"; +const { console: console_1 } = globals; const file = undefined; function create_fragment(ctx) { @@ -102,6 +104,12 @@ function instance($$self, $$props, $$invalidate) { } while (true); } + const writable_props = []; + + Object.keys($$props).forEach(key => { + if (!~writable_props.indexOf(key) && key.slice(0, 2) !== "$$") console_1.warn(` was created with unknown prop '${key}'`); + }); + function div_binding($$value) { binding_callbacks[$$value ? "unshift" : "push"](() => { $$invalidate(0, node = $$value); diff --git a/test/runtime/samples/dev-warning-unknown-props-2/Foo.svelte b/test/runtime/samples/dev-warning-unknown-props-2/Foo.svelte new file mode 100644 index 0000000000..bc56c4d894 --- /dev/null +++ b/test/runtime/samples/dev-warning-unknown-props-2/Foo.svelte @@ -0,0 +1 @@ +Foo diff --git a/test/runtime/samples/dev-warning-unknown-props-2/_config.js b/test/runtime/samples/dev-warning-unknown-props-2/_config.js new file mode 100644 index 0000000000..9bff4a2a74 --- /dev/null +++ b/test/runtime/samples/dev-warning-unknown-props-2/_config.js @@ -0,0 +1,9 @@ +export default { + compileOptions: { + dev: true + }, + + warnings: [ + ` was created with unknown prop 'fo'` + ] +}; diff --git a/test/runtime/samples/dev-warning-unknown-props-2/main.svelte b/test/runtime/samples/dev-warning-unknown-props-2/main.svelte new file mode 100644 index 0000000000..1566cf3e41 --- /dev/null +++ b/test/runtime/samples/dev-warning-unknown-props-2/main.svelte @@ -0,0 +1,5 @@ + + + From 3f647a84f6c295334ac8309caa9724a3fa137ace Mon Sep 17 00:00:00 2001 From: Conduitry Date: Sat, 29 Feb 2020 12:44:54 -0500 Subject: [PATCH 6/7] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8197888f57..3dd0aadf8b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## Unreleased * In `vars` array, correctly indicate whether `module` variables are `mutated` or `reassigned` ([#3215](https://github.com/sveltejs/svelte/issues/3215)) +* In `dev` mode, check for unknown props even if the component has no writable props ([#4323](https://github.com/sveltejs/svelte/issues/4323)) * Exclude global variables from `$capture_state` ([#4463](https://github.com/sveltejs/svelte/issues/4463)) * Fix bitmask overflow for slots ([#4481](https://github.com/sveltejs/svelte/issues/4481)) From 3a37de364bfbe75202d8e9fcef9e76b9ce6faaa2 Mon Sep 17 00:00:00 2001 From: Brian Takita Date: Sat, 29 Feb 2020 12:50:54 -0500 Subject: [PATCH 7/7] chore: more specific typings, and add README note about Yarn (#4483) --- README.md | 2 ++ src/compiler/compile/Component.ts | 26 +++++++++---------- src/compiler/compile/nodes/Let.ts | 12 ++++----- .../compile/nodes/shared/Expression.ts | 4 +-- src/compiler/compile/render_dom/index.ts | 4 +-- 5 files changed, 25 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 3a43725637..fa725804a9 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,8 @@ cd svelte npm install ``` +> Do not use Yarn to install the dependencies, as the specific package versions in `package-lock.json` are used to build and test Svelte. + > Many tests depend on newlines being preserved as ``. On Windows, you can ensure this by cloning with: > ```bash > git -c core.autocrlf=false clone https://github.com/sveltejs/svelte.git diff --git a/src/compiler/compile/Component.ts b/src/compiler/compile/Component.ts index 2569820464..a7fe2992d1 100644 --- a/src/compiler/compile/Component.ts +++ b/src/compiler/compile/Component.ts @@ -239,7 +239,7 @@ export default class Component { const program: any = { type: 'Program', body: result.js }; walk(program, { - enter: (node, parent, key) => { + enter: (node: Node, parent: Node, key) => { if (node.type === 'Identifier') { if (node.name[0] === '@') { if (node.name[1] === '_') { @@ -526,7 +526,7 @@ export default class Component { if (!script) return; walk(script.content, { - enter(node) { + enter(node: Node) { if (node.type === 'LabeledStatement' && node.label.name === '$') { component.warn(node as any, { code: 'module-script-reactive-declaration', @@ -715,7 +715,7 @@ export default class Component { let scope_updated = false; walk(content, { - enter(node, parent, prop, index) { + enter(node: Node, parent, prop, index) { if (map.has(node)) { scope = map.get(node); } @@ -741,7 +741,7 @@ export default class Component { component.warn_on_undefined_store_value_references(node, parent, scope); }, - leave(node) { + leave(node: Node) { // do it on leave, to prevent infinite loop if (component.compile_options.dev && component.compile_options.loopGuardTimeout > 0) { const to_replace_for_loop_protect = component.loop_protect(node, scope, component.compile_options.loopGuardTimeout); @@ -785,7 +785,7 @@ export default class Component { let scope = instance_scope; walk(content, { - enter(node, parent) { + enter(node: Node, parent: Node) { if (map.has(node)) { scope = map.get(node); } @@ -818,7 +818,7 @@ export default class Component { } }, - leave(node) { + leave(node: Node) { if (map.has(node)) { scope = scope.parent; } @@ -886,7 +886,7 @@ export default class Component { let scope = instance_scope; walk(this.ast.instance.content, { - enter(node, parent, key, index) { + enter(node: Node, parent, key, index) { if (/Function/.test(node.type)) { return this.skip(); } @@ -963,7 +963,7 @@ export default class Component { } }, - leave(node, parent, _key, index) { + leave(node: Node, parent, _key, index) { if (map.has(node)) { scope = scope.parent; } @@ -1064,7 +1064,7 @@ export default class Component { walking.add(fn_declaration); walk(fn_declaration, { - enter(node, parent) { + enter(node: Node, parent) { if (!hoistable) return this.skip(); if (map.has(node)) { @@ -1112,7 +1112,7 @@ export default class Component { } }, - leave(node) { + leave(node: Node) { if (map.has(node)) { scope = scope.parent; } @@ -1155,7 +1155,7 @@ export default class Component { const map = this.instance_scope_map; walk(node.body, { - enter(node, parent) { + enter(node: Node, parent) { if (map.has(node)) { scope = map.get(node); } @@ -1195,7 +1195,7 @@ export default class Component { } }, - leave(node) { + leave(node: Node) { if (map.has(node)) { scope = scope.parent; } @@ -1455,4 +1455,4 @@ function get_relative_path(from: string, to: string) { } return from_parts.concat(to_parts).join('/'); -} \ No newline at end of file +} diff --git a/src/compiler/compile/nodes/Let.ts b/src/compiler/compile/nodes/Let.ts index 7b92c5ce70..ef38cd36a8 100644 --- a/src/compiler/compile/nodes/Let.ts +++ b/src/compiler/compile/nodes/Let.ts @@ -1,7 +1,7 @@ import Node from './shared/Node'; import Component from '../Component'; import { walk } from 'estree-walker'; -import { Identifier } from 'estree'; +import { BasePattern, Identifier } from 'estree'; const applicable = new Set(['Identifier', 'ObjectExpression', 'ArrayExpression', 'Property']); @@ -22,7 +22,7 @@ export default class Let extends Node { this.value = info.expression; walk(info.expression, { - enter(node) { + enter(node: Identifier|BasePattern) { if (!applicable.has(node.type)) { component.error(node as any, { code: 'invalid-let', @@ -31,16 +31,16 @@ export default class Let extends Node { } if (node.type === 'Identifier') { - names.push(node.name); + names.push((node as Identifier).name); } // slightly unfortunate hack if (node.type === 'ArrayExpression') { - (node as any).type = 'ArrayPattern'; + node.type = 'ArrayPattern'; } if (node.type === 'ObjectExpression') { - (node as any).type = 'ObjectPattern'; + node.type = 'ObjectPattern'; } } }); @@ -48,4 +48,4 @@ export default class Let extends Node { names.push(this.name.name); } } -} \ No newline at end of file +} diff --git a/src/compiler/compile/nodes/shared/Expression.ts b/src/compiler/compile/nodes/shared/Expression.ts index 1882c19267..db0908c3f4 100644 --- a/src/compiler/compile/nodes/shared/Expression.ts +++ b/src/compiler/compile/nodes/shared/Expression.ts @@ -143,7 +143,7 @@ export default class Expression { } }, - leave(node) { + leave(node: Node) { if (map.has(node)) { scope = scope.parent; } @@ -338,7 +338,7 @@ export default class Expression { }); } - return (this.manipulated = node); + return (this.manipulated = node as Node); } } diff --git a/src/compiler/compile/render_dom/index.ts b/src/compiler/compile/render_dom/index.ts index 3d1870ccaa..d6da614276 100644 --- a/src/compiler/compile/render_dom/index.ts +++ b/src/compiler/compile/render_dom/index.ts @@ -200,7 +200,7 @@ export default function dom( let execution_context: Node | null = null; walk(component.ast.instance.content, { - enter(node) { + enter(node: Node) { if (map.has(node)) { scope = map.get(node) as Scope; @@ -212,7 +212,7 @@ export default function dom( } }, - leave(node) { + leave(node: Node) { if (map.has(node)) { scope = scope.parent; }