fix(ivy): make defineComponent tree shakable by Closure Compiler (#26425)
PR Close #26425
This commit is contained in:
parent
371ffef4ce
commit
4d164b6ca4
|
@ -12,7 +12,8 @@ import {ChangeDetectionStrategy} from '../change_detection/constants';
|
||||||
import {Provider} from '../di/provider';
|
import {Provider} from '../di/provider';
|
||||||
import {NgModuleDef} from '../metadata/ng_module';
|
import {NgModuleDef} from '../metadata/ng_module';
|
||||||
import {ViewEncapsulation} from '../metadata/view';
|
import {ViewEncapsulation} from '../metadata/view';
|
||||||
import {Type} from '../type';
|
import {Mutable, Type} from '../type';
|
||||||
|
import {noSideEffects} from '../util';
|
||||||
|
|
||||||
import {NG_COMPONENT_DEF, NG_DIRECTIVE_DEF, NG_MODULE_DEF, NG_PIPE_DEF} from './fields';
|
import {NG_COMPONENT_DEF, NG_DIRECTIVE_DEF, NG_MODULE_DEF, NG_PIPE_DEF} from './fields';
|
||||||
import {BaseDef, ComponentDef, ComponentDefFeature, ComponentQuery, ComponentTemplate, ComponentType, DirectiveDef, DirectiveDefFeature, DirectiveType, DirectiveTypesOrFactory, PipeDef, PipeType, PipeTypesOrFactory} from './interfaces/definition';
|
import {BaseDef, ComponentDef, ComponentDefFeature, ComponentQuery, ComponentTemplate, ComponentType, DirectiveDef, DirectiveDefFeature, DirectiveType, DirectiveTypesOrFactory, PipeDef, PipeType, PipeTypesOrFactory} from './interfaces/definition';
|
||||||
|
@ -265,13 +266,9 @@ export function defineComponent<T>(componentDefinition: {
|
||||||
pipes?: PipeTypesOrFactory | null;
|
pipes?: PipeTypesOrFactory | null;
|
||||||
}): never {
|
}): never {
|
||||||
const type = componentDefinition.type;
|
const type = componentDefinition.type;
|
||||||
const pipeTypes = componentDefinition.pipes !;
|
const typePrototype = type.prototype;
|
||||||
const directiveTypes = componentDefinition.directives !;
|
|
||||||
const declaredInputs: {[key: string]: string} = {} as any;
|
const declaredInputs: {[key: string]: string} = {} as any;
|
||||||
const encapsulation = componentDefinition.encapsulation || ViewEncapsulation.Emulated;
|
const def: Mutable<ComponentDef<any>, keyof ComponentDef<any>> = {
|
||||||
const styles: string[] = componentDefinition.styles || EMPTY_ARRAY;
|
|
||||||
const data = componentDefinition.data || {};
|
|
||||||
const def: ComponentDef<any> = {
|
|
||||||
type: type,
|
type: type,
|
||||||
diPublic: null,
|
diPublic: null,
|
||||||
consts: componentDefinition.consts,
|
consts: componentDefinition.consts,
|
||||||
|
@ -283,38 +280,49 @@ export function defineComponent<T>(componentDefinition: {
|
||||||
contentQueries: componentDefinition.contentQueries || null,
|
contentQueries: componentDefinition.contentQueries || null,
|
||||||
contentQueriesRefresh: componentDefinition.contentQueriesRefresh || null,
|
contentQueriesRefresh: componentDefinition.contentQueriesRefresh || null,
|
||||||
attributes: componentDefinition.attributes || null,
|
attributes: componentDefinition.attributes || null,
|
||||||
inputs: invertObject(componentDefinition.inputs, declaredInputs),
|
|
||||||
declaredInputs: declaredInputs,
|
declaredInputs: declaredInputs,
|
||||||
outputs: invertObject(componentDefinition.outputs),
|
inputs: null !, // assigned in noSideEffects
|
||||||
|
outputs: null !, // assigned in noSideEffects
|
||||||
exportAs: componentDefinition.exportAs || null,
|
exportAs: componentDefinition.exportAs || null,
|
||||||
onInit: type.prototype.ngOnInit || null,
|
onInit: typePrototype.ngOnInit || null,
|
||||||
doCheck: type.prototype.ngDoCheck || null,
|
doCheck: typePrototype.ngDoCheck || null,
|
||||||
afterContentInit: type.prototype.ngAfterContentInit || null,
|
afterContentInit: typePrototype.ngAfterContentInit || null,
|
||||||
afterContentChecked: type.prototype.ngAfterContentChecked || null,
|
afterContentChecked: typePrototype.ngAfterContentChecked || null,
|
||||||
afterViewInit: type.prototype.ngAfterViewInit || null,
|
afterViewInit: typePrototype.ngAfterViewInit || null,
|
||||||
afterViewChecked: type.prototype.ngAfterViewChecked || null,
|
afterViewChecked: typePrototype.ngAfterViewChecked || null,
|
||||||
onDestroy: type.prototype.ngOnDestroy || null,
|
onDestroy: typePrototype.ngOnDestroy || null,
|
||||||
onPush: componentDefinition.changeDetection === ChangeDetectionStrategy.OnPush,
|
onPush: componentDefinition.changeDetection === ChangeDetectionStrategy.OnPush,
|
||||||
directiveDefs: directiveTypes ?
|
directiveDefs: null !, // assigned in noSideEffects
|
||||||
() => (typeof directiveTypes === 'function' ? directiveTypes() : directiveTypes)
|
pipeDefs: null !, // assigned in noSideEffects
|
||||||
.map(extractDirectiveDef) :
|
|
||||||
null,
|
|
||||||
pipeDefs: pipeTypes ?
|
|
||||||
() => (typeof pipeTypes === 'function' ? pipeTypes() : pipeTypes).map(extractPipeDef) :
|
|
||||||
null,
|
|
||||||
selectors: componentDefinition.selectors,
|
selectors: componentDefinition.selectors,
|
||||||
viewQuery: componentDefinition.viewQuery || null,
|
viewQuery: componentDefinition.viewQuery || null,
|
||||||
features: componentDefinition.features || null,
|
features: componentDefinition.features || null,
|
||||||
data,
|
data: componentDefinition.data || {},
|
||||||
// TODO(misko): convert ViewEncapsulation into const enum so that it can be used directly in the
|
// TODO(misko): convert ViewEncapsulation into const enum so that it can be used directly in the
|
||||||
// next line. Also `None` should be 0 not 2.
|
// next line. Also `None` should be 0 not 2.
|
||||||
encapsulation,
|
encapsulation: componentDefinition.encapsulation || ViewEncapsulation.Emulated,
|
||||||
providers: EMPTY_ARRAY,
|
providers: EMPTY_ARRAY,
|
||||||
viewProviders: EMPTY_ARRAY,
|
viewProviders: EMPTY_ARRAY,
|
||||||
id: `c${_renderCompCount++}`, styles,
|
id: 'c',
|
||||||
|
styles: componentDefinition.styles || EMPTY_ARRAY,
|
||||||
|
_: null as never,
|
||||||
};
|
};
|
||||||
|
def._ = noSideEffects(() => {
|
||||||
|
const directiveTypes = componentDefinition.directives !;
|
||||||
const feature = componentDefinition.features;
|
const feature = componentDefinition.features;
|
||||||
|
const pipeTypes = componentDefinition.pipes !;
|
||||||
|
def.id += _renderCompCount++;
|
||||||
|
def.inputs = invertObject(componentDefinition.inputs, declaredInputs),
|
||||||
|
def.outputs = invertObject(componentDefinition.outputs),
|
||||||
feature && feature.forEach((fn) => fn(def));
|
feature && feature.forEach((fn) => fn(def));
|
||||||
|
def.directiveDefs = directiveTypes ?
|
||||||
|
() => (typeof directiveTypes === 'function' ? directiveTypes() : directiveTypes)
|
||||||
|
.map(extractDirectiveDef) :
|
||||||
|
null;
|
||||||
|
def.pipeDefs = pipeTypes ?
|
||||||
|
() => (typeof pipeTypes === 'function' ? pipeTypes() : pipeTypes).map(extractPipeDef) :
|
||||||
|
null;
|
||||||
|
}) as never;
|
||||||
return def as never;
|
return def as never;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -190,7 +190,7 @@ export interface ComponentDef<T> extends DirectiveDef<T> {
|
||||||
/**
|
/**
|
||||||
* Runtime unique component ID.
|
* Runtime unique component ID.
|
||||||
*/
|
*/
|
||||||
id: string;
|
readonly id: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The View template of the component.
|
* The View template of the component.
|
||||||
|
@ -209,7 +209,7 @@ export interface ComponentDef<T> extends DirectiveDef<T> {
|
||||||
* can pre-fill the array and set the binding start index.
|
* can pre-fill the array and set the binding start index.
|
||||||
*/
|
*/
|
||||||
// TODO(kara): remove queries from this count
|
// TODO(kara): remove queries from this count
|
||||||
consts: number;
|
readonly consts: number;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The number of bindings in this component template (including pure fn bindings).
|
* The number of bindings in this component template (including pure fn bindings).
|
||||||
|
@ -217,7 +217,7 @@ export interface ComponentDef<T> extends DirectiveDef<T> {
|
||||||
* Used to calculate the length of the component's LViewData array, so we
|
* Used to calculate the length of the component's LViewData array, so we
|
||||||
* can pre-fill the array and set the host binding start index.
|
* can pre-fill the array and set the host binding start index.
|
||||||
*/
|
*/
|
||||||
vars: number;
|
readonly vars: number;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Query-related instructions for a component.
|
* Query-related instructions for a component.
|
||||||
|
@ -271,6 +271,12 @@ export interface ComponentDef<T> extends DirectiveDef<T> {
|
||||||
* `PipeDefs`s. The function is necessary to be able to support forward declarations.
|
* `PipeDefs`s. The function is necessary to be able to support forward declarations.
|
||||||
*/
|
*/
|
||||||
pipeDefs: PipeDefListOrFactory|null;
|
pipeDefs: PipeDefListOrFactory|null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to store the result of `noSideEffects` function so that it is not removed by closure
|
||||||
|
* compiler. The property should never be read.
|
||||||
|
*/
|
||||||
|
readonly _?: never;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -23,3 +23,7 @@ export function isType(v: any): v is Type<any> {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Type<T> extends Function { new (...args: any[]): T; }
|
export interface Type<T> extends Function { new (...args: any[]): T; }
|
||||||
|
|
||||||
|
export type Mutable<T extends{[x: string]: any}, K extends string> = {
|
||||||
|
[P in K]: T[P];
|
||||||
|
};
|
||||||
|
|
|
@ -96,3 +96,16 @@ export function stringify(token: any): string {
|
||||||
const newLineIndex = res.indexOf('\n');
|
const newLineIndex = res.indexOf('\n');
|
||||||
return newLineIndex === -1 ? res : res.substring(0, newLineIndex);
|
return newLineIndex === -1 ? res : res.substring(0, newLineIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convince closure compiler that the wrapped function has no side-effects.
|
||||||
|
*
|
||||||
|
* Closure compiler always assumes that `toString` has no side-effects. We use this quirk to
|
||||||
|
* allow us to execute a function but have closure compiler mark the call as no-side-effects.
|
||||||
|
* It is important that the return value for the `noSideEffects` function be assigned
|
||||||
|
* to something which is retained otherwise the call to `noSideEffects` will be removed by closure
|
||||||
|
* compiler.
|
||||||
|
*/
|
||||||
|
export function noSideEffects(fn: () => void): string {
|
||||||
|
return '' + {toString: fn};
|
||||||
|
}
|
|
@ -827,6 +827,9 @@
|
||||||
{
|
{
|
||||||
"name": "nextNgElementId"
|
"name": "nextNgElementId"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "noSideEffects"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "pointers"
|
"name": "pointers"
|
||||||
},
|
},
|
||||||
|
|
|
@ -308,6 +308,9 @@
|
||||||
{
|
{
|
||||||
"name": "nextNgElementId"
|
"name": "nextNgElementId"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "noSideEffects"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "prefillHostVars"
|
"name": "prefillHostVars"
|
||||||
},
|
},
|
||||||
|
|
|
@ -854,6 +854,9 @@
|
||||||
{
|
{
|
||||||
"name": "nextNgElementId"
|
"name": "nextNgElementId"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "noSideEffects"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "pointers"
|
"name": "pointers"
|
||||||
},
|
},
|
||||||
|
|
|
@ -2120,6 +2120,9 @@
|
||||||
{
|
{
|
||||||
"name": "noComponentFactoryError"
|
"name": "noComponentFactoryError"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "noSideEffects"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "noop$1"
|
"name": "noop$1"
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in New Issue