diff --git a/src/compiler/compile/render_dom/wrappers/Element/Attribute.ts b/src/compiler/compile/render_dom/wrappers/Element/Attribute.ts
index c8cc7c8443..3f57d004be 100644
--- a/src/compiler/compile/render_dom/wrappers/Element/Attribute.ts
+++ b/src/compiler/compile/render_dom/wrappers/Element/Attribute.ts
@@ -86,8 +86,9 @@ export default class AttributeWrapper extends BaseAttributeWrapper {
this.is_select_value_attribute = this.name === 'value' && this.parent.node.name === 'select';
this.is_input_value = this.name === 'value' && this.parent.node.name === 'input';
}
-
- this.is_src = this.name === 'src'; // TODO retire this exception in favour of https://github.com/sveltejs/svelte/issues/3750
+
+ // TODO retire this exception in favour of https://github.com/sveltejs/svelte/issues/3750
+ this.is_src = this.name === 'src' && (!this.parent.node.namespace || this.parent.node.namespace === namespaces.html);
this.should_cache = should_cache(this);
}
diff --git a/src/runtime/internal/dom.ts b/src/runtime/internal/dom.ts
index 2aef1c7f28..eb3389e3f8 100644
--- a/src/runtime/internal/dom.ts
+++ b/src/runtime/internal/dom.ts
@@ -148,7 +148,7 @@ export function get_root_for_style(node: Node): ShadowRoot | Document {
if (!node) return document;
const root = node.getRootNode ? node.getRootNode() : node.ownerDocument;
- if ((root as ShadowRoot).host) {
+ if (root && (root as ShadowRoot).host) {
return root as ShadowRoot;
}
return node.ownerDocument;
diff --git a/test/js/samples/src-attribute-check-in-foreign/_config.js b/test/js/samples/src-attribute-check-in-foreign/_config.js
new file mode 100644
index 0000000000..af1bf11a52
--- /dev/null
+++ b/test/js/samples/src-attribute-check-in-foreign/_config.js
@@ -0,0 +1,5 @@
+export default {
+ options: {
+ hydratable: true
+ }
+};
diff --git a/test/js/samples/src-attribute-check-in-foreign/expected.js b/test/js/samples/src-attribute-check-in-foreign/expected.js
new file mode 100644
index 0000000000..3d781b72d4
--- /dev/null
+++ b/test/js/samples/src-attribute-check-in-foreign/expected.js
@@ -0,0 +1,70 @@
+/* generated by Svelte vX.Y.Z */
+import {
+ SvelteComponent,
+ append_hydration,
+ attr,
+ children,
+ claim_element,
+ detach,
+ init,
+ insert_hydration,
+ noop,
+ safe_not_equal
+} from "svelte/internal";
+
+function create_fragment(ctx) {
+ let svg;
+ let img;
+
+ return {
+ c() {
+ svg = document.createElementNS("https://svelte.dev/docs#svelte_options", "svg");
+ img = document.createElementNS("https://svelte.dev/docs#svelte_options", "img");
+ this.h();
+ },
+ l(nodes) {
+ svg = claim_element(nodes, "svg", {});
+ var svg_nodes = children(svg);
+ img = claim_element(svg_nodes, "img", { alt: true, src: true });
+ svg_nodes.forEach(detach);
+ this.h();
+ },
+ h() {
+ attr(img, "alt", "potato");
+ attr(img, "src", /*url*/ ctx[0]);
+ },
+ m(target, anchor) {
+ insert_hydration(target, svg, anchor);
+ append_hydration(svg, img);
+ },
+ p(ctx, [dirty]) {
+ if (dirty & /*url*/ 1) {
+ attr(img, "src", /*url*/ ctx[0]);
+ }
+ },
+ i: noop,
+ o: noop,
+ d(detaching) {
+ if (detaching) detach(svg);
+ }
+ };
+}
+
+function instance($$self, $$props, $$invalidate) {
+ let { url } = $$props;
+
+ $$self.$$set = $$props => {
+ if ('url' in $$props) $$invalidate(0, url = $$props.url);
+ };
+
+ return [url];
+}
+
+class Component extends SvelteComponent {
+ constructor(options) {
+ super();
+ init(this, options, instance, create_fragment, safe_not_equal, { url: 0 });
+ }
+}
+
+export default Component;
diff --git a/test/js/samples/src-attribute-check-in-foreign/input.svelte b/test/js/samples/src-attribute-check-in-foreign/input.svelte
new file mode 100644
index 0000000000..6d04f0fa55
--- /dev/null
+++ b/test/js/samples/src-attribute-check-in-foreign/input.svelte
@@ -0,0 +1,9 @@
+
+
+
+
+
diff --git a/test/js/samples/src-attribute-check-in-svg/_config.js b/test/js/samples/src-attribute-check-in-svg/_config.js
new file mode 100644
index 0000000000..af1bf11a52
--- /dev/null
+++ b/test/js/samples/src-attribute-check-in-svg/_config.js
@@ -0,0 +1,5 @@
+export default {
+ options: {
+ hydratable: true
+ }
+};
diff --git a/test/js/samples/src-attribute-check-in-svg/expected.js b/test/js/samples/src-attribute-check-in-svg/expected.js
new file mode 100644
index 0000000000..efcb1c7064
--- /dev/null
+++ b/test/js/samples/src-attribute-check-in-svg/expected.js
@@ -0,0 +1,71 @@
+/* generated by Svelte vX.Y.Z */
+import {
+ SvelteComponent,
+ append_hydration,
+ attr,
+ children,
+ claim_element,
+ detach,
+ init,
+ insert_hydration,
+ noop,
+ safe_not_equal,
+ svg_element
+} from "svelte/internal";
+
+function create_fragment(ctx) {
+ let svg;
+ let img;
+
+ return {
+ c() {
+ svg = svg_element("svg");
+ img = svg_element("img");
+ this.h();
+ },
+ l(nodes) {
+ svg = claim_element(nodes, "svg", {}, 1);
+ var svg_nodes = children(svg);
+ img = claim_element(svg_nodes, "img", { alt: true, src: true }, 1);
+ svg_nodes.forEach(detach);
+ this.h();
+ },
+ h() {
+ attr(img, "alt", "potato");
+ attr(img, "src", /*url*/ ctx[0]);
+ },
+ m(target, anchor) {
+ insert_hydration(target, svg, anchor);
+ append_hydration(svg, img);
+ },
+ p(ctx, [dirty]) {
+ if (dirty & /*url*/ 1) {
+ attr(img, "src", /*url*/ ctx[0]);
+ }
+ },
+ i: noop,
+ o: noop,
+ d(detaching) {
+ if (detaching) detach(svg);
+ }
+ };
+}
+
+function instance($$self, $$props, $$invalidate) {
+ let { url } = $$props;
+
+ $$self.$$set = $$props => {
+ if ('url' in $$props) $$invalidate(0, url = $$props.url);
+ };
+
+ return [url];
+}
+
+class Component extends SvelteComponent {
+ constructor(options) {
+ super();
+ init(this, options, instance, create_fragment, safe_not_equal, { url: 0 });
+ }
+}
+
+export default Component;
diff --git a/test/js/samples/src-attribute-check-in-svg/input.svelte b/test/js/samples/src-attribute-check-in-svg/input.svelte
new file mode 100644
index 0000000000..05dbc37608
--- /dev/null
+++ b/test/js/samples/src-attribute-check-in-svg/input.svelte
@@ -0,0 +1,7 @@
+
+
+