Skip to content
Permalink
Browse files

fix(ivy): incorrectly validating html foreign objects inside svg (#34178

)

Fixes ngtsc incorrectly logging an unknown element diagnostic for HTML elements that are inside an SVG `foreignObject` with the `xhtml` namespace.

Fixes #34171.

PR Close #34178
  • Loading branch information
crisbeto authored and mhevery committed Dec 2, 2019
1 parent 1bab8c2 commit 4836fe08b5ae1d8f38fe6daa3c6575835d769ee5
@@ -14,6 +14,7 @@ import {ErrorCode} from '../../diagnostics';
import {TcbSourceResolver, makeTemplateDiagnostic} from './diagnostics';

const REGISTRY = new DomElementSchemaRegistry();
const REMOVE_XHTML_REGEX = /^:xhtml:/;

/**
* Checks every non-Angular element/property processed in a template and potentially produces
@@ -69,15 +70,20 @@ export class RegistryDomSchemaChecker implements DomSchemaChecker {
constructor(private resolver: TcbSourceResolver) {}

checkElement(id: string, element: TmplAstElement, schemas: SchemaMetadata[]): void {
if (!REGISTRY.hasElement(element.name, schemas)) {
// HTML elements inside an SVG `foreignObject` are declared in the `xhtml` namespace.
// We need to strip it before handing it over to the registry because all HTML tag names
// in the registry are without a namespace.
const name = element.name.replace(REMOVE_XHTML_REGEX, '');

if (!REGISTRY.hasElement(name, schemas)) {
const mapping = this.resolver.getSourceMapping(id);

let errorMsg = `'${element.name}' is not a known element:\n`;
let errorMsg = `'${name}' is not a known element:\n`;
errorMsg +=
`1. If '${element.name}' is an Angular component, then verify that it is part of this module.\n`;
if (element.name.indexOf('-') > -1) {
`1. If '${name}' is an Angular component, then verify that it is part of this module.\n`;
if (name.indexOf('-') > -1) {
errorMsg +=
`2. If '${element.name}' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '@NgModule.schemas' of this component to suppress this message.`;
`2. If '${name}' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '@NgModule.schemas' of this component to suppress this message.`;
} else {
errorMsg +=
`2. To allow any element add 'NO_ERRORS_SCHEMA' to the '@NgModule.schemas' of this component.`;
@@ -1362,6 +1362,55 @@ export declare class AnimationEvent {
const diags = env.driveDiagnostics();
expect(diags).toEqual([]);
});

it('should allow HTML elements inside SVG foreignObject', () => {
env.write('test.ts', `
import {Component, NgModule} from '@angular/core';
@Component({
selector: 'blah',
template: \`
<svg>
<svg:foreignObject>
<xhtml:div>Hello</xhtml:div>
</svg:foreignObject>
</svg>
\`,
})
export class FooCmp {}
@NgModule({
declarations: [FooCmp],
})
export class FooModule {}
`);
const diags = env.driveDiagnostics();
expect(diags.length).toBe(0);
});

it('should check for unknown elements inside an SVG foreignObject', () => {
env.write('test.ts', `
import {Component, NgModule} from '@angular/core';
@Component({
selector: 'blah',
template: \`
<svg>
<svg:foreignObject>
<xhtml:foo>Hello</xhtml:foo>
</svg:foreignObject>
</svg>
\`,
})
export class FooCmp {}
@NgModule({
declarations: [FooCmp],
})
export class FooModule {}
`);
const diags = env.driveDiagnostics();
expect(diags.length).toBe(1);
expect(diags[0].messageText).toBe(`'foo' is not a known element:
1. If 'foo' is an Angular component, then verify that it is part of this module.
2. To allow any element add 'NO_ERRORS_SCHEMA' to the '@NgModule.schemas' of this component.`);
});
});

// Test both sync and async compilations, see https://github.com/angular/angular/issues/32538
@@ -311,5 +311,30 @@ describe('NgModule', () => {
}).not.toThrow();
});

it('should not throw for HTML elements inside an SVG foreignObject', () => {
@Component({
template: `
<svg>
<svg:foreignObject>
<xhtml:div>Hello</xhtml:div>
</svg:foreignObject>
</svg>
`,
})
class MyComp {
}

@NgModule({declarations: [MyComp]})
class MyModule {
}

TestBed.configureTestingModule({imports: [MyModule]});

expect(() => {
const fixture = TestBed.createComponent(MyComp);
fixture.detectChanges();
}).not.toThrow();
});

});
});

0 comments on commit 4836fe0

Please sign in to comment.
You can’t perform that action at this time.