fix(ivy): support schemas at runtime (#28637)

Accounts for schemas in when validating properties in Ivy.

This PR resolves FW-819.

A couple of notes:
* I had to rework the test slightly, in order to have it fail when we expect it to. The one in master is passing since Ivy's validation runs during the update phase, rather than creation.
* I had to deviate from the design in FW-819 and not add an `enableSchema` instruction, because the schema is part of the `NgModule` scope, however the scope is only assigned to a component once all of the module's declarations have been resolved and some of them can be async. Instead, I opted to have the `schemas` on the component definition.

PR Close #28637
This commit is contained in:
Kristiyan Kostadinov
2019-02-12 00:03:04 +01:00
committed by Miško Hevery
parent 7cbc36fdac
commit 80a5934af6
18 changed files with 162 additions and 76 deletions

View File

@ -97,6 +97,7 @@ export interface R3NgModuleMetadataFacade {
imports: Function[];
exports: Function[];
emitInline: boolean;
schemas: {name: string}[]|null;
}
export interface R3InjectorMetadataFacade {
@ -155,4 +156,4 @@ export interface ParseSourceSpan {
start: any;
end: any;
details: any;
}
}

View File

@ -86,6 +86,7 @@ export class CompilerFacadeImpl implements CompilerFacade {
imports: facade.imports.map(wrapReference),
exports: facade.exports.map(wrapReference),
emitInline: true,
schemas: facade.schemas ? facade.schemas.map(wrapReference) : null,
};
const res = compileNgModule(meta);
return this.jitExpression(res.expression, angularCoreEnv, sourceMapUrl, []);

View File

@ -57,13 +57,18 @@ export interface R3NgModuleMetadata {
* does not allow components to be tree-shaken, but is useful for JIT mode.
*/
emitInline: boolean;
/**
* The set of schemas that declare elements to be allowed in the NgModule.
*/
schemas: R3Reference[]|null;
}
/**
* Construct an `R3NgModuleDef` for the given `R3NgModuleMetadata`.
*/
export function compileNgModule(meta: R3NgModuleMetadata): R3NgModuleDef {
const {type: moduleType, bootstrap, declarations, imports, exports} = meta;
const {type: moduleType, bootstrap, declarations, imports, exports, schemas} = meta;
const definitionMap = {
type: moduleType
} as{
@ -71,7 +76,8 @@ export function compileNgModule(meta: R3NgModuleMetadata): R3NgModuleDef {
bootstrap: o.LiteralArrayExpr,
declarations: o.LiteralArrayExpr,
imports: o.LiteralArrayExpr,
exports: o.LiteralArrayExpr
exports: o.LiteralArrayExpr,
schemas: o.LiteralArrayExpr
};
// Only generate the keys in the metadata if the arrays have values.
@ -91,6 +97,10 @@ export function compileNgModule(meta: R3NgModuleMetadata): R3NgModuleDef {
definitionMap.exports = o.literalArr(exports.map(ref => ref.value));
}
if (schemas && schemas.length) {
definitionMap.schemas = o.literalArr(schemas.map(ref => ref.value));
}
const expression = o.importExpr(R3.defineNgModule).callFn([mapToMapExpression(definitionMap)]);
const type = new o.ExpressionType(o.importExpr(R3.NgModuleDefWithMeta, [
new o.ExpressionType(moduleType), tupleTypeOf(declarations), tupleTypeOf(imports),