From c9304554d3893459e2dee382861394edcfbb4528 Mon Sep 17 00:00:00 2001 From: suxin2017 <1107178482@qq.com> Date: Fri, 29 Jan 2021 14:24:58 +0800 Subject: [PATCH 01/14] fix: same-text-no-update --- src/compiler/compile/render_dom/index.ts | 1 - src/runtime/internal/dev.ts | 2 +- src/runtime/internal/dom.ts | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/compiler/compile/render_dom/index.ts b/src/compiler/compile/render_dom/index.ts index 3b1f873ba501..99e5f112abcc 100644 --- a/src/compiler/compile/render_dom/index.ts +++ b/src/compiler/compile/render_dom/index.ts @@ -549,7 +549,6 @@ export default function dom( body.push(declaration); } - return { js: flatten(body, []), css }; } diff --git a/src/runtime/internal/dev.ts b/src/runtime/internal/dev.ts index 53f6ef3bf1ba..cd61ec98d62d 100644 --- a/src/runtime/internal/dev.ts +++ b/src/runtime/internal/dev.ts @@ -73,7 +73,7 @@ export function dataset_dev(node: HTMLElement, property: string, value?: any) { export function set_data_dev(text, data) { data = '' + data; - if (text.wholeText === data) return; + if (text === data) return; dispatch_dev('SvelteDOMSetData', { node: text, data }); text.data = data; diff --git a/src/runtime/internal/dom.ts b/src/runtime/internal/dom.ts index 8d99234c9de2..663cc27ca062 100644 --- a/src/runtime/internal/dom.ts +++ b/src/runtime/internal/dom.ts @@ -193,7 +193,7 @@ export function claim_space(nodes) { export function set_data(text, data) { data = '' + data; - if (text.wholeText !== data) text.data = data; + if (text !== data) text.data = data; } export function set_input_value(input, value) { From fbf0ed926b82104ef680a7c17808d503af9c20d6 Mon Sep 17 00:00:00 2001 From: suxin2017 <1107178482@qq.com> Date: Fri, 29 Jan 2021 20:56:22 +0800 Subject: [PATCH 02/14] fix: same-text-no-update --- src/runtime/internal/dev.ts | 9 +++++++-- src/runtime/internal/dom.ts | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/runtime/internal/dev.ts b/src/runtime/internal/dev.ts index cd61ec98d62d..bc7f39a8d603 100644 --- a/src/runtime/internal/dev.ts +++ b/src/runtime/internal/dev.ts @@ -73,8 +73,13 @@ export function dataset_dev(node: HTMLElement, property: string, value?: any) { export function set_data_dev(text, data) { data = '' + data; - if (text === data) return; - + // In particular, when the property is contentEditable, ' 'TEXT_NODE is inserted into the text + if (text.textContent === '' && text.wholeText !== '') { + if (text.wholeText === data) return; + } else { + if (text.textContent === data) return; + } + dispatch_dev('SvelteDOMSetData', { node: text, data }); text.data = data; } diff --git a/src/runtime/internal/dom.ts b/src/runtime/internal/dom.ts index 663cc27ca062..8d99234c9de2 100644 --- a/src/runtime/internal/dom.ts +++ b/src/runtime/internal/dom.ts @@ -193,7 +193,7 @@ export function claim_space(nodes) { export function set_data(text, data) { data = '' + data; - if (text !== data) text.data = data; + if (text.wholeText !== data) text.data = data; } export function set_input_value(input, value) { From 6bbacfbd15c65d8a63c92a2fecb431d8e9269f1e Mon Sep 17 00:00:00 2001 From: suxin2017 <1107178482@qq.com> Date: Fri, 29 Jan 2021 20:57:17 +0800 Subject: [PATCH 03/14] chore: a problem --- src/runtime/internal/dom.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/runtime/internal/dom.ts b/src/runtime/internal/dom.ts index 8d99234c9de2..234eca90a48b 100644 --- a/src/runtime/internal/dom.ts +++ b/src/runtime/internal/dom.ts @@ -193,6 +193,7 @@ export function claim_space(nodes) { export function set_data(text, data) { data = '' + data; + // ??? I'm not sure if I need to change this if (text.wholeText !== data) text.data = data; } From c257ff124296e2ce14fd2e626c58743ad0a216f6 Mon Sep 17 00:00:00 2001 From: suxin2017 <1107178482@qq.com> Date: Fri, 29 Jan 2021 20:59:50 +0800 Subject: [PATCH 04/14] fix: empty fix --- src/compiler/compile/render_dom/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/compiler/compile/render_dom/index.ts b/src/compiler/compile/render_dom/index.ts index 99e5f112abcc..c19a5c3cdd08 100644 --- a/src/compiler/compile/render_dom/index.ts +++ b/src/compiler/compile/render_dom/index.ts @@ -549,6 +549,7 @@ export default function dom( body.push(declaration); } + return { js: flatten(body, []), css }; } From 3caa3a7f295c850a027757491080eb14451bfe93 Mon Sep 17 00:00:00 2001 From: suxin2017 <1107178482@qq.com> Date: Sat, 30 Jan 2021 09:00:05 +0800 Subject: [PATCH 05/14] feat: add reactive-values-text-node test case --- src/runtime/internal/dom.ts | 9 +++++++-- .../runtime/samples/reactive-values-text-node/_config.js | 9 +++++++++ .../samples/reactive-values-text-node/main.svelte | 8 ++++++++ 3 files changed, 24 insertions(+), 2 deletions(-) create mode 100644 test/runtime/samples/reactive-values-text-node/_config.js create mode 100644 test/runtime/samples/reactive-values-text-node/main.svelte diff --git a/src/runtime/internal/dom.ts b/src/runtime/internal/dom.ts index 234eca90a48b..1ac39aff5152 100644 --- a/src/runtime/internal/dom.ts +++ b/src/runtime/internal/dom.ts @@ -193,8 +193,13 @@ export function claim_space(nodes) { export function set_data(text, data) { data = '' + data; - // ??? I'm not sure if I need to change this - if (text.wholeText !== data) text.data = data; + // In particular, when the property is contentEditable, ' 'TEXT_NODE is inserted into the text + if (text.textContent === '' && text.wholeText !== '') { + if (text.wholeText === data) return; + } else { + if (text.textContent === data) return; + } + text.data = data; } export function set_input_value(input, value) { diff --git a/test/runtime/samples/reactive-values-text-node/_config.js b/test/runtime/samples/reactive-values-text-node/_config.js new file mode 100644 index 000000000000..9e0cb2d5d306 --- /dev/null +++ b/test/runtime/samples/reactive-values-text-node/_config.js @@ -0,0 +1,9 @@ +export default { + html:'
same text
', + async test({ assert, component, target }) { + await new Promise(f => setTimeout(f, 10)); + assert.htmlEqual(target.innerHTML, ` +
same text text
+ `); + } +}; diff --git a/test/runtime/samples/reactive-values-text-node/main.svelte b/test/runtime/samples/reactive-values-text-node/main.svelte new file mode 100644 index 000000000000..1ca11d19f443 --- /dev/null +++ b/test/runtime/samples/reactive-values-text-node/main.svelte @@ -0,0 +1,8 @@ + + +
{text} text
\ No newline at end of file From a128e3c56fe512ad4f8e28f1bd9c7bfe27bd1597 Mon Sep 17 00:00:00 2001 From: baseballyama Date: Sat, 18 Mar 2023 16:57:53 +0900 Subject: [PATCH 06/14] fix 5931 --- .../render_dom/wrappers/Element/index.ts | 37 ++++++++++--------- .../render_dom/wrappers/MustacheTag.ts | 30 +++++++++++++-- .../render_dom/wrappers/shared/Wrapper.ts | 2 +- src/runtime/internal/dev.ts | 10 ++--- src/runtime/internal/dom.ts | 9 ++--- src/runtime/internal/utils.ts | 2 + .../_config.js | 5 +-- .../_config.js | 12 ++++++ .../main.svelte | 6 +++ .../_config.js | 13 +++++++ .../main.svelte | 9 +++++ .../_config.js | 12 ++++++ .../main.svelte | 6 +++ .../reactive-values-text-node/_config.js | 2 +- .../reactive-values-text-node/main.svelte | 8 ++-- 15 files changed, 122 insertions(+), 41 deletions(-) create mode 100644 test/runtime/samples/component-event-handler-contenteditable2/_config.js create mode 100644 test/runtime/samples/component-event-handler-contenteditable2/main.svelte create mode 100644 test/runtime/samples/component-event-handler-contenteditable3/_config.js create mode 100644 test/runtime/samples/component-event-handler-contenteditable3/main.svelte create mode 100644 test/runtime/samples/component-event-handler-contenteditable4/_config.js create mode 100644 test/runtime/samples/component-event-handler-contenteditable4/main.svelte diff --git a/src/compiler/compile/render_dom/wrappers/Element/index.ts b/src/compiler/compile/render_dom/wrappers/Element/index.ts index 1f80cee89cf0..b57d24ae9c5e 100644 --- a/src/compiler/compile/render_dom/wrappers/Element/index.ts +++ b/src/compiler/compile/render_dom/wrappers/Element/index.ts @@ -174,6 +174,8 @@ export default class ElementWrapper extends Wrapper { child_dynamic_element_block?: Block = null; child_dynamic_element?: ElementWrapper = null; + element_data_name = null; + constructor( renderer: Renderer, block: Block, @@ -287,6 +289,8 @@ export default class ElementWrapper extends Wrapper { } this.fragment = new FragmentWrapper(renderer, block, node.children, this, strip_whitespace, next_sibling); + + this.element_data_name = block.get_unique_name(`${this.var.name}_data`); } render(block: Block, parent_node: Identifier, parent_nodes: Identifier) { @@ -516,7 +520,8 @@ export default class ElementWrapper extends Wrapper { child.render( block, is_template ? x`${node}.content` : node, - nodes + nodes, + { element_data_name: this.element_data_name } ); }); } @@ -824,7 +829,6 @@ export default class ElementWrapper extends Wrapper { add_spread_attributes(block: Block) { const levels = block.get_unique_name(`${this.var.name}_levels`); - const data = block.get_unique_name(`${this.var.name}_data`); const initial_props = []; const updates = []; @@ -855,9 +859,9 @@ export default class ElementWrapper extends Wrapper { block.chunks.init.push(b` let ${levels} = [${initial_props}]; - let ${data} = {}; + let ${this.element_data_name} = {}; for (let #i = 0; #i < ${levels}.length; #i += 1) { - ${data} = @assign(${data}, ${levels}[#i]); + ${this.element_data_name} = @assign(${this.element_data_name}, ${levels}[#i]); } `); @@ -868,13 +872,13 @@ export default class ElementWrapper extends Wrapper { ? x`@set_dynamic_element_data(${this.node.tag_expr.manipulate(block)})` : x`@set_attributes`; - block.chunks.hydrate.push( - b`${fn}(${this.var}, ${data});` + block.chunks.hydrate.unshift( + b`${fn}(${this.var}, ${this.element_data_name});` ); if (this.has_dynamic_attribute) { - block.chunks.update.push(b` - ${fn}(${this.var}, ${data} = @get_spread_update(${levels}, [ + block.chunks.update.unshift(b` + ${fn}(${this.var}, ${this.element_data_name} = @get_spread_update(${levels}, [ ${updates} ])); `); @@ -890,23 +894,23 @@ export default class ElementWrapper extends Wrapper { } block.chunks.mount.push(b` - 'value' in ${data} && (${data}.multiple ? @select_options : @select_option)(${this.var}, ${data}.value); + 'value' in ${this.element_data_name} && (${this.element_data_name}.multiple ? @select_options : @select_option)(${this.var}, ${this.element_data_name}.value); `); block.chunks.update.push(b` - if (${block.renderer.dirty(Array.from(dependencies))} && 'value' in ${data}) (${data}.multiple ? @select_options : @select_option)(${this.var}, ${data}.value); + if (${block.renderer.dirty(Array.from(dependencies))} && 'value' in ${this.element_data_name}) (${this.element_data_name}.multiple ? @select_options : @select_option)(${this.var}, ${this.element_data_name}.value); `); } else if (this.node.name === 'input' && this.attributes.find(attr => attr.node.name === 'value')) { const type = this.node.get_static_attribute_value('type'); if (type === null || type === '' || type === 'text' || type === 'email' || type === 'password') { block.chunks.mount.push(b` - if ('value' in ${data}) { - ${this.var}.value = ${data}.value; + if ('value' in ${this.element_data_name}) { + ${this.var}.value = ${this.element_data_name}.value; } `); block.chunks.update.push(b` - if ('value' in ${data}) { - ${this.var}.value = ${data}.value; + if ('value' in ${this.element_data_name}) { + ${this.var}.value = ${this.element_data_name}.value; } `); } @@ -1220,8 +1224,8 @@ export default class ElementWrapper extends Wrapper { if (this.dynamic_style_dependencies.size > 0) { maybe_create_style_changed_var(); // If all dependencies are same as the style attribute dependencies, then we can skip the dirty check - condition = - all_deps.size === this.dynamic_style_dependencies.size + condition = + all_deps.size === this.dynamic_style_dependencies.size ? style_changed_var : x`${style_changed_var} || ${condition}`; } @@ -1232,7 +1236,6 @@ export default class ElementWrapper extends Wrapper { } `); } - }); } diff --git a/src/compiler/compile/render_dom/wrappers/MustacheTag.ts b/src/compiler/compile/render_dom/wrappers/MustacheTag.ts index ea6634ec803c..cbea2e7bcaa4 100644 --- a/src/compiler/compile/render_dom/wrappers/MustacheTag.ts +++ b/src/compiler/compile/render_dom/wrappers/MustacheTag.ts @@ -5,7 +5,9 @@ import Wrapper from './shared/Wrapper'; import MustacheTag from '../../nodes/MustacheTag'; import RawMustacheTag from '../../nodes/RawMustacheTag'; import { x } from 'code-red'; -import { Identifier } from 'estree'; +import { Identifier, Expression } from 'estree'; +import ElementWrapper from './Element'; +import AttributeWrapper from './Element/Attribute'; export default class MustacheTagWrapper extends Tag { var: Identifier = { type: 'Identifier', name: 't' }; @@ -14,10 +16,32 @@ export default class MustacheTagWrapper extends Tag { super(renderer, block, parent, node); } - render(block: Block, parent_node: Identifier, parent_nodes: Identifier) { + render(block: Block, parent_node: Identifier, parent_nodes: Identifier, data: Record | undefined) { + const contenteditable = + this.parent instanceof ElementWrapper && + this.parent.attributes.filter((a) => a.node.name === 'contenteditable'); + + const spread_attres = + this.parent instanceof ElementWrapper && + this.parent.attributes.filter((a) => a.node.is_spread); + + let is_contenteditable: Expression | undefined = undefined; + if (contenteditable.length > 0) { + const value = (contenteditable[0] as AttributeWrapper).get_value(block); + is_contenteditable = x`~@contenteditable_truly_values.indexOf(${value})`; + } else if (spread_attres.length > 0 && data.element_data_name) { + is_contenteditable = x`~@contenteditable_truly_values.indexOf(${data.element_data_name}['contenteditable'])`; + } + const { init } = this.rename_this_method( block, - value => x`@set_data(${this.var}, ${value})` + value => { + if (is_contenteditable) { + return x`@set_data(${this.var}, ${value}, ${is_contenteditable})`; + } else { + return x`@set_data(${this.var}, ${value})`; + } + } ); block.add_element( diff --git a/src/compiler/compile/render_dom/wrappers/shared/Wrapper.ts b/src/compiler/compile/render_dom/wrappers/shared/Wrapper.ts index 4bf8c20bd876..53847d887071 100644 --- a/src/compiler/compile/render_dom/wrappers/shared/Wrapper.ts +++ b/src/compiler/compile/render_dom/wrappers/shared/Wrapper.ts @@ -85,7 +85,7 @@ export default class Wrapper { ); } - render(_block: Block, _parent_node: Identifier, _parent_nodes: Identifier) { + render(_block: Block, _parent_node: Identifier, _parent_nodes: Identifier, _data: Record = undefined) { throw Error('Wrapper class is not renderable'); } } diff --git a/src/runtime/internal/dev.ts b/src/runtime/internal/dev.ts index e092c27ee26c..51547229cd27 100644 --- a/src/runtime/internal/dev.ts +++ b/src/runtime/internal/dev.ts @@ -83,17 +83,15 @@ export function dataset_dev(node: HTMLElement, property: string, value?: any) { dispatch_dev('SvelteDOMSetDataset', { node, property, value }); } -export function set_data_dev(text, data) { +export function set_data_dev(text: Text, data: unknown, is_contenteditable: boolean | undefined) { data = '' + data; - // In particular, when the property is contentEditable, ' 'TEXT_NODE is inserted into the text - if (text.textContent === '' && text.wholeText !== '') { + if (is_contenteditable) { if (text.wholeText === data) return; } else { - if (text.textContent === data) return; + if (text.data === data) return; } - dispatch_dev('SvelteDOMSetData', { node: text, data }); - text.data = data; + text.data = (data as string); } export function validate_each_argument(arg) { diff --git a/src/runtime/internal/dom.ts b/src/runtime/internal/dom.ts index 775c278bbaba..9d220ba8cce2 100644 --- a/src/runtime/internal/dom.ts +++ b/src/runtime/internal/dom.ts @@ -581,15 +581,14 @@ export function claim_html_tag(nodes, is_svg: boolean) { return new HtmlTagHydration(claimed_nodes, is_svg); } -export function set_data(text, data) { +export function set_data(text: Text, data: unknown, is_contenteditable: boolean | undefined) { data = '' + data; - // In particular, when the property is contentEditable, ' 'TEXT_NODE is inserted into the text - if (text.textContent === '' && text.wholeText !== '') { + if (is_contenteditable) { if (text.wholeText === data) return; } else { - if (text.textContent === data) return; + if (text.data === data) return; } - text.data = data; + text.data = (data as string); } export function set_input_value(input, value) { diff --git a/src/runtime/internal/utils.ts b/src/runtime/internal/utils.ts index b1c27a355de1..31623eeaab7b 100644 --- a/src/runtime/internal/utils.ts +++ b/src/runtime/internal/utils.ts @@ -194,3 +194,5 @@ export function split_css_unit(value: number | string): [number, string] { const split = typeof value === 'string' && value.match(/^\s*(-?[\d.]+)([^\s]*)\s*$/); return split ? [parseFloat(split[1]), split[2] || 'px'] : [value as number, 'px']; } + +export const contenteditable_truly_values = ['', true, 1, 'true', 'contenteditable']; diff --git a/test/runtime/samples/component-event-handler-contenteditable/_config.js b/test/runtime/samples/component-event-handler-contenteditable/_config.js index 1628e22d017b..cfd51e500591 100644 --- a/test/runtime/samples/component-event-handler-contenteditable/_config.js +++ b/test/runtime/samples/component-event-handler-contenteditable/_config.js @@ -1,7 +1,5 @@ export default { - html: ` -
- `, + html: '
', async test({ assert, target, window }) { const div = target.querySelector('div'); @@ -9,7 +7,6 @@ export default { div.insertBefore(text, null); const event = new window.InputEvent('input'); await div.dispatchEvent(event); - assert.equal(div.textContent, 'a'); } }; diff --git a/test/runtime/samples/component-event-handler-contenteditable2/_config.js b/test/runtime/samples/component-event-handler-contenteditable2/_config.js new file mode 100644 index 000000000000..10736ec1b2b1 --- /dev/null +++ b/test/runtime/samples/component-event-handler-contenteditable2/_config.js @@ -0,0 +1,12 @@ +export default { + html: '
', + + async test({ assert, target, window }) { + const div = target.querySelector('div'); + const text = window.document.createTextNode('a'); + div.insertBefore(text, null); + const event = new window.InputEvent('input'); + await div.dispatchEvent(event); + assert.equal(div.textContent, 'a'); + } +}; diff --git a/test/runtime/samples/component-event-handler-contenteditable2/main.svelte b/test/runtime/samples/component-event-handler-contenteditable2/main.svelte new file mode 100644 index 000000000000..e540ceff2571 --- /dev/null +++ b/test/runtime/samples/component-event-handler-contenteditable2/main.svelte @@ -0,0 +1,6 @@ + + +
{text}
diff --git a/test/runtime/samples/component-event-handler-contenteditable3/_config.js b/test/runtime/samples/component-event-handler-contenteditable3/_config.js new file mode 100644 index 000000000000..957be6388b49 --- /dev/null +++ b/test/runtime/samples/component-event-handler-contenteditable3/_config.js @@ -0,0 +1,13 @@ +export default { + html: '
', + ssrHtml: '
', + + async test({ assert, target, window }) { + const div = target.querySelector('div'); + const text = window.document.createTextNode('a'); + div.insertBefore(text, null); + const event = new window.InputEvent('input'); + await div.dispatchEvent(event); + assert.equal(div.textContent, 'a'); + } +}; diff --git a/test/runtime/samples/component-event-handler-contenteditable3/main.svelte b/test/runtime/samples/component-event-handler-contenteditable3/main.svelte new file mode 100644 index 000000000000..34bc4300e08e --- /dev/null +++ b/test/runtime/samples/component-event-handler-contenteditable3/main.svelte @@ -0,0 +1,9 @@ + + +
{text}
diff --git a/test/runtime/samples/component-event-handler-contenteditable4/_config.js b/test/runtime/samples/component-event-handler-contenteditable4/_config.js new file mode 100644 index 000000000000..bc9d65d1c315 --- /dev/null +++ b/test/runtime/samples/component-event-handler-contenteditable4/_config.js @@ -0,0 +1,12 @@ +export default { + html: '
', + + async test({ assert, target, component, window }) { + const div = target.querySelector('div'); + const text = window.document.createTextNode('a'); + div.insertBefore(text, null); + assert.equal(div.textContent, 'a'); + component.text = 'bcde'; + assert.equal(div.textContent, 'bcdea'); + } +}; diff --git a/test/runtime/samples/component-event-handler-contenteditable4/main.svelte b/test/runtime/samples/component-event-handler-contenteditable4/main.svelte new file mode 100644 index 000000000000..955592548748 --- /dev/null +++ b/test/runtime/samples/component-event-handler-contenteditable4/main.svelte @@ -0,0 +1,6 @@ + + +
{text}
diff --git a/test/runtime/samples/reactive-values-text-node/_config.js b/test/runtime/samples/reactive-values-text-node/_config.js index 9e0cb2d5d306..fb859285ddda 100644 --- a/test/runtime/samples/reactive-values-text-node/_config.js +++ b/test/runtime/samples/reactive-values-text-node/_config.js @@ -1,6 +1,6 @@ export default { html:'
same text
', - async test({ assert, component, target }) { + async test({ assert, target }) { await new Promise(f => setTimeout(f, 10)); assert.htmlEqual(target.innerHTML, `
same text text
diff --git a/test/runtime/samples/reactive-values-text-node/main.svelte b/test/runtime/samples/reactive-values-text-node/main.svelte index 1ca11d19f443..0982622b1a91 100644 --- a/test/runtime/samples/reactive-values-text-node/main.svelte +++ b/test/runtime/samples/reactive-values-text-node/main.svelte @@ -1,8 +1,8 @@ -
{text} text
\ No newline at end of file +
{text} text
From 535623de61b9ea7da936be12535b11a7b5b40ff8 Mon Sep 17 00:00:00 2001 From: baseballyama Date: Sun, 19 Mar 2023 00:47:43 +0900 Subject: [PATCH 07/14] refactor and split runtine function --- .../compile/render_dom/wrappers/MustacheTag.ts | 12 ++++++------ src/runtime/internal/dev.ts | 15 +++++++++------ src/runtime/internal/dom.ts | 16 +++++++++------- 3 files changed, 24 insertions(+), 19 deletions(-) diff --git a/src/compiler/compile/render_dom/wrappers/MustacheTag.ts b/src/compiler/compile/render_dom/wrappers/MustacheTag.ts index cbea2e7bcaa4..34edf5378865 100644 --- a/src/compiler/compile/render_dom/wrappers/MustacheTag.ts +++ b/src/compiler/compile/render_dom/wrappers/MustacheTag.ts @@ -17,19 +17,19 @@ export default class MustacheTagWrapper extends Tag { } render(block: Block, parent_node: Identifier, parent_nodes: Identifier, data: Record | undefined) { - const contenteditable = + const contenteditable_attributes = this.parent instanceof ElementWrapper && this.parent.attributes.filter((a) => a.node.name === 'contenteditable'); - const spread_attres = + const spread_attributes = this.parent instanceof ElementWrapper && this.parent.attributes.filter((a) => a.node.is_spread); let is_contenteditable: Expression | undefined = undefined; - if (contenteditable.length > 0) { - const value = (contenteditable[0] as AttributeWrapper).get_value(block); + if (contenteditable_attributes.length > 0) { + const value = (contenteditable_attributes[0] as AttributeWrapper).get_value(block); is_contenteditable = x`~@contenteditable_truly_values.indexOf(${value})`; - } else if (spread_attres.length > 0 && data.element_data_name) { + } else if (spread_attributes.length > 0 && data.element_data_name) { is_contenteditable = x`~@contenteditable_truly_values.indexOf(${data.element_data_name}['contenteditable'])`; } @@ -37,7 +37,7 @@ export default class MustacheTagWrapper extends Tag { block, value => { if (is_contenteditable) { - return x`@set_data(${this.var}, ${value}, ${is_contenteditable})`; + return x`@set_data_contenteditable(${this.var}, ${value}, ${is_contenteditable})`; } else { return x`@set_data(${this.var}, ${value})`; } diff --git a/src/runtime/internal/dev.ts b/src/runtime/internal/dev.ts index 51547229cd27..8dec822a41ff 100644 --- a/src/runtime/internal/dev.ts +++ b/src/runtime/internal/dev.ts @@ -83,13 +83,16 @@ export function dataset_dev(node: HTMLElement, property: string, value?: any) { dispatch_dev('SvelteDOMSetDataset', { node, property, value }); } -export function set_data_dev(text: Text, data: unknown, is_contenteditable: boolean | undefined) { +export function set_data_dev(text: Text, data: unknown) { data = '' + data; - if (is_contenteditable) { - if (text.wholeText === data) return; - } else { - if (text.data === data) return; - } + if (text.data === data) return; + dispatch_dev('SvelteDOMSetData', { node: text, data }); + text.data = (data as string); +} + +export function set_data_contenteditable_dev(text: Text, data: unknown) { + data = '' + data; + if (text.wholeText === data) return; dispatch_dev('SvelteDOMSetData', { node: text, data }); text.data = (data as string); } diff --git a/src/runtime/internal/dom.ts b/src/runtime/internal/dom.ts index 9d220ba8cce2..4b0b27f62845 100644 --- a/src/runtime/internal/dom.ts +++ b/src/runtime/internal/dom.ts @@ -581,14 +581,16 @@ export function claim_html_tag(nodes, is_svg: boolean) { return new HtmlTagHydration(claimed_nodes, is_svg); } -export function set_data(text: Text, data: unknown, is_contenteditable: boolean | undefined) { +export function set_data(text: Text, data: unknown) { data = '' + data; - if (is_contenteditable) { - if (text.wholeText === data) return; - } else { - if (text.data === data) return; - } - text.data = (data as string); + if (text.data === data) return; + text.data = (data as string); +} + +export function set_data_contenteditable(text: Text, data: unknown) { + data = '' + data; + if (text.wholeText === data) return; + text.data = (data as string); } export function set_input_value(input, value) { From 370a8942c3c430515b1180e8dbb6d1f5659931e7 Mon Sep 17 00:00:00 2001 From: Simon Holthausen Date: Sun, 19 Mar 2023 15:04:47 +0100 Subject: [PATCH 08/14] truthy --- src/compiler/compile/render_dom/wrappers/MustacheTag.ts | 4 ++-- src/runtime/internal/utils.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/compiler/compile/render_dom/wrappers/MustacheTag.ts b/src/compiler/compile/render_dom/wrappers/MustacheTag.ts index 34edf5378865..886a964b72a0 100644 --- a/src/compiler/compile/render_dom/wrappers/MustacheTag.ts +++ b/src/compiler/compile/render_dom/wrappers/MustacheTag.ts @@ -28,9 +28,9 @@ export default class MustacheTagWrapper extends Tag { let is_contenteditable: Expression | undefined = undefined; if (contenteditable_attributes.length > 0) { const value = (contenteditable_attributes[0] as AttributeWrapper).get_value(block); - is_contenteditable = x`~@contenteditable_truly_values.indexOf(${value})`; + is_contenteditable = x`~@contenteditable_truthy_values.indexOf(${value})`; } else if (spread_attributes.length > 0 && data.element_data_name) { - is_contenteditable = x`~@contenteditable_truly_values.indexOf(${data.element_data_name}['contenteditable'])`; + is_contenteditable = x`~@contenteditable_truthy_values.indexOf(${data.element_data_name}['contenteditable'])`; } const { init } = this.rename_this_method( diff --git a/src/runtime/internal/utils.ts b/src/runtime/internal/utils.ts index 31623eeaab7b..192f40140e4c 100644 --- a/src/runtime/internal/utils.ts +++ b/src/runtime/internal/utils.ts @@ -195,4 +195,4 @@ export function split_css_unit(value: number | string): [number, string] { return split ? [parseFloat(split[1]), split[2] || 'px'] : [value as number, 'px']; } -export const contenteditable_truly_values = ['', true, 1, 'true', 'contenteditable']; +export const contenteditable_truthy_values = ['', true, 1, 'true', 'contenteditable']; From 1a9f56660f29102019093cafb0e7e1e223c785e0 Mon Sep 17 00:00:00 2001 From: Simon Holthausen Date: Mon, 20 Mar 2023 12:03:35 +0100 Subject: [PATCH 09/14] fix double elementwrapper output in rollup; fix code --- src/compiler/compile/render_dom/wrappers/Fragment.ts | 2 +- src/compiler/compile/render_dom/wrappers/MustacheTag.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/compiler/compile/render_dom/wrappers/Fragment.ts b/src/compiler/compile/render_dom/wrappers/Fragment.ts index 8c633aeb71fd..463c8db24a1b 100644 --- a/src/compiler/compile/render_dom/wrappers/Fragment.ts +++ b/src/compiler/compile/render_dom/wrappers/Fragment.ts @@ -4,7 +4,7 @@ import Body from './Body'; import DebugTag from './DebugTag'; import Document from './Document'; import EachBlock from './EachBlock'; -import Element from './Element/index'; +import Element from './Element'; import Head from './Head'; import IfBlock from './IfBlock'; import KeyBlock from './KeyBlock'; diff --git a/src/compiler/compile/render_dom/wrappers/MustacheTag.ts b/src/compiler/compile/render_dom/wrappers/MustacheTag.ts index 886a964b72a0..cfece7bc5fd4 100644 --- a/src/compiler/compile/render_dom/wrappers/MustacheTag.ts +++ b/src/compiler/compile/render_dom/wrappers/MustacheTag.ts @@ -37,7 +37,7 @@ export default class MustacheTagWrapper extends Tag { block, value => { if (is_contenteditable) { - return x`@set_data_contenteditable(${this.var}, ${value}, ${is_contenteditable})`; + return x`${is_contenteditable} ? @set_data_contenteditable(${this.var}, ${value}) : @set_data(${this.var}, ${value})` } else { return x`@set_data(${this.var}, ${value})`; } From e6bdc5a4ffc938ccc2c4e80e0a55c068413ddd72 Mon Sep 17 00:00:00 2001 From: Simon Holthausen Date: Mon, 20 Mar 2023 12:06:40 +0100 Subject: [PATCH 10/14] refactor into smaller compiler output --- .../compile/render_dom/wrappers/MustacheTag.ts | 10 +++++----- src/runtime/internal/dev.ts | 15 ++++++++++----- src/runtime/internal/dom.ts | 14 +++++++++----- 3 files changed, 24 insertions(+), 15 deletions(-) diff --git a/src/compiler/compile/render_dom/wrappers/MustacheTag.ts b/src/compiler/compile/render_dom/wrappers/MustacheTag.ts index cfece7bc5fd4..f636f1028b3d 100644 --- a/src/compiler/compile/render_dom/wrappers/MustacheTag.ts +++ b/src/compiler/compile/render_dom/wrappers/MustacheTag.ts @@ -25,19 +25,19 @@ export default class MustacheTagWrapper extends Tag { this.parent instanceof ElementWrapper && this.parent.attributes.filter((a) => a.node.is_spread); - let is_contenteditable: Expression | undefined = undefined; + let contenteditable_attr_value: Expression | undefined = undefined; if (contenteditable_attributes.length > 0) { const value = (contenteditable_attributes[0] as AttributeWrapper).get_value(block); - is_contenteditable = x`~@contenteditable_truthy_values.indexOf(${value})`; + contenteditable_attr_value = x`${value}`; } else if (spread_attributes.length > 0 && data.element_data_name) { - is_contenteditable = x`~@contenteditable_truthy_values.indexOf(${data.element_data_name}['contenteditable'])`; + contenteditable_attr_value = x`${data.element_data_name}['contenteditable']`; } const { init } = this.rename_this_method( block, value => { - if (is_contenteditable) { - return x`${is_contenteditable} ? @set_data_contenteditable(${this.var}, ${value}) : @set_data(${this.var}, ${value})` + if (contenteditable_attr_value) { + return x`@set_data_maybe_contenteditable(${this.var}, ${value}, ${contenteditable_attr_value})` } else { return x`@set_data(${this.var}, ${value})`; } diff --git a/src/runtime/internal/dev.ts b/src/runtime/internal/dev.ts index 8dec822a41ff..ae50e365d2e9 100644 --- a/src/runtime/internal/dev.ts +++ b/src/runtime/internal/dev.ts @@ -1,6 +1,7 @@ import { custom_event, append, append_hydration, insert, insert_hydration, detach, listen, attr } from './dom'; import { SvelteComponent } from './Component'; import { is_void } from '../../shared/utils/names'; +import { contenteditable_truthy_values } from './utils'; export function dispatch_dev(type: string, detail?: T) { document.dispatchEvent(custom_event(type, { version: '__VERSION__', ...detail }, { bubbles: true })); @@ -90,11 +91,15 @@ export function set_data_dev(text: Text, data: unknown) { text.data = (data as string); } -export function set_data_contenteditable_dev(text: Text, data: unknown) { - data = '' + data; - if (text.wholeText === data) return; - dispatch_dev('SvelteDOMSetData', { node: text, data }); - text.data = (data as string); +export function set_data_maybe_contenteditable_dev(text: Text, data: unknown, attr_value: string) { + if (~contenteditable_truthy_values.indexOf(attr_value)) { + data = '' + data; + if (text.wholeText === data) return; + dispatch_dev('SvelteDOMSetData', { node: text, data }); + text.data = (data as string); + } else { + set_data_dev(text, data); + } } export function validate_each_argument(arg) { diff --git a/src/runtime/internal/dom.ts b/src/runtime/internal/dom.ts index 4b0b27f62845..2e54305c46f3 100644 --- a/src/runtime/internal/dom.ts +++ b/src/runtime/internal/dom.ts @@ -1,4 +1,4 @@ -import { has_prop } from './utils'; +import { contenteditable_truthy_values, has_prop } from './utils'; // Track which nodes are claimed during hydration. Unclaimed nodes can then be removed from the DOM // at the end of hydration without touching the remaining nodes. @@ -587,10 +587,14 @@ export function set_data(text: Text, data: unknown) { text.data = (data as string); } -export function set_data_contenteditable(text: Text, data: unknown) { - data = '' + data; - if (text.wholeText === data) return; - text.data = (data as string); +export function set_data_maybe_contenteditable(text: Text, data: unknown, attr_value: string) { + if (~contenteditable_truthy_values.indexOf(attr_value)) { + data = '' + data; + if (text.wholeText === data) return; + text.data = (data as string); + } else { + set_data(text, data); + } } export function set_input_value(input, value) { From e257fd105435e70e569778adc940dd622bb90066 Mon Sep 17 00:00:00 2001 From: Simon Holthausen Date: Mon, 20 Mar 2023 12:47:15 +0100 Subject: [PATCH 11/14] can't wait for prettier to land in this repo --- src/compiler/compile/render_dom/wrappers/MustacheTag.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/compile/render_dom/wrappers/MustacheTag.ts b/src/compiler/compile/render_dom/wrappers/MustacheTag.ts index f636f1028b3d..08d2b9ee87d5 100644 --- a/src/compiler/compile/render_dom/wrappers/MustacheTag.ts +++ b/src/compiler/compile/render_dom/wrappers/MustacheTag.ts @@ -37,7 +37,7 @@ export default class MustacheTagWrapper extends Tag { block, value => { if (contenteditable_attr_value) { - return x`@set_data_maybe_contenteditable(${this.var}, ${value}, ${contenteditable_attr_value})` + return x`@set_data_maybe_contenteditable(${this.var}, ${value}, ${contenteditable_attr_value})`; } else { return x`@set_data(${this.var}, ${value})`; } From 866e52a72259eaa9de975cef65d8af252c699e6b Mon Sep 17 00:00:00 2001 From: Simon Holthausen Date: Tue, 21 Mar 2023 13:38:30 +0100 Subject: [PATCH 12/14] - move tests to puppeteer because jsdom does not support contenteditable - remove unnecessary test - adjust one test to actually test a regression and skip it because it fails --- .../render_dom/wrappers/Element/index.ts | 4 +-- .../_config.js | 1 + .../main.svelte | 0 .../_config.js | 24 ++++++++++++++ .../main.svelte | 11 +++++++ .../_config.js | 33 +++++++++++++++++++ .../main.svelte | 0 .../_config.js | 12 ------- .../_config.js | 12 ------- .../main.svelte | 6 ---- .../_config.js | 13 -------- .../main.svelte | 9 ----- 12 files changed, 71 insertions(+), 54 deletions(-) rename test/{runtime/samples/component-event-handler-contenteditable4 => runtime-puppeteer/samples/component-event-handler-contenteditable-false}/_config.js (84%) rename test/{runtime/samples/component-event-handler-contenteditable4 => runtime-puppeteer/samples/component-event-handler-contenteditable-false}/main.svelte (100%) create mode 100644 test/runtime-puppeteer/samples/component-event-handler-contenteditable-spread/_config.js create mode 100644 test/runtime-puppeteer/samples/component-event-handler-contenteditable-spread/main.svelte create mode 100644 test/runtime-puppeteer/samples/component-event-handler-contenteditable/_config.js rename test/{runtime => runtime-puppeteer}/samples/component-event-handler-contenteditable/main.svelte (100%) delete mode 100644 test/runtime/samples/component-event-handler-contenteditable/_config.js delete mode 100644 test/runtime/samples/component-event-handler-contenteditable2/_config.js delete mode 100644 test/runtime/samples/component-event-handler-contenteditable2/main.svelte delete mode 100644 test/runtime/samples/component-event-handler-contenteditable3/_config.js delete mode 100644 test/runtime/samples/component-event-handler-contenteditable3/main.svelte diff --git a/src/compiler/compile/render_dom/wrappers/Element/index.ts b/src/compiler/compile/render_dom/wrappers/Element/index.ts index b57d24ae9c5e..7a0bdbaa060a 100644 --- a/src/compiler/compile/render_dom/wrappers/Element/index.ts +++ b/src/compiler/compile/render_dom/wrappers/Element/index.ts @@ -872,12 +872,12 @@ export default class ElementWrapper extends Wrapper { ? x`@set_dynamic_element_data(${this.node.tag_expr.manipulate(block)})` : x`@set_attributes`; - block.chunks.hydrate.unshift( + block.chunks.hydrate.push( b`${fn}(${this.var}, ${this.element_data_name});` ); if (this.has_dynamic_attribute) { - block.chunks.update.unshift(b` + block.chunks.update.push(b` ${fn}(${this.var}, ${this.element_data_name} = @get_spread_update(${levels}, [ ${updates} ])); diff --git a/test/runtime/samples/component-event-handler-contenteditable4/_config.js b/test/runtime-puppeteer/samples/component-event-handler-contenteditable-false/_config.js similarity index 84% rename from test/runtime/samples/component-event-handler-contenteditable4/_config.js rename to test/runtime-puppeteer/samples/component-event-handler-contenteditable-false/_config.js index bc9d65d1c315..3763360fd82a 100644 --- a/test/runtime/samples/component-event-handler-contenteditable4/_config.js +++ b/test/runtime-puppeteer/samples/component-event-handler-contenteditable-false/_config.js @@ -1,3 +1,4 @@ +// A puppeteer test because JSDOM doesn't support contenteditable export default { html: '
', diff --git a/test/runtime/samples/component-event-handler-contenteditable4/main.svelte b/test/runtime-puppeteer/samples/component-event-handler-contenteditable-false/main.svelte similarity index 100% rename from test/runtime/samples/component-event-handler-contenteditable4/main.svelte rename to test/runtime-puppeteer/samples/component-event-handler-contenteditable-false/main.svelte diff --git a/test/runtime-puppeteer/samples/component-event-handler-contenteditable-spread/_config.js b/test/runtime-puppeteer/samples/component-event-handler-contenteditable-spread/_config.js new file mode 100644 index 000000000000..de65bd662752 --- /dev/null +++ b/test/runtime-puppeteer/samples/component-event-handler-contenteditable-spread/_config.js @@ -0,0 +1,24 @@ +// A puppeteer test because JSDOM doesn't support contenteditable +export default { + html: '
', + ssrHtml: '
', + + async test({ assert, target, window }) { + // this tests that by going from contenteditable=true to false, the + // content is correctly updated before that. This relies on the order + // of the updates: first updating the content, then setting contenteditable + // to false, which means that `set_data_maybe_contenteditable` is used and not `set_data`. + // If the order is reversed, https://github.com/sveltejs/svelte/issues/5018 + // would be happening. The caveat is that if we go from contenteditable=false to true + // then we will have the same issue. To fix this reliably we probably need to + // overhaul the way we handle text updates in general. + // If due to some refactoring this test fails, it's probably fine to ignore it since + // this is a very specific edge case and the behavior is unstable anyway. + const div = target.querySelector('div'); + const text = window.document.createTextNode('a'); + div.insertBefore(text, null); + const event = new window.InputEvent('input'); + await div.dispatchEvent(event); + assert.equal(div.textContent, 'a'); + } +}; diff --git a/test/runtime-puppeteer/samples/component-event-handler-contenteditable-spread/main.svelte b/test/runtime-puppeteer/samples/component-event-handler-contenteditable-spread/main.svelte new file mode 100644 index 000000000000..ed301e8d2037 --- /dev/null +++ b/test/runtime-puppeteer/samples/component-event-handler-contenteditable-spread/main.svelte @@ -0,0 +1,11 @@ + + +
{text}
diff --git a/test/runtime-puppeteer/samples/component-event-handler-contenteditable/_config.js b/test/runtime-puppeteer/samples/component-event-handler-contenteditable/_config.js new file mode 100644 index 000000000000..1b4b3b0271e8 --- /dev/null +++ b/test/runtime-puppeteer/samples/component-event-handler-contenteditable/_config.js @@ -0,0 +1,33 @@ +// A puppeteer test because JSDOM doesn't support contenteditable +export default { + html: '
', + + // Failing test for https://github.com/sveltejs/svelte/issues/5018, fix pending + // It's hard to fix this because in order to do that, we would need to change the + // way the value is compared completely. Right now it compares the value of the + // first text node, but it should compare the value of the whole content + skip: true, + + async test({ assert, target, window }) { + const div = target.querySelector('div'); + + let text = window.document.createTextNode('a'); + div.insertBefore(text, null); + let event = new window.InputEvent('input'); + await div.dispatchEvent(event); + assert.equal(div.textContent, 'a'); + + // When a user types a newline, the browser inserts a
element + const inner_div = window.document.createElement('div'); + div.insertBefore(inner_div, null); + event = new window.InputEvent('input'); + await div.dispatchEvent(event); + assert.equal(div.textContent, 'a'); + + text = window.document.createTextNode('b'); + inner_div.insertBefore(text, null); + event = new window.InputEvent('input'); + await div.dispatchEvent(event); + assert.equal(div.textContent, 'ab'); + } +}; diff --git a/test/runtime/samples/component-event-handler-contenteditable/main.svelte b/test/runtime-puppeteer/samples/component-event-handler-contenteditable/main.svelte similarity index 100% rename from test/runtime/samples/component-event-handler-contenteditable/main.svelte rename to test/runtime-puppeteer/samples/component-event-handler-contenteditable/main.svelte diff --git a/test/runtime/samples/component-event-handler-contenteditable/_config.js b/test/runtime/samples/component-event-handler-contenteditable/_config.js deleted file mode 100644 index cfd51e500591..000000000000 --- a/test/runtime/samples/component-event-handler-contenteditable/_config.js +++ /dev/null @@ -1,12 +0,0 @@ -export default { - html: '
', - - async test({ assert, target, window }) { - const div = target.querySelector('div'); - const text = window.document.createTextNode('a'); - div.insertBefore(text, null); - const event = new window.InputEvent('input'); - await div.dispatchEvent(event); - assert.equal(div.textContent, 'a'); - } -}; diff --git a/test/runtime/samples/component-event-handler-contenteditable2/_config.js b/test/runtime/samples/component-event-handler-contenteditable2/_config.js deleted file mode 100644 index 10736ec1b2b1..000000000000 --- a/test/runtime/samples/component-event-handler-contenteditable2/_config.js +++ /dev/null @@ -1,12 +0,0 @@ -export default { - html: '
', - - async test({ assert, target, window }) { - const div = target.querySelector('div'); - const text = window.document.createTextNode('a'); - div.insertBefore(text, null); - const event = new window.InputEvent('input'); - await div.dispatchEvent(event); - assert.equal(div.textContent, 'a'); - } -}; diff --git a/test/runtime/samples/component-event-handler-contenteditable2/main.svelte b/test/runtime/samples/component-event-handler-contenteditable2/main.svelte deleted file mode 100644 index e540ceff2571..000000000000 --- a/test/runtime/samples/component-event-handler-contenteditable2/main.svelte +++ /dev/null @@ -1,6 +0,0 @@ - - -
{text}
diff --git a/test/runtime/samples/component-event-handler-contenteditable3/_config.js b/test/runtime/samples/component-event-handler-contenteditable3/_config.js deleted file mode 100644 index 957be6388b49..000000000000 --- a/test/runtime/samples/component-event-handler-contenteditable3/_config.js +++ /dev/null @@ -1,13 +0,0 @@ -export default { - html: '
', - ssrHtml: '
', - - async test({ assert, target, window }) { - const div = target.querySelector('div'); - const text = window.document.createTextNode('a'); - div.insertBefore(text, null); - const event = new window.InputEvent('input'); - await div.dispatchEvent(event); - assert.equal(div.textContent, 'a'); - } -}; diff --git a/test/runtime/samples/component-event-handler-contenteditable3/main.svelte b/test/runtime/samples/component-event-handler-contenteditable3/main.svelte deleted file mode 100644 index 34bc4300e08e..000000000000 --- a/test/runtime/samples/component-event-handler-contenteditable3/main.svelte +++ /dev/null @@ -1,9 +0,0 @@ - - -
{text}
From 55209c44f5ad684db1cb777c6287516f132a561d Mon Sep 17 00:00:00 2001 From: Simon Holthausen Date: Tue, 21 Mar 2023 13:56:28 +0100 Subject: [PATCH 13/14] optimize for static contenteditable value --- .../compile/render_dom/wrappers/MustacheTag.ts | 16 ++++++++++++---- src/runtime/internal/dev.ts | 12 ++++++++---- src/runtime/internal/dom.ts | 10 +++++++--- 3 files changed, 27 insertions(+), 11 deletions(-) diff --git a/src/compiler/compile/render_dom/wrappers/MustacheTag.ts b/src/compiler/compile/render_dom/wrappers/MustacheTag.ts index 08d2b9ee87d5..0bfa0198aea8 100644 --- a/src/compiler/compile/render_dom/wrappers/MustacheTag.ts +++ b/src/compiler/compile/render_dom/wrappers/MustacheTag.ts @@ -25,10 +25,14 @@ export default class MustacheTagWrapper extends Tag { this.parent instanceof ElementWrapper && this.parent.attributes.filter((a) => a.node.is_spread); - let contenteditable_attr_value: Expression | undefined = undefined; + let contenteditable_attr_value: Expression | true | undefined = undefined; if (contenteditable_attributes.length > 0) { - const value = (contenteditable_attributes[0] as AttributeWrapper).get_value(block); - contenteditable_attr_value = x`${value}`; + const attribute = contenteditable_attributes[0] as AttributeWrapper; + if ([true, 'true', ''].includes(attribute.node.get_static_value())) { + contenteditable_attr_value = true; + } else { + contenteditable_attr_value = x`${attribute.get_value(block)}`; + } } else if (spread_attributes.length > 0 && data.element_data_name) { contenteditable_attr_value = x`${data.element_data_name}['contenteditable']`; } @@ -37,7 +41,11 @@ export default class MustacheTagWrapper extends Tag { block, value => { if (contenteditable_attr_value) { - return x`@set_data_maybe_contenteditable(${this.var}, ${value}, ${contenteditable_attr_value})`; + if (contenteditable_attr_value === true) { + return x`@set_data_contenteditable(${this.var}, ${value})`; + } else { + return x`@set_data_maybe_contenteditable(${this.var}, ${value}, ${contenteditable_attr_value})`; + } } else { return x`@set_data(${this.var}, ${value})`; } diff --git a/src/runtime/internal/dev.ts b/src/runtime/internal/dev.ts index ae50e365d2e9..cd47138fefcc 100644 --- a/src/runtime/internal/dev.ts +++ b/src/runtime/internal/dev.ts @@ -91,12 +91,16 @@ export function set_data_dev(text: Text, data: unknown) { text.data = (data as string); } +export function set_data_contenteditable_dev(text: Text, data: unknown) { + data = '' + data; + if (text.wholeText === data) return; + dispatch_dev('SvelteDOMSetData', { node: text, data }); + text.data = (data as string); +} + export function set_data_maybe_contenteditable_dev(text: Text, data: unknown, attr_value: string) { if (~contenteditable_truthy_values.indexOf(attr_value)) { - data = '' + data; - if (text.wholeText === data) return; - dispatch_dev('SvelteDOMSetData', { node: text, data }); - text.data = (data as string); + set_data_contenteditable_dev(text, data); } else { set_data_dev(text, data); } diff --git a/src/runtime/internal/dom.ts b/src/runtime/internal/dom.ts index 2e54305c46f3..bbe9ed2e0859 100644 --- a/src/runtime/internal/dom.ts +++ b/src/runtime/internal/dom.ts @@ -587,11 +587,15 @@ export function set_data(text: Text, data: unknown) { text.data = (data as string); } +export function set_data_contenteditable(text: Text, data: unknown) { + data = '' + data; + if (text.wholeText === data) return; + text.data = (data as string); +} + export function set_data_maybe_contenteditable(text: Text, data: unknown, attr_value: string) { if (~contenteditable_truthy_values.indexOf(attr_value)) { - data = '' + data; - if (text.wholeText === data) return; - text.data = (data as string); + set_data_contenteditable(text, data) } else { set_data(text, data); } From 05f0927f556092bc7f32136713e2d99ac29fac02 Mon Sep 17 00:00:00 2001 From: Simon Holthausen Date: Tue, 21 Mar 2023 13:59:58 +0100 Subject: [PATCH 14/14] ffs --- src/runtime/internal/dom.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/runtime/internal/dom.ts b/src/runtime/internal/dom.ts index bbe9ed2e0859..a7466131708e 100644 --- a/src/runtime/internal/dom.ts +++ b/src/runtime/internal/dom.ts @@ -595,7 +595,7 @@ export function set_data_contenteditable(text: Text, data: unknown) { export function set_data_maybe_contenteditable(text: Text, data: unknown, attr_value: string) { if (~contenteditable_truthy_values.indexOf(attr_value)) { - set_data_contenteditable(text, data) + set_data_contenteditable(text, data); } else { set_data(text, data); }