diff --git a/src/compiler/compile/Component.ts b/src/compiler/compile/Component.ts index 355ad0c423b9..d4d4d33790e6 100644 --- a/src/compiler/compile/Component.ts +++ b/src/compiler/compile/Component.ts @@ -179,7 +179,7 @@ export default class Component { this.walk_instance_js_post_template(); - if (!compile_options.customElement) this.stylesheet.reify(); + if (!compile_options.shadowDom) this.stylesheet.reify(); this.stylesheet.warn_on_unused_selectors(this); } @@ -342,7 +342,7 @@ export default class Component { add_string(final_chunk); - css = compile_options.customElement ? + css = compile_options.shadowDom ? { code: null, map: null } : this.stylesheet.render(compile_options.cssOutputFilename, true); diff --git a/src/compiler/compile/index.ts b/src/compiler/compile/index.ts index 98004ba5daf1..b63dca09a192 100644 --- a/src/compiler/compile/index.ts +++ b/src/compiler/compile/index.ts @@ -22,6 +22,7 @@ const valid_options = [ 'hydratable', 'legacy', 'customElement', + 'shadowDom', 'tag', 'css', 'preserveComments', @@ -29,7 +30,7 @@ const valid_options = [ ]; function validate_options(options: CompileOptions, warnings: Warning[]) { - const { name, filename } = options; + const { name, filename, shadowDom, customElement } = options; Object.keys(options).forEach(key => { if (valid_options.indexOf(key) === -1) { @@ -54,10 +55,14 @@ function validate_options(options: CompileOptions, warnings: Warning[]) { toString: () => message, }); } + + if (!customElement && shadowDom) { + throw new Error(`options.shadowDom cannot be true if options.customElement is false`) + } } export default function compile(source: string, options: CompileOptions = {}) { - options = assign({ generate: 'dom', dev: false }, options); + options = assign({ generate: 'dom', dev: false, shadowDom: options.customElement }, options); const stats = new Stats(); const warnings = []; diff --git a/src/compiler/compile/render_ssr/index.ts b/src/compiler/compile/render_ssr/index.ts index c63bd5d45778..117824a52375 100644 --- a/src/compiler/compile/render_ssr/index.ts +++ b/src/compiler/compile/render_ssr/index.ts @@ -21,7 +21,7 @@ export default function ssr( }, options)); // TODO concatenate CSS maps - const css = options.customElement ? + const css = options.shadowDom ? { code: null, map: null } : component.stylesheet.render(options.filename, true); diff --git a/src/compiler/interfaces.ts b/src/compiler/interfaces.ts index d63194edcd93..729b8fc4de0d 100644 --- a/src/compiler/interfaces.ts +++ b/src/compiler/interfaces.ts @@ -95,6 +95,7 @@ export interface CompileOptions { hydratable?: boolean; legacy?: boolean; customElement?: boolean; + shadowDom?: boolean; tag?: string; css?: boolean; diff --git a/test/custom-elements/index.js b/test/custom-elements/index.js index 9255d33c0ef4..dc59533fefbf 100644 --- a/test/custom-elements/index.js +++ b/test/custom-elements/index.js @@ -84,7 +84,7 @@ describe('custom-elements', function() { if (id.endsWith('.svelte')) { const compiled = svelte.compile(code, { customElement: true, - dev: config.dev + ...config }); compiled.warnings.forEach(w => warnings.push(w)); diff --git a/test/custom-elements/samples/no-shadow-dom-with-slots/AsElement.svelte b/test/custom-elements/samples/no-shadow-dom-with-slots/AsElement.svelte new file mode 100644 index 000000000000..0d53cfe76637 --- /dev/null +++ b/test/custom-elements/samples/no-shadow-dom-with-slots/AsElement.svelte @@ -0,0 +1,3 @@ + + +

\ No newline at end of file diff --git a/test/custom-elements/samples/no-shadow-dom-with-slots/AsImported.svelte b/test/custom-elements/samples/no-shadow-dom-with-slots/AsImported.svelte new file mode 100644 index 000000000000..032e39256966 --- /dev/null +++ b/test/custom-elements/samples/no-shadow-dom-with-slots/AsImported.svelte @@ -0,0 +1,3 @@ + + +

\ No newline at end of file diff --git a/test/custom-elements/samples/no-shadow-dom-with-slots/_config.js b/test/custom-elements/samples/no-shadow-dom-with-slots/_config.js new file mode 100644 index 000000000000..ad44e196d783 --- /dev/null +++ b/test/custom-elements/samples/no-shadow-dom-with-slots/_config.js @@ -0,0 +1,4 @@ +export default { + customElement: true, + shadowDom: false +}; \ No newline at end of file diff --git a/test/custom-elements/samples/no-shadow-dom-with-slots/main.svelte b/test/custom-elements/samples/no-shadow-dom-with-slots/main.svelte new file mode 100644 index 000000000000..63c835d7bd74 --- /dev/null +++ b/test/custom-elements/samples/no-shadow-dom-with-slots/main.svelte @@ -0,0 +1,9 @@ + + + + +Hello +world \ No newline at end of file diff --git a/test/custom-elements/samples/no-shadow-dom-with-slots/test.js b/test/custom-elements/samples/no-shadow-dom-with-slots/test.js new file mode 100644 index 000000000000..0c15b2debc0e --- /dev/null +++ b/test/custom-elements/samples/no-shadow-dom-with-slots/test.js @@ -0,0 +1,13 @@ +import * as assert from 'assert'; +import CustomElement from './main.svelte'; + +export default function (target) { + new CustomElement({ + target + }); + + assert.equal(target.innerHTML, '

Hello

world

'); + + const el = target.querySelector('custom-element'); + assert.equal(el.innerText, "Hello world!"); +} \ No newline at end of file diff --git a/test/custom-elements/samples/no-shadow-dom/_config.js b/test/custom-elements/samples/no-shadow-dom/_config.js new file mode 100644 index 000000000000..ad44e196d783 --- /dev/null +++ b/test/custom-elements/samples/no-shadow-dom/_config.js @@ -0,0 +1,4 @@ +export default { + customElement: true, + shadowDom: false +}; \ No newline at end of file diff --git a/test/custom-elements/samples/no-shadow-dom/main.svelte b/test/custom-elements/samples/no-shadow-dom/main.svelte new file mode 100644 index 000000000000..dd5d2d515f94 --- /dev/null +++ b/test/custom-elements/samples/no-shadow-dom/main.svelte @@ -0,0 +1,9 @@ + + +

Hello world!

+ + diff --git a/test/custom-elements/samples/no-shadow-dom/test.js b/test/custom-elements/samples/no-shadow-dom/test.js new file mode 100644 index 000000000000..2d6a6de09bbe --- /dev/null +++ b/test/custom-elements/samples/no-shadow-dom/test.js @@ -0,0 +1,17 @@ +import * as assert from 'assert'; +import CustomElement from './main.svelte'; + +export default function (target) { + new CustomElement({ + target + }); + + assert.equal(target.innerHTML, '

Hello world!

'); + + const el = target.querySelector('custom-element'); + const h1 = el.querySelector('h1'); + const { color } = getComputedStyle(h1); + + assert.equal(h1.textContent, 'Hello world!'); + assert.equal(color, 'rgb(0, 0, 255)'); +} \ No newline at end of file diff --git a/test/js/samples/css-custom-element-no-shadow-dom-with-slots/AsElement.svelte b/test/js/samples/css-custom-element-no-shadow-dom-with-slots/AsElement.svelte new file mode 100644 index 000000000000..0d53cfe76637 --- /dev/null +++ b/test/js/samples/css-custom-element-no-shadow-dom-with-slots/AsElement.svelte @@ -0,0 +1,3 @@ + + +

\ No newline at end of file diff --git a/test/js/samples/css-custom-element-no-shadow-dom-with-slots/AsImport.svelte b/test/js/samples/css-custom-element-no-shadow-dom-with-slots/AsImport.svelte new file mode 100644 index 000000000000..cc19bd68f52e --- /dev/null +++ b/test/js/samples/css-custom-element-no-shadow-dom-with-slots/AsImport.svelte @@ -0,0 +1,3 @@ + + +

\ No newline at end of file diff --git a/test/js/samples/css-custom-element-no-shadow-dom-with-slots/_config.js b/test/js/samples/css-custom-element-no-shadow-dom-with-slots/_config.js new file mode 100644 index 000000000000..52d689af969b --- /dev/null +++ b/test/js/samples/css-custom-element-no-shadow-dom-with-slots/_config.js @@ -0,0 +1,6 @@ +export default { + options: { + customElement: true, + shadowDom: false + } +}; \ No newline at end of file diff --git a/test/js/samples/css-custom-element-no-shadow-dom-with-slots/expected.js b/test/js/samples/css-custom-element-no-shadow-dom-with-slots/expected.js new file mode 100644 index 000000000000..7eb038c88cb9 --- /dev/null +++ b/test/js/samples/css-custom-element-no-shadow-dom-with-slots/expected.js @@ -0,0 +1,109 @@ +/* generated by Svelte vX.Y.Z */ +import { + SvelteElement, + detach, + element, + init, + insert, + mount_component, + noop, + safe_not_equal, + space, + text +} from "svelte/internal"; +import "./AsElement.svelte"; +import AsImport from "./AsImport.svelte"; + +// (9:0) +function create_default_slot(ctx) { + var t; + + return { + c() { + t = text("world"); + }, + + m(target, anchor) { + insert(target, t, anchor); + }, + + d(detaching) { + if (detaching) { + detach(t); + } + } + }; +} + +function create_fragment(ctx) { + var as_element, t_1, current; + + var asimport = new AsImport({ + props: { + $$slots: { default: [create_default_slot] }, + $$scope: { ctx } + } + }); + + return { + c() { + as_element = element("as-element"); + as_element.textContent = "hello"; + t_1 = space(); + asimport.$$.fragment.c(); + this.c = noop; + }, + + m(target, anchor) { + insert(target, as_element, anchor); + insert(target, t_1, anchor); + mount_component(asimport, target, anchor); + current = true; + }, + + p(changed, ctx) { + var asimport_changes = {}; + if (changed.$$scope) asimport_changes.$$scope = { changed, ctx }; + asimport.$set(asimport_changes); + }, + + i(local) { + if (current) return; + asimport.$$.fragment.i(local); + + current = true; + }, + + o(local) { + asimport.$$.fragment.o(local); + current = false; + }, + + d(detaching) { + if (detaching) { + detach(as_element); + detach(t_1); + } + + asimport.$destroy(detaching); + } + }; +} + +class Component extends SvelteElement { + constructor(options) { + super({ use_shadow_dom: false }); + + init(this, { target: this }, null, create_fragment, safe_not_equal, []); + + if (options) { + if (options.target) { + insert(options.target, this, options.anchor); + } + } + } +} + +customElements.define("custom-element", Component); + +export default Component; \ No newline at end of file diff --git a/test/js/samples/css-custom-element-no-shadow-dom-with-slots/input.svelte b/test/js/samples/css-custom-element-no-shadow-dom-with-slots/input.svelte new file mode 100644 index 000000000000..ffdebd0a558a --- /dev/null +++ b/test/js/samples/css-custom-element-no-shadow-dom-with-slots/input.svelte @@ -0,0 +1,9 @@ + + + + +hello +world diff --git a/test/js/samples/css-custom-element-no-shadow-dom/_config.js b/test/js/samples/css-custom-element-no-shadow-dom/_config.js new file mode 100644 index 000000000000..52d689af969b --- /dev/null +++ b/test/js/samples/css-custom-element-no-shadow-dom/_config.js @@ -0,0 +1,6 @@ +export default { + options: { + customElement: true, + shadowDom: false + } +}; \ No newline at end of file diff --git a/test/js/samples/css-custom-element-no-shadow-dom/expected.js b/test/js/samples/css-custom-element-no-shadow-dom/expected.js new file mode 100644 index 000000000000..0591092b9941 --- /dev/null +++ b/test/js/samples/css-custom-element-no-shadow-dom/expected.js @@ -0,0 +1,64 @@ +/* generated by Svelte vX.Y.Z */ +import { + SvelteElement, + append, + detach, + element, + init, + insert, + noop, + safe_not_equal +} from "svelte/internal"; + +function add_css() { + var style = element("style"); + style.id = 'svelte-pbe34-style'; + style.textContent = "h1.svelte-pbe34{color:blue}"; + append(document.head, style); +} + +function create_fragment(ctx) { + var h1; + + return { + c() { + h1 = element("h1"); + h1.textContent = "Hello world"; + this.c = noop; + h1.className = "svelte-pbe34"; + }, + + m(target, anchor) { + insert(target, h1, anchor); + }, + + p: noop, + i: noop, + o: noop, + + d(detaching) { + if (detaching) { + detach(h1); + } + } + }; +} + +class Component extends SvelteElement { + constructor(options) { + super({ use_shadow_dom: false }); + if (!document.getElementById("svelte-pbe34-style")) add_css(); + + init(this, { target: this }, null, create_fragment, safe_not_equal, []); + + if (options) { + if (options.target) { + insert(options.target, this, options.anchor); + } + } + } +} + +customElements.define("custom-element", Component); + +export default Component; \ No newline at end of file diff --git a/test/js/samples/css-custom-element-no-shadow-dom/input.svelte b/test/js/samples/css-custom-element-no-shadow-dom/input.svelte new file mode 100644 index 000000000000..ecfe1205d9d4 --- /dev/null +++ b/test/js/samples/css-custom-element-no-shadow-dom/input.svelte @@ -0,0 +1,9 @@ + + +

Hello world

+ + \ No newline at end of file