From 6469f9d08903f437590d5adf5b8e3777d0e8afa6 Mon Sep 17 00:00:00 2001 From: Tan Li Hau Date: Thu, 29 Oct 2020 00:59:02 +0800 Subject: [PATCH] support $$props and $$restProps for custom elements --- src/compiler/compile/render_dom/index.ts | 2 +- src/runtime/internal/dom.ts | 8 +++++++ test/custom-elements/assert.js | 21 +++++++++++++++++++ .../samples/$$props/main.svelte | 10 +++++++++ test/custom-elements/samples/$$props/test.js | 13 ++++++++++++ 5 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 test/custom-elements/samples/$$props/main.svelte create mode 100644 test/custom-elements/samples/$$props/test.js diff --git a/src/compiler/compile/render_dom/index.ts b/src/compiler/compile/render_dom/index.ts index 6380843b8712..024aafde14a0 100644 --- a/src/compiler/compile/render_dom/index.ts +++ b/src/compiler/compile/render_dom/index.ts @@ -474,7 +474,7 @@ export default function dom( ${css.code && b`this.shadowRoot.innerHTML = \`\`;`} - @init(this, { target: this.shadowRoot }, ${definition}, ${has_create_fragment ? 'create_fragment': 'null'}, ${not_equal}, ${prop_indexes}, ${dirty}); + @init(this, { target: this.shadowRoot, props: @attribute_to_object(this.attributes) }, ${definition}, ${has_create_fragment ? 'create_fragment': 'null'}, ${not_equal}, ${prop_indexes}, ${dirty}); ${dev_props_check} diff --git a/src/runtime/internal/dom.ts b/src/runtime/internal/dom.ts index 5380443fbc0a..830bc6abd186 100644 --- a/src/runtime/internal/dom.ts +++ b/src/runtime/internal/dom.ts @@ -360,3 +360,11 @@ export class HtmlTag { this.n.forEach(detach); } } + +export function attribute_to_object(attributes) { + const result = {}; + for (const attribute of attributes) { + result[attribute.name] = attribute.value; + } + return result; +} \ No newline at end of file diff --git a/test/custom-elements/assert.js b/test/custom-elements/assert.js index b8add0dadc22..474c314da983 100644 --- a/test/custom-elements/assert.js +++ b/test/custom-elements/assert.js @@ -31,3 +31,24 @@ export function equal(a, b, message) { export function ok(condition, message) { if (!condition) throw new Error(message || `Expected ${condition} to be truthy`); } + +export function htmlEqual(actual, expected, message) { + return deepEqual( + normalizeHtml(window, actual), + normalizeHtml(window, expected), + message + ); +} + +function normalizeHtml(window, html) { + try { + const node = window.document.createElement('div'); + node.innerHTML = html + .replace(//g, '') + .replace(/>[\s\r\n]+<') + .trim(); + return node.innerHTML.replace(/<\/?noscript\/?>/g, ''); + } catch (err) { + throw new Error(`Failed to normalize HTML:\n${html}`); + } +} \ No newline at end of file diff --git a/test/custom-elements/samples/$$props/main.svelte b/test/custom-elements/samples/$$props/main.svelte new file mode 100644 index 000000000000..68931e22db79 --- /dev/null +++ b/test/custom-elements/samples/$$props/main.svelte @@ -0,0 +1,10 @@ + + + + +

name: {name}

+

$$props: {JSON.stringify($$props)}

+

$$restProps: {JSON.stringify($$restProps)}

+ diff --git a/test/custom-elements/samples/$$props/test.js b/test/custom-elements/samples/$$props/test.js new file mode 100644 index 000000000000..94cad865778c --- /dev/null +++ b/test/custom-elements/samples/$$props/test.js @@ -0,0 +1,13 @@ +import * as assert from 'assert'; +import './main.svelte'; + +export default function (target) { + target.innerHTML = ''; + const el = target.querySelector('custom-element'); + + assert.htmlEqual(el.shadowRoot.innerHTML, ` +

name: world

+

$$props: {"name":"world","answer":"42","test":"svelte"}

+

$$restProps: {"answer":"42","test":"svelte"}

+ `); +}