Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 42 additions & 21 deletions packages/compiler/src/jit_compiler_facade.ts
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,25 @@ function convertDirectiveFacadeToMetadata(facade: R3DirectiveMetadataFacade): R3
}
}

const hostDirectives = facade.hostDirectives?.length ?
facade.hostDirectives.map((hostDirective) => {
return typeof hostDirective === 'function' ?
{
directive: wrapReference(hostDirective),
inputs: null,
outputs: null,
isForwardReference: false,
} :
{
directive: wrapReference(hostDirective.directive),
isForwardReference: false,
inputs: hostDirective.inputs ? parseMappingStringArray(hostDirective.inputs) : null,
outputs: hostDirective.outputs ? parseMappingStringArray(hostDirective.outputs) :
null,
};
}) :
null;

return {
...facade,
typeArgumentCount: 0,
Expand All @@ -368,12 +387,22 @@ function convertDirectiveFacadeToMetadata(facade: R3DirectiveMetadataFacade): R3
providers: facade.providers != null ? new WrappedNodeExpr(facade.providers) : null,
viewQueries: facade.viewQueries.map(convertToR3QueryMetadata),
fullInheritance: false,
hostDirectives: convertHostDirectivesToMetadata(facade),
hostDirectives,
};
}

function convertDeclareDirectiveFacadeToMetadata(
declaration: R3DeclareDirectiveFacade, typeSourceSpan: ParseSourceSpan): R3DirectiveMetadata {
const hostDirectives = declaration.hostDirectives?.length ?
declaration.hostDirectives.map(
(dir) => ({
directive: wrapReference(dir.directive),
isForwardReference: false,
inputs: dir.inputs ? getHostDirectiveBindingMapping(dir.inputs) : null,
outputs: dir.outputs ? getHostDirectiveBindingMapping(dir.outputs) : null,
})) :
null;

return {
name: declaration.type.name,
type: wrapReference(declaration.type),
Expand All @@ -394,7 +423,7 @@ function convertDeclareDirectiveFacadeToMetadata(
fullInheritance: false,
isStandalone: declaration.isStandalone ?? false,
isSignal: declaration.isSignal ?? false,
hostDirectives: convertHostDirectivesToMetadata(declaration),
hostDirectives,
};
}

Expand All @@ -412,27 +441,19 @@ function convertHostDeclarationToMetadata(host: R3DeclareDirectiveFacade['host']
};
}

function convertHostDirectivesToMetadata(
metadata: R3DeclareDirectiveFacade|R3DirectiveMetadataFacade): R3HostDirectiveMetadata[]|null {
if (metadata.hostDirectives?.length) {
return metadata.hostDirectives.map(hostDirective => {
return typeof hostDirective === 'function' ?
{
directive: wrapReference(hostDirective),
inputs: null,
outputs: null,
isForwardReference: false
} :
{
directive: wrapReference(hostDirective.directive),
isForwardReference: false,
inputs: hostDirective.inputs ? parseMappingStringArray(hostDirective.inputs) : null,
outputs: hostDirective.outputs ? parseMappingStringArray(hostDirective.outputs) : null,
};
});
/*
* Parses a host directive mapping where each odd array key is the name of an input/output
* and each even key is its public name, e.g. `['one', 'oneAlias', 'two', 'two']`.
*/
function getHostDirectiveBindingMapping(array: string[]) {
let result: {[publicName: string]: string}|null = null;

for (let i = 1; i < array.length; i += 2) {
result = result || {};
result[array[i - 1]] = array[i];
}

return null;
return result;
}

function convertOpaqueValuesToExpressions(obj: {[key: string]: OpaqueValue}):
Expand Down
47 changes: 45 additions & 2 deletions packages/core/test/render3/jit/declare_directive_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -250,12 +250,53 @@ describe('directive declaration jit compilation', () => {
features: [ɵɵNgOnChangesFeature],
});
});

it('should compile host directives', () => {
class One {}
class Two {}

const def = ɵɵngDeclareDirective({
type: TestClass,
hostDirectives: [
{
directive: One,
inputs: ['firstInput', 'firstInput', 'secondInput', 'secondInputAlias'],
outputs: ['firstOutput', 'firstOutput', 'secondOutput', 'secondOutputAlias']
},
{
directive: Two,
},
]
}) as DirectiveDef<TestClass>;

expectDirectiveDef(def, {
features: [jasmine.any(Function)],
hostDirectives: [
{
directive: One,
inputs: {
'firstInput': 'firstInput',
'secondInput': 'secondInputAlias',
},
outputs: {
'firstOutput': 'firstOutput',
'secondOutput': 'secondOutputAlias',
},
},
{
directive: Two,
inputs: {},
outputs: {},
},
],
});
});
});

type DirectiveDefExpectations = jasmine.Expected<Pick<
DirectiveDef<unknown>,
'selectors'|'inputs'|'declaredInputs'|'outputs'|'features'|'hostAttrs'|'hostBindings'|
'hostVars'|'contentQueries'|'viewQuery'|'exportAs'|'providersResolver'>>;
|'selectors'|'inputs'|'declaredInputs'|'outputs'|'features'|'hostAttrs'|'hostBindings'|
'hostVars'|'contentQueries'|'viewQuery'|'exportAs'|'providersResolver'|'hostDirectives'>>;

/**
* Asserts that the provided directive definition is according to the provided expectation.
Expand All @@ -277,6 +318,7 @@ function expectDirectiveDef(
viewQuery: null,
exportAs: null,
providersResolver: null,
hostDirectives: null,
...expected,
};

Expand All @@ -295,6 +337,7 @@ function expectDirectiveDef(
expect(actual.providersResolver)
.withContext('providersResolver')
.toEqual(expectation.providersResolver);
expect(actual.hostDirectives).withContext('hostDirectives').toEqual(expectation.hostDirectives);
}

class TestClass {}