diff --git a/src/runtime/internal/Component.ts b/src/runtime/internal/Component.ts index 9bab5c7575..0772d98f6c 100644 --- a/src/runtime/internal/Component.ts +++ b/src/runtime/internal/Component.ts @@ -238,7 +238,7 @@ if (typeof HTMLElement === 'function') { attr = this.$$get_prop_name(attr); this.$$data[attr] = get_custom_element_value(attr, newValue, this.$$props_definition, 'toProp'); - this.$$component![attr] = this.$$data[attr]; + this.$$component!.$set({ [attr]: this.$$data[attr] }); } disconnectedCallback() { @@ -253,7 +253,10 @@ if (typeof HTMLElement === 'function') { } private $$get_prop_name(attribute_name: string): string { - return Object.keys(this.$$props_definition).find(key => this.$$props_definition[key].attribute === attribute_name) || attribute_name; + return Object.keys(this.$$props_definition).find( + key => this.$$props_definition[key].attribute === attribute_name || + (!this.$$props_definition[key].attribute && key.toLowerCase() === attribute_name) + ) || attribute_name; } }; } @@ -316,12 +319,12 @@ export function create_custom_element( } static get observedAttributes() { - return Object.keys(props_definition).map(key => props_definition[key].attribute || key); + return Object.keys(props_definition).map(key => (props_definition[key].attribute || key).toLowerCase()); } }; - function createProperty(name: string, prop: string) { - Object.defineProperty(Class.prototype, name, { + Object.keys(props_definition).forEach((prop) => { + Object.defineProperty(Class.prototype, prop, { get() { return this.$$component && prop in this.$$component ? this.$$component[prop] @@ -331,10 +334,7 @@ export function create_custom_element( set(value) { value = get_custom_element_value(prop, value, props_definition); this.$$data[prop] = value; - - if (this.$$component) { - this.$$component[prop] = value; - } + this.$$component?.$set({ [prop]: value }); if (props_definition[prop].reflect) { this.$$reflecting = true; @@ -351,15 +351,6 @@ export function create_custom_element( } } }); - } - - Object.keys(props_definition).forEach((prop) => { - createProperty(prop, prop); - // will be ce.camcelcase = "foo" - const lower = prop.toLowerCase(); - if (lower !== prop) { - createProperty(lower, prop); - } }); accessors.forEach(accessor => { diff --git a/test/custom-elements/samples/action/test.js b/test/custom-elements/samples/action/test.js index e57be4059e..4619ae8568 100644 --- a/test/custom-elements/samples/action/test.js +++ b/test/custom-elements/samples/action/test.js @@ -10,6 +10,7 @@ export default async function (target) { assert.deepEqual(events, ['foo']); el.name = 'bar'; + await tick(); assert.deepEqual(events, ['foo', 'bar']); target.innerHTML = ''; diff --git a/test/custom-elements/samples/camel-case-attribute/main.svelte b/test/custom-elements/samples/camel-case-attribute/main.svelte index 392af5f857..0738e51607 100644 --- a/test/custom-elements/samples/camel-case-attribute/main.svelte +++ b/test/custom-elements/samples/camel-case-attribute/main.svelte @@ -2,16 +2,18 @@ tag="custom-element" cePropsDefinition={{ camelCase: { attribute: "camel-case" }, + camelCase2: { reflect: true }, anArray: { attribute: "an-array", type: "Array", reflect: true }, }} /> -

Hello {camelCase}!

+

{camelCase2} {camelCase}!

{#each anArray as item}

{item}

{/each} diff --git a/test/custom-elements/samples/camel-case-attribute/test.js b/test/custom-elements/samples/camel-case-attribute/test.js index e8933e2c1f..6a8d044cf7 100644 --- a/test/custom-elements/samples/camel-case-attribute/test.js +++ b/test/custom-elements/samples/camel-case-attribute/test.js @@ -3,24 +3,23 @@ import { tick } from 'svelte'; import './main.svelte'; export default async function (target) { - target.innerHTML = ''; + target.innerHTML = ''; await tick(); const el = target.querySelector('custom-element'); - + assert.equal(el.shadowRoot.innerHTML, '

Hello world!

1

2

'); - + el.setAttribute('camel-case', 'universe'); el.setAttribute('an-array', '[3,4]'); - assert.equal(el.shadowRoot.innerHTML, '

Hello universe!

3

4

'); - assert.equal(target.innerHTML, ''); - + el.setAttribute('camelcase2', 'Hi'); + await tick(); + assert.equal(el.shadowRoot.innerHTML, '

Hi universe!

3

4

'); + assert.equal(target.innerHTML, ''); + el.camelCase = 'galaxy'; + el.camelCase2 = 'Hey'; el.anArray = [5, 6]; - assert.equal(el.shadowRoot.innerHTML, '

Hello galaxy!

5

6

'); - assert.equal(target.innerHTML, ''); - - el.camelcase = 'solar system'; - el.anarray = [7, 8]; - assert.equal(el.shadowRoot.innerHTML, '

Hello solar system!

7

8

'); - assert.equal(target.innerHTML, ''); + await tick(); + assert.equal(el.shadowRoot.innerHTML, '

Hey galaxy!

5

6

'); + assert.equal(target.innerHTML, ''); } diff --git a/test/custom-elements/samples/props/test.js b/test/custom-elements/samples/props/test.js index e3824582e1..1f50c9be88 100644 --- a/test/custom-elements/samples/props/test.js +++ b/test/custom-elements/samples/props/test.js @@ -13,7 +13,6 @@ export default async function (target) { const widget = el.shadowRoot.querySelector('my-widget'); const [p1, p2, p3, p4] = widget.shadowRoot.querySelectorAll('p'); - console.log('goooo', !!p1, !!p2, !!p3, !!p4) assert.equal(p1.textContent, '3 items'); assert.equal(p2.textContent, 'a, b, c'); @@ -22,6 +21,7 @@ export default async function (target) { el.items = ['d', 'e', 'f', 'g', 'h']; el.flagged = true; + await tick(); assert.equal(p1.textContent, '5 items'); assert.equal(p2.textContent, 'd, e, f, g, h');