diff --git a/CHANGELOG.md b/CHANGELOG.md index f39308e5ff..e58b9b6e06 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ * In `vars` array, correctly indicate whether `module` variables are `mutated` or `reassigned` ([#3215](https://github.com/sveltejs/svelte/issues/3215)) * Fix spread props not updating in certain situations ([#3521](https://github.com/sveltejs/svelte/issues/3521), [#4480](https://github.com/sveltejs/svelte/issues/4480)) * Use the fallback content for slots if they are passed only whitespace ([#4092](https://github.com/sveltejs/svelte/issues/4092)) +* Fix bitmask overflow for `{#if}` blocks ([#4263](https://github.com/sveltejs/svelte/issues/4263)) * 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)) diff --git a/src/compiler/compile/render_dom/Renderer.ts b/src/compiler/compile/render_dom/Renderer.ts index fbb0c76d7d..2501279214 100644 --- a/src/compiler/compile/render_dom/Renderer.ts +++ b/src/compiler/compile/render_dom/Renderer.ts @@ -230,6 +230,7 @@ export default class Renderer { return bitmask; }; + // TODO: context-overflow make it less gross return { // Using a ParenthesizedExpression allows us to create // the expression lazily. TODO would be better if diff --git a/src/compiler/compile/render_dom/wrappers/IfBlock.ts b/src/compiler/compile/render_dom/wrappers/IfBlock.ts index dfc2228bc5..0506c943f9 100644 --- a/src/compiler/compile/render_dom/wrappers/IfBlock.ts +++ b/src/compiler/compile/render_dom/wrappers/IfBlock.ts @@ -288,7 +288,7 @@ export default class IfBlockWrapper extends Wrapper { } block.chunks.init.push(b` - let ${current_block_type} = ${select_block_type}(#ctx, -1); + let ${current_block_type} = ${select_block_type}(#ctx, ${this.get_initial_dirty_bit()}); let ${name} = ${get_block}; `); @@ -407,12 +407,12 @@ export default class IfBlockWrapper extends Wrapper { if (has_else) { block.chunks.init.push(b` - ${current_block_type_index} = ${select_block_type}(#ctx, -1); + ${current_block_type_index} = ${select_block_type}(#ctx, ${this.get_initial_dirty_bit()}); ${name} = ${if_blocks}[${current_block_type_index}] = ${if_block_creators}[${current_block_type_index}](#ctx); `); } else { block.chunks.init.push(b` - if (~(${current_block_type_index} = ${select_block_type}(#ctx, -1))) { + if (~(${current_block_type_index} = ${select_block_type}(#ctx, ${this.get_initial_dirty_bit()}))) { ${name} = ${if_blocks}[${current_block_type_index}] = ${if_block_creators}[${current_block_type_index}](#ctx); } `); @@ -587,4 +587,18 @@ export default class IfBlockWrapper extends Wrapper { `); } } + + get_initial_dirty_bit() { + const _this = this; + // TODO: context-overflow make it less gross + + const val = x`-1`; + return { + ...val, + elements: [val], + get type() { + return _this.renderer.context_overflow ? 'ArrayExpression' : 'UnaryExpression'; + }, + }; + } } diff --git a/src/compiler/compile/render_dom/wrappers/shared/get_slot_definition.ts b/src/compiler/compile/render_dom/wrappers/shared/get_slot_definition.ts index 9ab48dd035..0f28689df3 100644 --- a/src/compiler/compile/render_dom/wrappers/shared/get_slot_definition.ts +++ b/src/compiler/compile/render_dom/wrappers/shared/get_slot_definition.ts @@ -63,7 +63,7 @@ export function get_slot_definition(block: Block, scope: TemplateScope, lets: Le const { context_lookup } = block.renderer; // i am well aware that this code is gross - // TODO make it less gross + // TODO: context-overflow make it less gross const changes = { type: 'ParenthesizedExpression', get expression() { diff --git a/test/runtime/samples/bitmask-overflow-if/_config.js b/test/runtime/samples/bitmask-overflow-if/_config.js new file mode 100644 index 0000000000..74bc70d414 --- /dev/null +++ b/test/runtime/samples/bitmask-overflow-if/_config.js @@ -0,0 +1,24 @@ +export default { + html: ` + 012345678910111213141516171819202122232425262728293031323334353637383940 + expected: true + if: true + + `, + + async test({ assert, component, target, window }) { + const button = target.querySelector("button"); + await button.dispatchEvent(new window.MouseEvent("click")); + + assert.htmlEqual( + target.innerHTML, + ` + 112345678910111213141516171819202122232425262728293031323334353637383940 + expected: false + if: false +
+ + ` + ); + } +}; diff --git a/test/runtime/samples/bitmask-overflow-if/main.svelte b/test/runtime/samples/bitmask-overflow-if/main.svelte new file mode 100644 index 0000000000..2c1c453091 --- /dev/null +++ b/test/runtime/samples/bitmask-overflow-if/main.svelte @@ -0,0 +1,62 @@ + + + +{_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} + +expected: {_a.indexOf(_0) && _0 === '0' && _1 === '1'} +{#if _a.indexOf(_0) && _0 === '0' && _1 === '1'} +if: true +{:else} +if: false +
+{/if} + + \ No newline at end of file